From 8ac57ee1cd50fcc3d02b36bea4ab1335924f1d7a Mon Sep 17 00:00:00 2001
From: Yannick Lecaillez <yannick.lecaillez@forgerock.com>
Date: Mon, 18 May 2015 13:52:40 +0000
Subject: [PATCH] OPENDJ-1864: Ordering matching rules should reuse equality indexes where possible
---
opendj-server-legacy/src/main/java/org/opends/server/backends/pluggable/AttributeIndex.java | 508 +++++++++++++++++++++++---------------------------------
1 files changed, 209 insertions(+), 299 deletions(-)
diff --git a/opendj-server-legacy/src/main/java/org/opends/server/backends/pluggable/AttributeIndex.java b/opendj-server-legacy/src/main/java/org/opends/server/backends/pluggable/AttributeIndex.java
index cd1d4b6..bb70938 100644
--- a/opendj-server-legacy/src/main/java/org/opends/server/backends/pluggable/AttributeIndex.java
+++ b/opendj-server-legacy/src/main/java/org/opends/server/backends/pluggable/AttributeIndex.java
@@ -111,36 +111,35 @@
/**
* This class implements an attribute indexer for matching rules in a Backend.
*/
- final class MatchingRuleIndex extends DefaultIndex
+ static final class MatchingRuleIndex extends DefaultIndex
{
- /**
- * The matching rule's indexer.
- */
+ private final AttributeType attributeType;
private final Indexer indexer;
- private MatchingRuleIndex(WriteableTransaction txn, BackendIndexCfg cfg, Indexer indexer)
+ private MatchingRuleIndex(EntryContainer entryContainer, AttributeType attributeType, State state, Indexer indexer,
+ int indexEntryLimit)
{
- super(getIndexName(attributeType, indexer.getIndexID()), state, cfg.getIndexEntryLimit(), txn, entryContainer);
+ super(getIndexName(entryContainer, attributeType, indexer.getIndexID()), state, indexEntryLimit, entryContainer);
+ this.attributeType = attributeType;
this.indexer = indexer;
}
- void indexEntry(Entry entry, Set<ByteString> keys, IndexingOptions options)
+ void indexEntry(Entry entry, Set<ByteString> keys)
{
List<Attribute> attributes = entry.getAttribute(attributeType, true);
if (attributes != null)
{
- indexAttribute(attributes, keys, options);
+ indexAttribute(attributes, keys);
}
}
- private void modifyEntry(Entry oldEntry, Entry newEntry, Map<ByteString, Boolean> modifiedKeys,
- IndexingOptions options)
+ private void modifyEntry(Entry oldEntry, Entry newEntry, Map<ByteString, Boolean> modifiedKeys)
{
List<Attribute> oldAttributes = oldEntry.getAttribute(attributeType, true);
if (oldAttributes != null)
{
final Set<ByteString> keys = new HashSet<ByteString>();
- indexAttribute(oldAttributes, keys, options);
+ indexAttribute(oldAttributes, keys);
for (ByteString key : keys)
{
modifiedKeys.put(key, false);
@@ -151,7 +150,7 @@
if (newAttributes != null)
{
final Set<ByteString> keys = new HashSet<ByteString>();
- indexAttribute(newAttributes, keys, options);
+ indexAttribute(newAttributes, keys);
for (ByteString key : keys)
{
final Boolean needsAdding = modifiedKeys.get(key);
@@ -169,7 +168,7 @@
}
}
- private void indexAttribute(List<Attribute> attributes, Set<ByteString> keys, IndexingOptions options)
+ private void indexAttribute(List<Attribute> attributes, Set<ByteString> keys)
{
for (Attribute attr : attributes)
{
@@ -179,7 +178,7 @@
{
try
{
- indexer.createKeys(Schema.getDefaultSchema(), value, options, keys);
+ indexer.createKeys(Schema.getDefaultSchema(), value, keys);
/*
* Optimization for presence: return immediately after first value since all values
@@ -209,8 +208,7 @@
private static final Indexer PRESENCE_INDEXER = new Indexer()
{
@Override
- public void createKeys(Schema schema, ByteSequence value, IndexingOptions options, Collection<ByteString> keys)
- throws DecodeException
+ public void createKeys(Schema schema, ByteSequence value, Collection<ByteString> keys) throws DecodeException
{
keys.add(PRESENCE_KEY);
}
@@ -235,118 +233,113 @@
private BackendIndexCfg config;
/** The mapping from names to indexes. */
- private final Map<String, MatchingRuleIndex> nameToIndexes = new HashMap<String, MatchingRuleIndex>();
- private final IndexingOptions indexingOptions;
+ private Map<String, MatchingRuleIndex> indexIdToIndexes;
+ private IndexingOptions indexingOptions;
private final State state;
- /** The attribute type for which this instance will generate index keys. */
- private final AttributeType attributeType;
-
- AttributeIndex(BackendIndexCfg config, State state, EntryContainer entryContainer, WriteableTransaction txn)
- throws ConfigException
+ AttributeIndex(BackendIndexCfg config, State state, EntryContainer entryContainer) throws ConfigException
{
this.entryContainer = entryContainer;
this.config = config;
this.state = state;
- this.attributeType = config.getAttribute();
-
- buildPresenceIndex(txn);
- buildIndexes(txn, IndexType.EQUALITY);
- buildIndexes(txn, IndexType.SUBSTRING);
- buildIndexes(txn, IndexType.ORDERING);
- buildIndexes(txn, IndexType.APPROXIMATE);
- buildExtensibleIndexes(txn);
-
- indexingOptions = new IndexingOptionsImpl(config.getSubstringLength());
+ this.indexingOptions = new IndexingOptionsImpl(config.getSubstringLength());
+ this.indexIdToIndexes = Collections.unmodifiableMap(buildIndexes(entryContainer, state, config));
}
- private void buildPresenceIndex(WriteableTransaction txn)
+ private static Map<String, MatchingRuleIndex> buildIndexes(EntryContainer entryContainer, State state,
+ BackendIndexCfg config) throws ConfigException
{
- final IndexType indexType = IndexType.PRESENCE;
- if (config.getIndexType().contains(indexType))
- {
- String indexID = indexType.toString();
- nameToIndexes.put(indexID, new MatchingRuleIndex(txn, config, PRESENCE_INDEXER));
- }
- }
+ final AttributeType attributeType = config.getAttribute();
+ final int indexEntryLimit = config.getIndexEntryLimit();
+ final IndexingOptions indexingOptions = new IndexingOptionsImpl(config.getSubstringLength());
- private void buildExtensibleIndexes(WriteableTransaction txn) throws ConfigException
- {
- final IndexType indexType = IndexType.EXTENSIBLE;
- if (config.getIndexType().contains(indexType))
- {
- final AttributeType attrType = config.getAttribute();
- Set<String> extensibleRules = config.getIndexExtensibleMatchingRule();
- if (extensibleRules == null || extensibleRules.isEmpty())
+ final Map<String, MatchingRuleIndex> indexes = new HashMap<>();
+
+ for(IndexType indexType : config.getIndexType()) {
+ Collection<? extends Indexer> indexers;
+ switch (indexType)
{
- throw new ConfigException(ERR_CONFIG_INDEX_TYPE_NEEDS_MATCHING_RULE.get(attrType, indexType.toString()));
+ case PRESENCE:
+ indexers = Collections.singleton(PRESENCE_INDEXER);
+ break;
+ case EXTENSIBLE:
+ indexers =
+ getExtensibleIndexers(config.getAttribute(), config.getIndexExtensibleMatchingRule(), indexingOptions);
+ break;
+ case APPROXIMATE:
+ indexers =
+ throwIfNoMatchingRule(attributeType, indexType, attributeType.getApproximateMatchingRule()).createIndexers(
+ indexingOptions);
+ break;
+ case EQUALITY:
+ indexers =
+ throwIfNoMatchingRule(attributeType, indexType, attributeType.getEqualityMatchingRule()).createIndexers(
+ indexingOptions);
+ break;
+ case ORDERING:
+ indexers =
+ throwIfNoMatchingRule(attributeType, indexType, attributeType.getOrderingMatchingRule()).createIndexers(
+ indexingOptions);
+ break;
+ case SUBSTRING:
+ indexers =
+ throwIfNoMatchingRule(attributeType, indexType, attributeType.getSubstringMatchingRule()).createIndexers(
+ indexingOptions);
+ break;
+ default:
+ throw new ConfigException(ERR_CONFIG_INDEX_TYPE_NEEDS_MATCHING_RULE.get(attributeType, indexType.toString()));
}
+ buildIndexesForIndexers(entryContainer, attributeType, state, indexes, indexEntryLimit, indexers);
+ }
+ return indexes;
+ }
- // Iterate through the Set and create the index only if necessary.
- // Collation equality and Ordering matching rules share the same indexer and index
- // A Collation substring matching rule is treated differently
- // as it uses a separate indexer and index.
- for (final String ruleName : extensibleRules)
+ private static MatchingRule throwIfNoMatchingRule(AttributeType attributeType, IndexType type, MatchingRule rule)
+ throws ConfigException
+ {
+ if (rule == null)
+ {
+ throw new ConfigException(ERR_CONFIG_INDEX_TYPE_NEEDS_MATCHING_RULE.get(attributeType, type.toString()));
+ }
+ return rule;
+ }
+
+ private static void buildIndexesForIndexers(EntryContainer entryContainer, AttributeType attributeType, State state,
+ Map<String, MatchingRuleIndex> indexes, int indexEntryLimit, Collection<? extends Indexer> indexers)
+ {
+ for (Indexer indexer : indexers)
+ {
+ final String indexID = indexer.getIndexID();
+ if (!indexes.containsKey(indexID))
{
- MatchingRule rule = DirectoryServer.getMatchingRule(toLowerCase(ruleName));
- if (rule == null)
- {
- logger.error(ERR_CONFIG_INDEX_TYPE_NEEDS_VALID_MATCHING_RULE, attrType, ruleName);
- continue;
- }
- for (Indexer indexer : rule.getIndexers())
- {
- final String indexId = indexer.getIndexID();
- if (!nameToIndexes.containsKey(indexId))
- {
- // There is no index available for this index id. Create a new index
- nameToIndexes.put(indexId, new MatchingRuleIndex(txn, config, indexer));
- }
- }
+ indexes.put(indexID, new MatchingRuleIndex(entryContainer, attributeType, state, indexer, indexEntryLimit));
}
}
}
- private void buildIndexes(WriteableTransaction txn, IndexType indexType) throws ConfigException
+ private static Collection<Indexer> getExtensibleIndexers(AttributeType attributeType, Set<String> extensibleRules,
+ IndexingOptions options) throws ConfigException
{
- if (config.getIndexType().contains(indexType))
+ if (extensibleRules == null || extensibleRules.isEmpty())
{
- final AttributeType attrType = config.getAttribute();
- final String indexID = indexType.toString();
- final MatchingRule rule = getMatchingRule(indexType, attrType);
- if (rule == null)
- {
- throw new ConfigException(ERR_CONFIG_INDEX_TYPE_NEEDS_MATCHING_RULE.get(attrType, indexID));
- }
-
- for (Indexer indexer : rule.getIndexers())
- {
- nameToIndexes.put(indexer.getIndexID(), new MatchingRuleIndex(txn, config, indexer));
- }
+ throw new ConfigException(
+ ERR_CONFIG_INDEX_TYPE_NEEDS_MATCHING_RULE.get(attributeType, IndexType.EXTENSIBLE.toString()));
}
+
+ final Collection<Indexer> indexers = new ArrayList<>();
+ for (final String ruleName : extensibleRules)
+ {
+ final MatchingRule rule = DirectoryServer.getMatchingRule(toLowerCase(ruleName));
+ throwIfNoMatchingRule(attributeType, IndexType.EXTENSIBLE, rule);
+ indexers.addAll(rule.createIndexers(options));
+ }
+
+ return indexers;
}
- private MatchingRule getMatchingRule(IndexType indexType, AttributeType attrType)
+ private static TreeName getIndexName(EntryContainer entryContainer, AttributeType attrType, String indexID)
{
- switch (indexType)
- {
- case APPROXIMATE:
- return attrType.getApproximateMatchingRule();
- case EQUALITY:
- return attrType.getEqualityMatchingRule();
- case ORDERING:
- return attrType.getOrderingMatchingRule();
- case SUBSTRING:
- return attrType.getSubstringMatchingRule();
- default:
- throw new IllegalArgumentException("Not implemented for index type " + indexType);
- }
- }
-
- private TreeName getIndexName(AttributeType attrType, String indexID)
- {
- final String attrIndexId = attrType.getNameOrOID() + "." + indexID;
- return new TreeName(entryContainer.getTreePrefix(), attrIndexId);
+ return new TreeName(entryContainer.getTreePrefix(), attrType.getNameOrOID() + "." + indexID);
}
/**
@@ -357,7 +350,7 @@
*/
void open(WriteableTransaction txn) throws StorageRuntimeException
{
- for (Index index : nameToIndexes.values())
+ for (Index index : indexIdToIndexes.values())
{
index.open(txn);
}
@@ -436,10 +429,10 @@
*/
void addEntry(IndexBuffer buffer, EntryID entryID, Entry entry) throws StorageRuntimeException, DirectoryException
{
- for (MatchingRuleIndex index : nameToIndexes.values())
+ for (MatchingRuleIndex index : indexIdToIndexes.values())
{
- HashSet<ByteString> keys = new HashSet<ByteString>();
- index.indexEntry(entry, keys, indexingOptions);
+ final Set<ByteString> keys = new HashSet<>();
+ index.indexEntry(entry, keys);
for (ByteString key : keys)
{
buffer.put(index, key, entryID);
@@ -458,10 +451,10 @@
*/
void removeEntry(IndexBuffer buffer, EntryID entryID, Entry entry) throws StorageRuntimeException, DirectoryException
{
- for (MatchingRuleIndex index : nameToIndexes.values())
+ for (MatchingRuleIndex index : indexIdToIndexes.values())
{
HashSet<ByteString> keys = new HashSet<ByteString>();
- index.indexEntry(entry, keys, indexingOptions);
+ index.indexEntry(entry, keys);
for (ByteString key : keys)
{
buffer.remove(index, key, entryID);
@@ -482,10 +475,10 @@
*/
void modifyEntry(IndexBuffer buffer, EntryID entryID, Entry oldEntry, Entry newEntry) throws StorageRuntimeException
{
- for (MatchingRuleIndex index : nameToIndexes.values())
+ for (MatchingRuleIndex index : indexIdToIndexes.values())
{
TreeMap<ByteString, Boolean> modifiedKeys = new TreeMap<ByteString, Boolean>();
- index.modifyEntry(oldEntry, newEntry, modifiedKeys, indexingOptions);
+ index.modifyEntry(oldEntry, newEntry, modifiedKeys);
for (Map.Entry<ByteString, Boolean> modifiedKey : modifiedKeys.entrySet())
{
if (modifiedKey.getValue())
@@ -694,226 +687,143 @@
return true;
}
- private boolean isIndexAcceptable(BackendIndexCfg cfg, IndexType indexType,
+ private static boolean isIndexAcceptable(BackendIndexCfg cfg, IndexType indexType,
List<LocalizableMessage> unacceptableReasons)
{
- final String indexId = indexType.toString();
final AttributeType attrType = cfg.getAttribute();
if (cfg.getIndexType().contains(indexType)
- && nameToIndexes.get(indexId) == null
&& getMatchingRule(indexType, attrType) == null)
{
- unacceptableReasons.add(ERR_CONFIG_INDEX_TYPE_NEEDS_MATCHING_RULE.get(attrType, indexId));
+ unacceptableReasons.add(ERR_CONFIG_INDEX_TYPE_NEEDS_MATCHING_RULE.get(attrType, indexType));
return false;
}
return true;
}
+ private static MatchingRule getMatchingRule(IndexType indexType, AttributeType attrType)
+ {
+ switch (indexType)
+ {
+ case APPROXIMATE:
+ return attrType.getApproximateMatchingRule();
+ case EQUALITY:
+ return attrType.getEqualityMatchingRule();
+ case ORDERING:
+ return attrType.getOrderingMatchingRule();
+ case SUBSTRING:
+ return attrType.getSubstringMatchingRule();
+ default:
+ throw new IllegalArgumentException("Not implemented for index type " + indexType);
+ }
+ }
+
/** {@inheritDoc} */
@Override
- public synchronized ConfigChangeResult applyConfigurationChange(final BackendIndexCfg cfg)
+ public synchronized ConfigChangeResult applyConfigurationChange(final BackendIndexCfg newConfiguration)
{
final ConfigChangeResult ccr = new ConfigChangeResult();
+ final IndexingOptions newIndexingOptions = new IndexingOptionsImpl(newConfiguration.getSubstringLength());
try
{
+ final Map<String, MatchingRuleIndex> newIndexIdToIndexes = buildIndexes(entryContainer, state, newConfiguration);
+
+ final Map<String, MatchingRuleIndex> removedIndexes = new HashMap<>(indexIdToIndexes);
+ removedIndexes.keySet().removeAll(newIndexIdToIndexes.keySet());
+
+ final Map<String, MatchingRuleIndex> addedIndexes = new HashMap<>(newIndexIdToIndexes);
+ addedIndexes.keySet().removeAll(indexIdToIndexes.keySet());
+
+ final Map<String, MatchingRuleIndex> updatedIndexes = new HashMap<>(indexIdToIndexes);
+ updatedIndexes.keySet().retainAll(newIndexIdToIndexes.keySet());
+
+ // Replace instances of Index created by buildIndexes() with the one already opened and present in the actual
+ // indexIdToIndexes
+ newIndexIdToIndexes.putAll(updatedIndexes);
+
+ // Open added indexes *before* adding them to indexIdToIndexes
entryContainer.getRootContainer().getStorage().write(new WriteOperation()
{
@Override
public void run(WriteableTransaction txn) throws Exception
{
- applyChangeToIndex(txn, IndexType.PRESENCE, cfg, ccr);
- applyChangeToIndex(txn, IndexType.EQUALITY, cfg, ccr);
- applyChangeToIndex(txn, IndexType.SUBSTRING, cfg, ccr);
- applyChangeToIndex(txn, IndexType.ORDERING, cfg, ccr);
- applyChangeToIndex(txn, IndexType.APPROXIMATE, cfg, ccr);
- applyChangeToExtensibleIndexes(txn, cfg, ccr);
+ for (MatchingRuleIndex addedIndex : addedIndexes.values())
+ {
+ openIndex(txn, addedIndex, ccr);
+ }
}
});
- config = cfg;
+ config = newConfiguration;
+ indexingOptions = newIndexingOptions;
+ indexIdToIndexes = Collections.unmodifiableMap(newIndexIdToIndexes);
+
+ // We get exclusive lock to ensure that no query is actually using the indexes that will be deleted.
+ entryContainer.lock();
+ try
+ {
+ entryContainer.getRootContainer().getStorage().write(new WriteOperation()
+ {
+ @Override
+ public void run(WriteableTransaction txn) throws Exception
+ {
+ for (MatchingRuleIndex removedIndex : removedIndexes.values())
+ {
+ deleteIndex(txn, entryContainer, removedIndex);
+ }
+ }
+ });
+ }
+ finally
+ {
+ entryContainer.unlock();
+ }
+
+ for (Index updatedIndex : updatedIndexes.values())
+ {
+ updateIndex(updatedIndex, newConfiguration.getIndexEntryLimit(), ccr);
+ }
+
}
- catch(Exception e)
+ catch (Exception e)
{
ccr.setResultCode(DirectoryServer.getServerErrorResultCode());
ccr.addMessage(LocalizableMessage.raw(StaticUtils.stackTraceToSingleLineString(e)));
}
+
return ccr;
}
- private void applyChangeToExtensibleIndexes(WriteableTransaction txn, BackendIndexCfg cfg, ConfigChangeResult ccr)
+ private static void openIndex(WriteableTransaction txn, MatchingRuleIndex index, ConfigChangeResult ccr)
{
- final AttributeType attrType = cfg.getAttribute();
- if (!cfg.getIndexType().contains(IndexType.EXTENSIBLE))
- {
- final Set<MatchingRule> validRules = Collections.emptySet();
- final Set<String> validIndexIds = Collections.emptySet();
- removeIndexesForExtensibleMatchingRules(txn, validRules, validIndexIds);
- return;
- }
-
- final Set<String> extensibleRules = cfg.getIndexExtensibleMatchingRule();
- final Set<MatchingRule> validRules = new HashSet<MatchingRule>();
- final Set<String> validIndexIds = new HashSet<String>();
- final int indexEntryLimit = cfg.getIndexEntryLimit();
-
- for (String ruleName : extensibleRules)
- {
- MatchingRule rule = DirectoryServer.getMatchingRule(toLowerCase(ruleName));
- if (rule == null)
- {
- logger.error(ERR_CONFIG_INDEX_TYPE_NEEDS_VALID_MATCHING_RULE, attrType, ruleName);
- continue;
- }
- validRules.add(rule);
- for (Indexer indexer : rule.getIndexers())
- {
- String indexId = indexer.getIndexID();
- validIndexIds.add(indexId);
- if (!nameToIndexes.containsKey(indexId))
- {
- nameToIndexes.put(indexId, openNewIndex(txn, cfg, indexer, ccr));
- }
- else
- {
- Index index = nameToIndexes.get(indexId);
- if (index.setIndexEntryLimit(indexEntryLimit))
- {
- ccr.setAdminActionRequired(true);
- ccr.addMessage(NOTE_CONFIG_INDEX_ENTRY_LIMIT_REQUIRES_REBUILD.get(index.getName()));
- }
- }
- }
- }
- removeIndexesForExtensibleMatchingRules(txn, validRules, validIndexIds);
- }
-
- /** Remove indexes which do not correspond to valid rules. */
- private void removeIndexesForExtensibleMatchingRules(WriteableTransaction txn, Set<MatchingRule> validRules,
- Set<String> validIndexIds)
- {
- final Set<MatchingRule> rulesToDelete = getCurrentExtensibleMatchingRules();
- rulesToDelete.removeAll(validRules);
- if (!rulesToDelete.isEmpty())
- {
- entryContainer.exclusiveLock.lock();
- try
- {
- for (MatchingRule rule: rulesToDelete)
- {
- final List<String> indexIdsToRemove = new ArrayList<String>();
- for (Indexer indexer : rule.getIndexers())
- {
- final String indexId = indexer.getIndexID();
- if (!validIndexIds.contains(indexId))
- {
- indexIdsToRemove.add(indexId);
- }
- }
- // Delete indexes which are not used
- for (String indexId : indexIdsToRemove)
- {
- Index index = nameToIndexes.get(indexId);
- if (index != null)
- {
- entryContainer.deleteTree(txn, index);
- nameToIndexes.remove(index);
- }
- }
- }
- }
- finally
- {
- entryContainer.exclusiveLock.unlock();
- }
- }
- }
-
- private Set<MatchingRule> getCurrentExtensibleMatchingRules()
- {
- final Set<MatchingRule> rules = new HashSet<MatchingRule>();
- for (String ruleName : config.getIndexExtensibleMatchingRule())
- {
- final MatchingRule rule = DirectoryServer.getMatchingRule(toLowerCase(ruleName));
- if (rule != null)
- {
- rules.add(rule);
- }
- }
- return rules;
- }
-
- private void applyChangeToIndex(final WriteableTransaction txn, final IndexType indexType, final BackendIndexCfg cfg,
- final ConfigChangeResult ccr)
- {
- String indexId = indexType.toString();
- MatchingRuleIndex index = nameToIndexes.get(indexId);
- if (!cfg.getIndexType().contains(indexType))
- {
- removeIndex(txn, index, indexType);
- return;
- }
-
- if (index == null)
- {
- if (indexType == IndexType.PRESENCE)
- {
- nameToIndexes.put(indexId, openNewIndex(txn, cfg, PRESENCE_INDEXER, ccr));
- }
- else
- {
- final MatchingRule matchingRule = getMatchingRule(indexType, cfg.getAttribute());
- for (Indexer indexer : matchingRule.getIndexers())
- {
- nameToIndexes.put(indexId, openNewIndex(txn, cfg, indexer, ccr));
- }
- }
- }
- else
- {
- // already exists. Just update index entry limit.
- if (index.setIndexEntryLimit(cfg.getIndexEntryLimit()))
- {
- ccr.setAdminActionRequired(true);
- ccr.addMessage(NOTE_CONFIG_INDEX_ENTRY_LIMIT_REQUIRES_REBUILD.get(index.getName()));
- }
-
- if (indexType == IndexType.SUBSTRING && config.getSubstringLength() != cfg.getSubstringLength())
- {
- ccr.setAdminActionRequired(true);
- ccr.addMessage(NOTE_CONFIG_INDEX_SUBSTRING_LENGTH_REQUIRES_REBUILD.get(index.getName()));
- }
- }
- }
-
- private void removeIndex(WriteableTransaction txn, Index index, IndexType indexType)
- {
- if (index != null)
- {
- entryContainer.exclusiveLock.lock();
- try
- {
- nameToIndexes.remove(indexType.toString());
- entryContainer.deleteTree(txn, index);
- }
- finally
- {
- entryContainer.exclusiveLock.unlock();
- }
- }
- }
-
- private MatchingRuleIndex openNewIndex(WriteableTransaction txn, BackendIndexCfg cfg, Indexer indexer,
- ConfigChangeResult ccr)
- {
- final MatchingRuleIndex index = new MatchingRuleIndex(txn, cfg, indexer);
index.open(txn);
-
if (!index.isTrusted())
{
ccr.setAdminActionRequired(true);
ccr.addMessage(NOTE_INDEX_ADD_REQUIRES_REBUILD.get(index.getName()));
}
- return index;
+ }
+
+ private static void updateIndex(Index updatedIndex, int newIndexEntryLimit, ConfigChangeResult ccr)
+ {
+ if (updatedIndex.setIndexEntryLimit(newIndexEntryLimit))
+ {
+ // This index can still be used since index size limit doesn't impact validity of the results.
+ ccr.setAdminActionRequired(true);
+ ccr.addMessage(NOTE_CONFIG_INDEX_ENTRY_LIMIT_REQUIRES_REBUILD.get(updatedIndex.getName()));
+ }
+ }
+
+ private static void deleteIndex(WriteableTransaction txn, EntryContainer entryContainer, Index index)
+ {
+ entryContainer.exclusiveLock.lock();
+ try
+ {
+ entryContainer.deleteTree(txn, index);
+ }
+ finally
+ {
+ entryContainer.exclusiveLock.unlock();
+ }
}
/**
@@ -922,7 +832,7 @@
*/
boolean isTrusted()
{
- for (Index index : nameToIndexes.values())
+ for (Index index : indexIdToIndexes.values())
{
if (!index.isTrusted())
{
@@ -946,7 +856,7 @@
Map<String, MatchingRuleIndex> getNameToIndexes()
{
- return Collections.unmodifiableMap(nameToIndexes);
+ return indexIdToIndexes;
}
/**
@@ -997,7 +907,7 @@
if (debugBuffer != null)
{
debugBuffer.append("[INDEX:");
- for (Indexer indexer : rule.getIndexers())
+ for (Indexer indexer : rule.createIndexers(indexingOptions))
{
debugBuffer.append(" ")
.append(filter.getAttributeType().getNameOrOID())
@@ -1032,9 +942,9 @@
private boolean ruleHasAtLeastOneIndex(MatchingRule rule)
{
- for (Indexer indexer : rule.getIndexers())
+ for (Indexer indexer : rule.createIndexers(indexingOptions))
{
- if (nameToIndexes.containsKey(indexer.getIndexID()))
+ if (indexIdToIndexes.containsKey(indexer.getIndexID()))
{
return true;
}
@@ -1043,7 +953,7 @@
}
/** Indexing options implementation. */
- private final class IndexingOptionsImpl implements IndexingOptions
+ private static final class IndexingOptionsImpl implements IndexingOptions
{
/** The length of substring keys used in substring indexes. */
private int substringKeySize;
@@ -1063,7 +973,7 @@
void closeAndDelete(WriteableTransaction txn)
{
close();
- for (Index index : nameToIndexes.values())
+ for (Index index : indexIdToIndexes.values())
{
index.delete(txn);
state.deleteRecord(txn, index.getName());
--
Gitblit v1.10.0