From 88f8db26c1a4389ea8ddcd5679f433446d0a55f3 Mon Sep 17 00:00:00 2001
From: Jean-Noël Rouvignac <jean-noel.rouvignac@forgerock.com>
Date: Thu, 08 Oct 2015 09:59:03 +0000
Subject: [PATCH] OPENDJ-1852 Fix feature envy between AttributeIndex and Index* classes
---
opendj-server-legacy/src/main/java/org/opends/server/backends/pluggable/IndexQueryFactoryImpl.java | 119 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++--
1 files changed, 115 insertions(+), 4 deletions(-)
diff --git a/opendj-server-legacy/src/main/java/org/opends/server/backends/pluggable/IndexQueryFactoryImpl.java b/opendj-server-legacy/src/main/java/org/opends/server/backends/pluggable/IndexQueryFactoryImpl.java
index 16e6ddc..9397e00 100644
--- a/opendj-server-legacy/src/main/java/org/opends/server/backends/pluggable/IndexQueryFactoryImpl.java
+++ b/opendj-server-legacy/src/main/java/org/opends/server/backends/pluggable/IndexQueryFactoryImpl.java
@@ -27,8 +27,8 @@
package org.opends.server.backends.pluggable;
import static org.opends.messages.BackendMessages.*;
-import static org.opends.server.backends.pluggable.EntryIDSet.newUndefinedSet;
-import static org.opends.server.backends.pluggable.EntryIDSet.newUndefinedSetWithKey;
+import static org.opends.server.backends.pluggable.EntryIDSet.*;
+import static org.opends.server.backends.pluggable.IndexFilter.*;
import java.util.ArrayList;
import java.util.Collection;
@@ -39,6 +39,7 @@
import org.forgerock.opendj.ldap.ByteString;
import org.forgerock.opendj.ldap.spi.IndexQueryFactory;
import org.forgerock.opendj.ldap.spi.IndexingOptions;
+import org.forgerock.util.Utils;
import org.opends.server.backends.pluggable.AttributeIndex.IndexFilterType;
import org.opends.server.backends.pluggable.spi.Cursor;
import org.opends.server.backends.pluggable.spi.ReadableTransaction;
@@ -50,9 +51,109 @@
*/
final class IndexQueryFactoryImpl implements IndexQueryFactory<IndexQuery>
{
+ /**
+ * This class creates a Null IndexQuery. It is used when there is no
+ * record in the index. It may also be used when the index contains
+ * all the records but an empty EntryIDSet should be returned as part
+ * of the optimization.
+ */
+ private static final class NullIndexQuery implements IndexQuery
+ {
+ @Override
+ public EntryIDSet evaluate(LocalizableMessageBuilder debugMessage, StringBuilder indexNameOut)
+ {
+ return newUndefinedSet();
+ }
+
+ @Override
+ public String toString()
+ {
+ return "Null";
+ }
+ }
+
+ /** This class creates an intersection IndexQuery from a collection of IndexQuery objects. */
+ private static final class IntersectionIndexQuery implements IndexQuery
+ {
+ /** Collection of IndexQuery objects. */
+ private final Collection<IndexQuery> subIndexQueries;
+
+ /**
+ * Creates an instance of IntersectionIndexQuery.
+ *
+ * @param subIndexQueries
+ * Collection of IndexQuery objects.
+ */
+ private IntersectionIndexQuery(Collection<IndexQuery> subIndexQueries)
+ {
+ this.subIndexQueries = subIndexQueries;
+ }
+
+ @Override
+ public EntryIDSet evaluate(LocalizableMessageBuilder debugMessage, StringBuilder indexNameOut)
+ {
+ final EntryIDSet entryIDs = newUndefinedSet();
+ for (IndexQuery query : subIndexQueries)
+ {
+ entryIDs.retainAll(query.evaluate(debugMessage, indexNameOut));
+ if (isBelowFilterThreshold(entryIDs))
+ {
+ break;
+ }
+ }
+ return entryIDs;
+ }
+
+ @Override
+ public String toString()
+ {
+ return "Intersection(" + SEPARATOR + Utils.joinAsString(SEPARATOR, subIndexQueries) + ")";
+ }
+ }
+
+ /** This class creates a union of IndexQuery objects. */
+ private static final class UnionIndexQuery implements IndexQuery
+ {
+ /** Collection containing IndexQuery objects. */
+ private final Collection<IndexQuery> subIndexQueries;
+
+ /**
+ * Creates an instance of UnionIndexQuery.
+ *
+ * @param subIndexQueries
+ * The Collection of IndexQuery objects.
+ */
+ private UnionIndexQuery(Collection<IndexQuery> subIndexQueries)
+ {
+ this.subIndexQueries = subIndexQueries;
+ }
+
+ @Override
+ public EntryIDSet evaluate(LocalizableMessageBuilder debugMessage, StringBuilder indexNameOut)
+ {
+ final EntryIDSet entryIDs = newDefinedSet();
+ for (IndexQuery query : subIndexQueries)
+ {
+ entryIDs.addAll(query.evaluate(debugMessage, indexNameOut));
+ if (entryIDs.isDefined() && entryIDs.size() >= CURSOR_ENTRY_LIMIT)
+ {
+ break;
+ }
+ }
+ return entryIDs;
+ }
+
+ @Override
+ public String toString()
+ {
+ return "Union(" + SEPARATOR + Utils.joinAsString(SEPARATOR, subIndexQueries) + ")";
+ }
+ }
+
private static final LocalizedLogger logger = LocalizedLogger.getLoggerForThisClass();
private static final String PRESENCE_INDEX_KEY = "presence";
+ private static final String SEPARATOR = "\n ";
private final ReadableTransaction txn;
/** The Map containing the string type identifier and the corresponding index. */
@@ -241,13 +342,13 @@
@Override
public IndexQuery createIntersectionQuery(Collection<IndexQuery> subqueries)
{
- return IndexQuery.createIntersectionIndexQuery(subqueries);
+ return new IntersectionIndexQuery(subqueries);
}
@Override
public IndexQuery createUnionQuery(Collection<IndexQuery> subqueries)
{
- return IndexQuery.createUnionIndexQuery(subqueries);
+ return new UnionIndexQuery(subqueries);
}
/**
@@ -313,4 +414,14 @@
{
return attributeIndex.getIndexingOptions();
}
+
+ /**
+ * Creates an empty IndexQuery object.
+ *
+ * @return A NullIndexQuery object.
+ */
+ static IndexQuery createNullIndexQuery()
+ {
+ return new NullIndexQuery();
+ }
}
--
Gitblit v1.10.0