Index rebuld and vlidation support for AVM.

Added AVM indexes to the configuration checker

git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@5818 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
Andrew Hind
2007-05-31 14:15:12 +00:00
parent 764e7b94af
commit 4bd5b0266c
8 changed files with 623 additions and 79 deletions

View File

@@ -271,6 +271,13 @@
</property> </property>
</bean> </bean>
<bean id="avmIndexRecoveryBootstrap" class="org.alfresco.repo.node.index.IndexRecoveryBootstrapBean" >
<property name="indexRecoveryComponent">
<ref bean="avmIndexRecoveryComponent"/>
</property>
</bean>
<!-- This component checks the interconnection between the metadata, indexes and content --> <!-- This component checks the interconnection between the metadata, indexes and content -->
<bean id="configurationChecker" class="org.alfresco.repo.admin.ConfigurationChecker"> <bean id="configurationChecker" class="org.alfresco.repo.admin.ConfigurationChecker">
<property name="strict"> <property name="strict">

View File

@@ -44,6 +44,22 @@
</property> </property>
</bean> </bean>
<bean
id="avmIndexRecoveryComponent"
class="org.alfresco.repo.node.index.AVMFullIndexRecoveryComponent"
parent="indexRecoveryComponentBase">
<property name="recoveryMode">
<value>${index.recovery.mode}</value>
</property>
<property name="avmService">
<ref bean="avmService" />
</property>
<property name="avmSnapShotTriggeredIndexingMethodInterceptor">
<ref bean="avmSnapShotTriggeredIndexingMethodInterceptor" />
</property>
</bean>
<!-- Bean that attempts to index content that was previously missing --> <!-- Bean that attempts to index content that was previously missing -->
<bean <bean
id="missingContentReindexComponent" id="missingContentReindexComponent"

View File

@@ -211,10 +211,10 @@ public class ConfigurationChecker extends AbstractLifecycleBean
for (StoreRef storeRef : storeRefs) for (StoreRef storeRef : storeRefs)
{ {
// TODO: For now, do not check existence of index for AVM stores // TODO: For now, do not check existence of index for AVM stores
if (storeRef.getProtocol().equals(StoreRef.PROTOCOL_AVM)) //if (storeRef.getProtocol().equals(StoreRef.PROTOCOL_AVM))
{ //{
continue; // continue;
} //}
NodeRef rootNodeRef = null; NodeRef rootNodeRef = null;
try try
@@ -237,7 +237,7 @@ public class ConfigurationChecker extends AbstractLifecycleBean
SearchParameters sp = new SearchParameters(); SearchParameters sp = new SearchParameters();
sp.addStore(storeRef); sp.addStore(storeRef);
sp.setLanguage(SearchService.LANGUAGE_LUCENE); sp.setLanguage(SearchService.LANGUAGE_LUCENE);
sp.setQuery("ID:" + LuceneQueryParser.escape(rootNodeRef.toString())); sp.setQuery("ISROOT:T");
ResultSet results = null; ResultSet results = null;
int size = 0; int size = 0;

View File

@@ -0,0 +1,218 @@
package org.alfresco.repo.node.index;
import java.util.List;
import org.alfresco.repo.node.index.FullIndexRecoveryComponent.RecoveryMode;
import org.alfresco.repo.search.AVMSnapShotTriggeredIndexingMethodInterceptor;
import org.alfresco.repo.transaction.TransactionUtil;
import org.alfresco.repo.transaction.TransactionUtil.TransactionWork;
import org.alfresco.service.cmr.avm.AVMService;
import org.alfresco.service.cmr.avm.AVMStoreDescriptor;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
/**
* Check and recover the indexes for AVM stores
*
* @author andyh
*/
public class AVMFullIndexRecoveryComponent extends AbstractReindexComponent
{
private static Log logger = LogFactory.getLog(AVMFullIndexRecoveryComponent.class);
private RecoveryMode recoveryMode;
private boolean lockServer;
private AVMService avmService;
private AVMSnapShotTriggeredIndexingMethodInterceptor avmSnapShotTriggeredIndexingMethodInterceptor;
/**
* Set the type of recovery to perform. Default is {@link RecoveryMode#VALIDATE to validate} the indexes only.
*
* @param recoveryMode
* one of the {@link RecoveryMode } values
*/
public void setRecoveryMode(String recoveryMode)
{
this.recoveryMode = RecoveryMode.valueOf(recoveryMode);
}
/**
* Set this on to put the server into READ-ONLY mode for the duration of the index recovery. The default is
* <tt>true</tt>, i.e. the server will be locked against further updates.
*
* @param lockServer
* true to force the server to be read-only
*/
public void setLockServer(boolean lockServer)
{
this.lockServer = lockServer;
}
public void setAvmService(AVMService avmService)
{
this.avmService = avmService;
}
public void setAvmSnapShotTriggeredIndexingMethodInterceptor(
AVMSnapShotTriggeredIndexingMethodInterceptor avmSnapShotTriggeredIndexingMethodInterceptor)
{
this.avmSnapShotTriggeredIndexingMethodInterceptor = avmSnapShotTriggeredIndexingMethodInterceptor;
}
@Override
protected void reindexImpl()
{
processStores();
}
private void processStores()
{
List<AVMStoreDescriptor> stores = avmService.getStores();
if(stores.size() == 0)
{
return;
}
int count = 0;
int tracker = -1;
logger.info("Checking indexes for AVM Stores");
for (AVMStoreDescriptor store : stores)
{
if (isShuttingDown())
{
return;
}
processStore(store.getName());
count++;
if (count*10l/stores.size() > tracker)
{
tracker = (int)(count*10l/stores.size());
logger.info(" Stores "+(tracker*10)+"% complete");
}
}
logger.info("Finished checking indexes for AVM Stores");
}
private void processStore(String store)
{
if (logger.isDebugEnabled())
{
logger.debug("Performing AVM index recovery for type: " + recoveryMode + " on store " + store);
}
// do we just ignore
if (recoveryMode == RecoveryMode.NONE)
{
return;
}
// check the level of cover required
boolean fullRecoveryRequired = false;
if (recoveryMode == RecoveryMode.FULL) // no validate required
{
fullRecoveryRequired = true;
}
else
// validate first
{
int lastActualSnapshotId = avmService.getLatestSnapshotID(store);
if (lastActualSnapshotId <= 0)
{
return;
}
int lastIndexedSnapshotId = avmSnapShotTriggeredIndexingMethodInterceptor.getLastIndexedSnapshot(store);
if (lastActualSnapshotId != lastIndexedSnapshotId)
{
logger.warn("Index for avm store " + store + " is out of date");
// this store isn't up to date
if (recoveryMode == RecoveryMode.VALIDATE)
{
// the store is out of date - validation failed
}
else if (recoveryMode == RecoveryMode.AUTO)
{
fullRecoveryRequired = true;
}
}
}
// put the server into read-only mode for the duration
boolean allowWrite = !transactionService.isReadOnly();
try
{
if (lockServer)
{
// set the server into read-only mode
transactionService.setAllowWrite(false);
}
// do we need to perform a full recovery
if (fullRecoveryRequired)
{
recoverStore(store);
}
}
finally
{
// restore read-only state
transactionService.setAllowWrite(allowWrite);
}
}
private void recoverStore(String store)
{
int tracker = -1;
int latest = avmService.getLatestSnapshotID(store);
if(latest <= 0)
{
return;
}
logger.info("Recovery for "+store);
if(!avmSnapShotTriggeredIndexingMethodInterceptor.hasIndexBeenCreated(store))
{
avmSnapShotTriggeredIndexingMethodInterceptor.createIndex(store);
}
for (int i = 0; i <= latest; i++)
{
if (isShuttingDown())
{
return;
}
recoverSnapShot(store, i);
if (i*10l/latest > tracker)
{
tracker = (int)(i*10l/latest);
logger.info(" Store "+store +" "+(tracker*10)+"% complete");
}
}
logger.info("Recovery for "+store+" done");
}
private void recoverSnapShot(final String store, final int id)
{
if (logger.isDebugEnabled())
{
logger.debug("Reindexing avm store: " + store + " snapshot id " + id);
}
TransactionWork<Object> reindexWork = new TransactionWork<Object>()
{
public Object doWork() throws Exception
{
if (!avmSnapShotTriggeredIndexingMethodInterceptor.isSnapshotIndexed(store, id))
{
avmSnapShotTriggeredIndexingMethodInterceptor.indexSnapshot(store, id - 1, id);
}
// done
return null;
}
};
TransactionUtil.executeInNonPropagatingUserTransaction(transactionService, reindexWork, true);
// done
}
}

View File

@@ -115,14 +115,7 @@ public class AVMSnapShotTriggeredIndexingMethodInterceptor implements MethodInte
int before = initialStates.get(store).intValue(); int before = initialStates.get(store).intValue();
if (after > before) if (after > before)
{ {
indexSnapshot(store, before, after);
StoreRef storeRef = AVMNodeConverter.ToStoreRef(store);
Indexer indexer = indexerAndSearcher.getIndexer(storeRef);
if (indexer instanceof AVMLuceneIndexer)
{
AVMLuceneIndexer avmIndexer = (AVMLuceneIndexer) indexer;
avmIndexer.index(store, before, after, getIndexMode(store));
}
} }
} }
return returnValue; return returnValue;
@@ -144,13 +137,7 @@ public class AVMSnapShotTriggeredIndexingMethodInterceptor implements MethodInte
{ {
String store = (String) mi.getArguments()[0]; String store = (String) mi.getArguments()[0];
Object returnValue = mi.proceed(); Object returnValue = mi.proceed();
StoreRef storeRef = AVMNodeConverter.ToStoreRef(store); createIndex(store);
Indexer indexer = indexerAndSearcher.getIndexer(storeRef);
if (indexer instanceof AVMLuceneIndexer)
{
AVMLuceneIndexer avmIndexer = (AVMLuceneIndexer) indexer;
avmIndexer.createIndex(store, IndexMode.SYNCHRONOUS);
}
return returnValue; return returnValue;
} }
else if (mi.getMethod().getName().equals("renameStore")) else if (mi.getMethod().getName().equals("renameStore"))
@@ -246,6 +233,63 @@ public class AVMSnapShotTriggeredIndexingMethodInterceptor implements MethodInte
this.defaultMode = defaultMode; this.defaultMode = defaultMode;
} }
/**
*
* @param store
* @param before
* @param after
*/
public void indexSnapshot(String store, int before, int after)
{
StoreRef storeRef = AVMNodeConverter.ToStoreRef(store);
Indexer indexer = indexerAndSearcher.getIndexer(storeRef);
if (indexer instanceof AVMLuceneIndexer)
{
AVMLuceneIndexer avmIndexer = (AVMLuceneIndexer) indexer;
avmIndexer.index(store, before, after, getIndexMode(store));
}
}
/**
*
* @param store
* @return
*/
public int getLastIndexedSnapshot(String store)
{
StoreRef storeRef = AVMNodeConverter.ToStoreRef(store);
Indexer indexer = indexerAndSearcher.getIndexer(storeRef);
if (indexer instanceof AVMLuceneIndexer)
{
AVMLuceneIndexer avmIndexer = (AVMLuceneIndexer) indexer;
return avmIndexer.getLastIndexedSnapshot(store);
}
return -1;
}
/**
* Is the snapshot applied to the index?
*
* Is there an entry for any node that was added OR have all the nodes in the transaction been deleted as expected?
*
* @param store
* @param id
* @return - true if applied, false if not
*/
public boolean isSnapshotIndexed(String store, int id)
{
StoreRef storeRef = AVMNodeConverter.ToStoreRef(store);
Indexer indexer = indexerAndSearcher.getIndexer(storeRef);
if (indexer instanceof AVMLuceneIndexer)
{
AVMLuceneIndexer avmIndexer = (AVMLuceneIndexer) indexer;
return avmIndexer.isSnapshotIndexed(store, id);
}
return false;
}
private synchronized IndexMode getIndexMode(String store) private synchronized IndexMode getIndexMode(String store)
{ {
IndexMode mode = modeCache.get(store); IndexMode mode = modeCache.get(store);
@@ -363,4 +407,27 @@ public class AVMSnapShotTriggeredIndexingMethodInterceptor implements MethodInte
{ {
STAGING, STAGING_PREVIEW, AUTHOR, AUTHOR_PREVIEW, WORKFLOW, WORKFLOW_PREVIEW, AUTHOR_WORKFLOW, AUTHOR_WORKFLOW_PREVIEW, UNKNOWN; STAGING, STAGING_PREVIEW, AUTHOR, AUTHOR_PREVIEW, WORKFLOW, WORKFLOW_PREVIEW, AUTHOR_WORKFLOW, AUTHOR_WORKFLOW_PREVIEW, UNKNOWN;
} }
public boolean hasIndexBeenCreated(String store)
{
StoreRef storeRef = AVMNodeConverter.ToStoreRef(store);
Indexer indexer = indexerAndSearcher.getIndexer(storeRef);
if (indexer instanceof AVMLuceneIndexer)
{
AVMLuceneIndexer avmIndexer = (AVMLuceneIndexer) indexer;
return avmIndexer.hasIndexBeenCreated(store);
}
return false;
}
public void createIndex(String store)
{
StoreRef storeRef = AVMNodeConverter.ToStoreRef(store);
Indexer indexer = indexerAndSearcher.getIndexer(storeRef);
if (indexer instanceof AVMLuceneIndexer)
{
AVMLuceneIndexer avmIndexer = (AVMLuceneIndexer) indexer;
avmIndexer.createIndex(store, IndexMode.SYNCHRONOUS);
}
}
} }

View File

@@ -61,4 +61,42 @@ public interface AVMLuceneIndexer extends LuceneIndexer, BackgroundIndexerAware
* @param mode * @param mode
*/ */
public void createIndex(String store, IndexMode mode); public void createIndex(String store, IndexMode mode);
/**
* Get the id of the last snapshot added to the index
* @param store
*
* @param mode
* - IndexMode.SYNCHRONOUS - the last searchable snapshop
* - IndexMode.ASYNCHRONOUS - the last pending snapshot to be indexed. It may or may not be searchable.
* @return - the snapshot id
*/
public int getLastIndexedSnapshot(String store);
/**
* Is the snapshot applied to the index?
*
* Is there an entry for any node that was added OR have all the nodes in the transaction been deleted as expected?
*
* @param store
* @param id
* @return - true if applied, false if not
*/
public boolean isSnapshotIndexed(String store, int id);
/**
* Is snapshot searchable
* @param store
* @param id
* @return - true if snapshot has been fully indexed, false if pending or unindexed.
*/
public boolean isSnapshotSearchable(String store, int id);
/**
* Has the index been ceated
*
* @param store
* @return
*/
public boolean hasIndexBeenCreated(String store);
} }

View File

@@ -40,6 +40,7 @@ import java.util.Locale;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
import org.alfresco.error.AlfrescoRuntimeException;
import org.alfresco.i18n.I18NUtil; import org.alfresco.i18n.I18NUtil;
import org.alfresco.model.ContentModel; import org.alfresco.model.ContentModel;
import org.alfresco.model.WCMModel; import org.alfresco.model.WCMModel;
@@ -52,7 +53,6 @@ import org.alfresco.repo.content.MimetypeMap;
import org.alfresco.repo.content.transform.ContentTransformer; import org.alfresco.repo.content.transform.ContentTransformer;
import org.alfresco.repo.domain.PropertyValue; import org.alfresco.repo.domain.PropertyValue;
import org.alfresco.repo.search.IndexMode; import org.alfresco.repo.search.IndexMode;
import org.alfresco.repo.search.impl.lucene.analysis.NumericEncoder;
import org.alfresco.repo.search.impl.lucene.fts.FTSIndexerAware; import org.alfresco.repo.search.impl.lucene.fts.FTSIndexerAware;
import org.alfresco.repo.search.impl.lucene.fts.FullTextSearchIndexer; import org.alfresco.repo.search.impl.lucene.fts.FullTextSearchIndexer;
import org.alfresco.repo.transaction.AlfrescoTransactionSupport; import org.alfresco.repo.transaction.AlfrescoTransactionSupport;
@@ -74,6 +74,9 @@ import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.repository.StoreRef; import org.alfresco.service.cmr.repository.StoreRef;
import org.alfresco.service.cmr.repository.datatype.DefaultTypeConverter; import org.alfresco.service.cmr.repository.datatype.DefaultTypeConverter;
import org.alfresco.service.cmr.repository.datatype.TypeConversionException; import org.alfresco.service.cmr.repository.datatype.TypeConversionException;
import org.alfresco.service.cmr.search.ResultSet;
import org.alfresco.service.cmr.search.SearchParameters;
import org.alfresco.service.cmr.search.SearchService;
import org.alfresco.service.namespace.QName; import org.alfresco.service.namespace.QName;
import org.alfresco.util.EqualsHelper; import org.alfresco.util.EqualsHelper;
import org.alfresco.util.GUID; import org.alfresco.util.GUID;
@@ -82,7 +85,10 @@ import org.alfresco.util.Pair;
import org.apache.log4j.Logger; import org.apache.log4j.Logger;
import org.apache.lucene.document.Document; import org.apache.lucene.document.Document;
import org.apache.lucene.document.Field; import org.apache.lucene.document.Field;
import org.apache.lucene.index.IndexReader;
import org.apache.lucene.index.Term; import org.apache.lucene.index.Term;
import org.apache.lucene.index.TermDocs;
import org.apache.lucene.index.TermEnum;
import org.apache.lucene.search.Hits; import org.apache.lucene.search.Hits;
import org.apache.lucene.search.PrefixQuery; import org.apache.lucene.search.PrefixQuery;
import org.apache.lucene.search.Searcher; import org.apache.lucene.search.Searcher;
@@ -94,9 +100,7 @@ import org.apache.lucene.search.Searcher;
*/ */
public class AVMLuceneIndexerImpl extends AbstractLuceneIndexerImpl<String> implements AVMLuceneIndexer public class AVMLuceneIndexerImpl extends AbstractLuceneIndexerImpl<String> implements AVMLuceneIndexer
{ {
private static String SNAP_SHOT_ID = "SnapShotId_"; private static String SNAP_SHOT_ID = "SnapShot";
private static String SNAP_SHOT_STORE = "SnapShotStore";
static Logger s_logger = Logger.getLogger(AVMLuceneIndexerImpl.class); static Logger s_logger = Logger.getLogger(AVMLuceneIndexerImpl.class);
@@ -213,7 +217,7 @@ public class AVMLuceneIndexerImpl extends AbstractLuceneIndexerImpl<String> impl
} }
} }
public void asynchronousIndex(String store, int srcVersion, int dstVersion) private void asynchronousIndex(String store, int srcVersion, int dstVersion)
{ {
if (s_logger.isDebugEnabled()) if (s_logger.isDebugEnabled())
{ {
@@ -223,7 +227,7 @@ public class AVMLuceneIndexerImpl extends AbstractLuceneIndexerImpl<String> impl
fullTextSearchIndexer.requiresIndex(AVMNodeConverter.ToStoreRef(store)); fullTextSearchIndexer.requiresIndex(AVMNodeConverter.ToStoreRef(store));
} }
public void synchronousIndex(String store, int srcVersion, int dstVersion) private void synchronousIndex(String store, int srcVersion, int dstVersion)
{ {
if (startVersion == -1) if (startVersion == -1)
{ {
@@ -232,7 +236,6 @@ public class AVMLuceneIndexerImpl extends AbstractLuceneIndexerImpl<String> impl
endVersion = dstVersion; endVersion = dstVersion;
if (s_logger.isDebugEnabled()) if (s_logger.isDebugEnabled())
{ {
s_logger.debug("Sync index for " + store + " from " + srcVersion + " to " + dstVersion); s_logger.debug("Sync index for " + store + " from " + srcVersion + " to " + dstVersion);
@@ -275,13 +278,21 @@ public class AVMLuceneIndexerImpl extends AbstractLuceneIndexerImpl<String> impl
// Anything else then we reindex // Anything else then we reindex
else else
{ {
// TODO: Check hen to rebuild aux paths if (!difference.getSourcePath().equals(difference.getDestinationPath()))
// Should only reindex if the path has changed - not anything on a directory {
reindex(difference.getSourcePath(), srcDesc.isDirectory()); reindex(difference.getSourcePath(), srcDesc.isDirectory());
reindex(difference.getDestinationPath(), dstDesc.isDirectory()); reindex(difference.getDestinationPath(), dstDesc.isDirectory());
reindexAllAncestors(difference.getSourcePath());
reindexAllAncestors(difference.getDestinationPath()); reindexAllAncestors(difference.getDestinationPath());
}
else
{
// If it is a directory, it is at the same path,
// so no cascade update is required for the bridge table data.
reindex(difference.getDestinationPath(), false);
reindexAllAncestors(difference.getDestinationPath()); reindexAllAncestors(difference.getDestinationPath());
} }
}
break; break;
case AVMDifference.DIRECTORY: case AVMDifference.DIRECTORY:
// Never seen // Never seen
@@ -293,7 +304,7 @@ public class AVMLuceneIndexerImpl extends AbstractLuceneIndexerImpl<String> impl
} }
} }
// record the snap shotid // record the snap shotid
reindex(SNAP_SHOT_ID + store, false); reindex(SNAP_SHOT_ID + ":" + store + ":" + srcVersion + ":" + dstVersion, false);
} }
/* /*
@@ -355,11 +366,6 @@ public class AVMLuceneIndexerImpl extends AbstractLuceneIndexerImpl<String> impl
{ {
Document sdoc = new Document(); Document sdoc = new Document();
sdoc.add(new Field("ID", stringNodeRef, Field.Store.YES, Field.Index.UN_TOKENIZED, Field.TermVector.NO)); sdoc.add(new Field("ID", stringNodeRef, Field.Store.YES, Field.Index.UN_TOKENIZED, Field.TermVector.NO));
String storeName = stringNodeRef.substring(SNAP_SHOT_ID.length());
sdoc.add(new Field(SNAP_SHOT_ID, NumericEncoder.encode(avmService.getLatestSnapshotID(storeName)),
Field.Store.YES, Field.Index.UN_TOKENIZED, Field.TermVector.NO));
sdoc.add(new Field(SNAP_SHOT_STORE, NumericEncoder.encode(avmService.getLatestSnapshotID(storeName)),
Field.Store.YES, Field.Index.UN_TOKENIZED, Field.TermVector.NO));
docs.add(sdoc); docs.add(sdoc);
return docs; return docs;
} }
@@ -437,17 +443,17 @@ public class AVMLuceneIndexerImpl extends AbstractLuceneIndexerImpl<String> impl
boolean isAtomic = true; boolean isAtomic = true;
Map<QName, Serializable> properties = getIndexableProperties(desc, node, nodeRef, endVersion, stringNodeRef); Map<QName, Serializable> properties = getIndexableProperties(desc, nodeRef, endVersion, stringNodeRef);
for (QName propertyName : properties.keySet()) for (QName propertyName : properties.keySet())
{ {
Serializable value = properties.get(propertyName); Serializable value = properties.get(propertyName);
if (indexAllProperties) if (indexAllProperties)
{ {
indexProperty(node, nodeRef, propertyName, value, xdoc, false); indexProperty(nodeRef, propertyName, value, xdoc, false, endVersion, stringNodeRef);
} }
else else
{ {
isAtomic &= indexProperty(node, nodeRef, propertyName, value, xdoc, true); isAtomic &= indexProperty(nodeRef, propertyName, value, xdoc, true, endVersion, stringNodeRef);
} }
} }
@@ -617,10 +623,10 @@ public class AVMLuceneIndexerImpl extends AbstractLuceneIndexerImpl<String> impl
} }
} }
private Map<QName, Serializable> getIndexableProperties(AVMNodeDescriptor desc, AVMNode node, NodeRef nodeRef, private Map<QName, Serializable> getIndexableProperties(AVMNodeDescriptor desc, NodeRef nodeRef, Integer version,
Integer version, String path) String path)
{ {
Map<QName, PropertyValue> properties = node.getProperties(); Map<QName, PropertyValue> properties = avmService.getNodeProperties(version, path);
Map<QName, Serializable> result = new HashMap<QName, Serializable>(); Map<QName, Serializable> result = new HashMap<QName, Serializable>();
for (QName qName : properties.keySet()) for (QName qName : properties.keySet())
@@ -642,11 +648,14 @@ public class AVMLuceneIndexerImpl extends AbstractLuceneIndexerImpl<String> impl
result.put(ContentModel.PROP_STORE_IDENTIFIER, nodeRef.getStoreRef().getIdentifier()); result.put(ContentModel.PROP_STORE_IDENTIFIER, nodeRef.getStoreRef().getIdentifier());
if (desc.isLayeredDirectory()) if (desc.isLayeredDirectory())
{ {
result.put(WCMModel.PROP_AVM_DIR_INDIRECTION, AVMNodeConverter.ToNodeRef(endVersion, desc.getIndirection())); result
.put(WCMModel.PROP_AVM_DIR_INDIRECTION, AVMNodeConverter.ToNodeRef(endVersion, desc
.getIndirection()));
} }
if (desc.isLayeredFile()) if (desc.isLayeredFile())
{ {
result.put(WCMModel.PROP_AVM_FILE_INDIRECTION, AVMNodeConverter.ToNodeRef(endVersion, desc.getIndirection())); result.put(WCMModel.PROP_AVM_FILE_INDIRECTION, AVMNodeConverter
.ToNodeRef(endVersion, desc.getIndirection()));
} }
if (desc.isFile()) if (desc.isFile())
{ {
@@ -696,8 +705,8 @@ public class AVMLuceneIndexerImpl extends AbstractLuceneIndexerImpl<String> impl
} }
} }
protected boolean indexProperty(AVMNode node, NodeRef banana, QName propertyName, Serializable value, Document doc, protected boolean indexProperty(NodeRef banana, QName propertyName, Serializable value, Document doc,
boolean indexAtomicPropertiesOnly) boolean indexAtomicPropertiesOnly, int version, String path)
{ {
String attributeName = "@" String attributeName = "@"
+ QName.createQName(propertyName.getNamespaceURI(), ISO9075.encode(propertyName.getLocalName())); + QName.createQName(propertyName.getNamespaceURI(), ISO9075.encode(propertyName.getLocalName()));
@@ -937,7 +946,8 @@ public class AVMLuceneIndexerImpl extends AbstractLuceneIndexerImpl<String> impl
// TODO: Use the node locale in preferanced to the system locale // TODO: Use the node locale in preferanced to the system locale
Locale locale = null; Locale locale = null;
Serializable localeProperty = node.getProperty(ContentModel.PROP_LOCALE); Serializable localeProperty = avmService.getNodeProperties(version, path).get(
ContentModel.PROP_LOCALE);
if (localeProperty != null) if (localeProperty != null)
{ {
locale = DefaultTypeConverter.INSTANCE.convert(Locale.class, localeProperty); locale = DefaultTypeConverter.INSTANCE.convert(Locale.class, localeProperty);
@@ -1329,4 +1339,177 @@ public class AVMLuceneIndexerImpl extends AbstractLuceneIndexerImpl<String> impl
{ {
this.fullTextSearchIndexer = fullTextSearchIndexer; this.fullTextSearchIndexer = fullTextSearchIndexer;
} }
public int getLastIndexedSnapshot(String store)
{
int last = getLastAsynchronousSnapshot(store);
if (last >= 0)
{
return last;
}
return getLastSynchronousSnapshot(store);
}
public boolean isSnapshotIndexed(String store, int id)
{
return (id <= getLastAsynchronousSnapshot(store)) || (id <= getLastSynchronousSnapshot(store));
}
public boolean isSnapshotSearchable(String store, int id)
{
return (id <= getLastSynchronousSnapshot(store));
}
private int getLastSynchronousSnapshot(String store)
{
String prefix = SNAP_SHOT_ID + ":" + store;
IndexReader mainReader = null;
int end = -1;
try
{
mainReader = getReader();
TermEnum terms = null;
try
{
terms = mainReader.terms(new Term("ID", prefix));
while (terms.next())
{
Term term = terms.term();
if (term.text().startsWith(prefix))
{
String[] split = term.text().split(":");
end = Integer.parseInt(split[3]);
}
else
{
break;
}
}
}
finally
{
if (terms != null)
{
terms.close();
}
}
return end;
}
catch (IOException e)
{
throw new AlfrescoRuntimeException("IO error", e);
}
finally
{
try
{
if (mainReader != null)
{
mainReader.close();
}
}
catch (IOException e)
{
s_logger.warn("Failed to close main reader", e);
}
}
}
private int getLastAsynchronousSnapshot(String store)
{
String prefix = "\u0000BG:STORE:" + store + ":";
IndexReader mainReader = null;
int end = -1;
try
{
mainReader = getReader();
TermEnum terms = null;
try
{
terms = mainReader.terms(new Term("ID", prefix));
while (terms.next())
{
Term term = terms.term();
if (term.text().startsWith(prefix))
{
String[] split = term.text().split(":");
end = Integer.parseInt(split[4]);
}
else
{
break;
}
}
}
finally
{
if (terms != null)
{
terms.close();
}
}
return end;
}
catch (IOException e)
{
throw new AlfrescoRuntimeException("IO error", e);
}
finally
{
try
{
if (mainReader != null)
{
mainReader.close();
}
}
catch (IOException e)
{
s_logger.warn("Failed to close main reader", e);
}
}
}
public boolean hasIndexBeenCreated(String store)
{
IndexReader mainReader = null;
try
{
mainReader = getReader();
TermDocs termDocs = null;
try
{
termDocs = mainReader.termDocs(new Term("ISROOT", "T"));
return termDocs.next();
}
finally
{
if (termDocs != null)
{
termDocs.close();
}
}
}
catch (IOException e)
{
throw new AlfrescoRuntimeException("IO error", e);
}
finally
{
try
{
if (mainReader != null)
{
mainReader.close();
}
}
catch (IOException e)
{
s_logger.warn("Failed to close main reader", e);
}
}
}
} }

View File

@@ -215,6 +215,21 @@ public class LuceneQueryParser extends QueryParser
TermQuery termQuery = new TermQuery(new Term(field, queryText)); TermQuery termQuery = new TermQuery(new Term(field, queryText));
return termQuery; return termQuery;
} }
else if (field.equals("ISROOT"))
{
TermQuery termQuery = new TermQuery(new Term(field, queryText));
return termQuery;
}
else if (field.equals("ISCONTAINER"))
{
TermQuery termQuery = new TermQuery(new Term(field, queryText));
return termQuery;
}
else if (field.equals("ISNODE"))
{
TermQuery termQuery = new TermQuery(new Term(field, queryText));
return termQuery;
}
else if (field.equals("TX")) else if (field.equals("TX"))
{ {
TermQuery termQuery = new TermQuery(new Term(field, queryText)); TermQuery termQuery = new TermQuery(new Term(field, queryText));