Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature for uniqueindex and equals performance changes discussed in issue #106 #107

Open
wants to merge 6 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,8 @@
import com.googlecode.cqengine.persistence.support.ObjectSet;
import com.googlecode.cqengine.persistence.support.ObjectStore;
import com.googlecode.cqengine.persistence.support.ObjectStoreAsSet;
import com.googlecode.cqengine.persistence.support.PersistenceFlags;
import com.googlecode.cqengine.query.Query;
import com.googlecode.cqengine.query.option.EngineFlags;
import com.googlecode.cqengine.query.option.FlagsEnabled;
import com.googlecode.cqengine.query.option.QueryOptions;
import com.googlecode.cqengine.resultset.ResultSet;
Expand Down Expand Up @@ -492,7 +492,7 @@ protected QueryOptions openRequestScopeResourcesIfNecessary(QueryOptions queryOp
if (!(persistence instanceof OnHeapPersistence)) {
persistence.openRequestScopeResources(queryOptions);
}
queryOptions.put(Persistence.class, persistence);
queryOptions.setPersistence(persistence);
return queryOptions;
}

Expand Down Expand Up @@ -554,6 +554,7 @@ public String toString() {
* @param queryOptions The query options for the request
*/
protected static void flagAsReadRequest(QueryOptions queryOptions) {
FlagsEnabled.forQueryOptions(queryOptions).add(PersistenceFlags.READ_REQUEST);
FlagsEnabled flagsEnabled = FlagsEnabled.forQueryOptions(queryOptions);
flagsEnabled.add(EngineFlags.READ_REQUEST);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
import com.googlecode.cqengine.persistence.support.ObjectStore;
import com.googlecode.cqengine.query.Query;
import com.googlecode.cqengine.query.option.ArgumentValidationOption;
import com.googlecode.cqengine.query.option.EngineFlags;
import com.googlecode.cqengine.query.option.FlagsEnabled;
import com.googlecode.cqengine.query.option.QueryOptions;
import com.googlecode.cqengine.resultset.ResultSet;
Expand Down Expand Up @@ -93,11 +94,6 @@
*/
public class TransactionalIndexedCollection<O> extends ConcurrentIndexedCollection<O> {

/**
* A query option flag which can be supplied to the update method to control the replacement behaviour.
*/
public static final String STRICT_REPLACEMENT = "STRICT_REPLACEMENT";

final Class<O> objectType;
volatile Version currentVersion;
final Object writeMutex = new Object();
Expand Down Expand Up @@ -239,7 +235,7 @@ public boolean update(final Iterable<O> objectsToRemove, final Iterable<O> objec
if (!objectsToRemoveIterator.hasNext() && !objectsToAddIterator.hasNext()) {
return false;
}
if (FlagsEnabled.isFlagEnabled(queryOptions, STRICT_REPLACEMENT)) {
if (FlagsEnabled.isFlagEnabled(queryOptions, EngineFlags.STRICT_REPLACEMENT)) {
if (!objectStoreContainsAllIterable(objectStore, objectsToRemove, queryOptions)) {
return false;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -117,8 +117,8 @@ public void init(final ObjectStore<O> objectStore, final QueryOptions queryOptio
forEachIndexDo(new IndexOperation<O>() {
@Override
public boolean perform(Index<O> index) {
queryOptions.put(QueryEngine.class, this);
queryOptions.put(Persistence.class, persistence);
queryOptions.setQueryEngine(CollectionQueryEngine.this);
queryOptions.setPersistence(persistence);
index.init(objectStore, queryOptions);
return true;
}
Expand Down Expand Up @@ -193,8 +193,8 @@ <A> void addAttributeIndex(AttributeIndex<A, O> attributeIndex, QueryOptions que
// We put UniqueIndexes in a separate map too, to access directly...
uniqueIndexes.put(attribute, attributeIndex);
}
queryOptions.put(QueryEngine.class, this);
queryOptions.put(Persistence.class, persistence);
queryOptions.setQueryEngine(this);
queryOptions.setPersistence(persistence);
attributeIndex.init(objectStore, queryOptions);
}

Expand All @@ -210,8 +210,8 @@ void addStandingQueryIndex(Index<O> standingQueryIndex, Query<O> standingQuery,
if (existingIndex != null) {
throw new IllegalStateException("An index has already been added for standing query: " + standingQuery);
}
queryOptions.put(QueryEngine.class, this);
queryOptions.put(Persistence.class, persistence);
queryOptions.setQueryEngine(this);
queryOptions.setPersistence(persistence);
standingQueryIndex.init(objectStore, queryOptions);
}

Expand All @@ -225,8 +225,8 @@ void addCompoundIndex(CompoundIndex<O> compoundIndex, CompoundAttribute<O> compo
if (existingIndex != null) {
throw new IllegalStateException("An index has already been added for compound attribute: " + compoundAttribute);
}
queryOptions.put(QueryEngine.class, this);
queryOptions.put(Persistence.class, persistence);
queryOptions.setQueryEngine(this);
queryOptions.setPersistence(persistence);
compoundIndex.init(objectStore, queryOptions);
}

Expand Down Expand Up @@ -345,16 +345,22 @@ <A> ResultSet<O> getResultSetWithLowestRetrievalCost(SimpleQuery<O, A> query, Qu
// to the #retrieveRecursive() method.
@Override
public ResultSet<O> retrieve(final Query<O> query, final QueryOptions queryOptions) {
if(query instanceof Equal) {
Index<O> uniqueIndex = uniqueIndexes.get(((Equal)query).getAttribute());
if (uniqueIndex != null && uniqueIndex.supportsQuery(query, queryOptions)) {
return uniqueIndex.retrieve(query, queryOptions);
}
}
@SuppressWarnings("unchecked")
OrderByOption<O> orderByOption = (OrderByOption<O>) queryOptions.get(OrderByOption.class);
OrderByOption<O> orderByOption = (OrderByOption<O>) queryOptions.getOrderByOption();

// Store the root query in the queryOptions, so that when retrieveRecursive() examines child branches, that
// both the branch query and the root query will be available to PartialIndexes so they may determine if they
// can be used to accelerate the overall query...
queryOptions.put(ROOT_QUERY, query);
queryOptions.setRootQuery(query);

// Log decisions made to the query log, if provided...
final QueryLog queryLog = queryOptions.get(QueryLog.class); // might be null
final QueryLog queryLog = queryOptions.getQueryLog(); // might be null

SortedKeyStatisticsAttributeIndex<?, O> indexForOrdering = null;
if (orderByOption != null) {
Expand Down Expand Up @@ -750,7 +756,7 @@ public boolean isValid(O object, QueryOptions queryOptions) {

static <O, A extends Comparable<A>> Persistence<O, A> getPersistenceFromQueryOptions(QueryOptions queryOptions) {
@SuppressWarnings("unchecked")
Persistence<O, A> persistence = (Persistence<O, A>) queryOptions.get(Persistence.class);
Persistence<O, A> persistence = (Persistence<O, A>) queryOptions.getPersistence();
if (persistence == null) {
throw new IllegalStateException("A required Persistence object was not supplied in query options");
}
Expand Down Expand Up @@ -959,11 +965,15 @@ else if (query instanceof Or) {
// The Or query is disjoint, so there is no need to perform deduplication on its results.
// Wrap the QueryOptions object in another which omits the DeduplicationOption if it is requested
// when evaluating this Or statement...
queryOptionsForOrUnion = new QueryOptions(queryOptions.getOptions()) {
queryOptionsForOrUnion = new QueryOptions(queryOptions) {
@Override
public Object get(Object key) {
return DeduplicationOption.class.equals(key) ? null : super.get(key);
}
@Override
public DeduplicationOption getDeduplicationOption() {
return null;
}
};
}
else {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
import com.googlecode.cqengine.persistence.support.ObjectSet;
import com.googlecode.cqengine.persistence.support.ObjectStore;
import com.googlecode.cqengine.query.Query;
import com.googlecode.cqengine.query.option.EngineFlags;
import com.googlecode.cqengine.query.option.FlagsEnabled;
import com.googlecode.cqengine.query.option.QueryOptions;
import com.googlecode.cqengine.query.simple.*;
Expand Down Expand Up @@ -413,7 +414,7 @@ public QueryOptions getQueryOptions() {
* {@inheritDoc}
* <p/>
* Note objects can be imported into this index rapidly via this method,
* by setting flag {@link SQLiteIndexFlags#BULK_IMPORT}. See documentation on that flag for details and caveats.
* by setting flag {@link EngineFlags#BULK_IMPORT}. See documentation on that flag for details and caveats.
*/
@Override
public boolean addAll(final ObjectSet<O> objectSet, final QueryOptions queryOptions) {
Expand All @@ -430,8 +431,8 @@ public boolean addAll(final ObjectSet<O> objectSet, final QueryOptions queryOpti

// Handle the SQLite indexes on the table
final BulkImportExternallyManged bulkImportExternallyManged = queryOptions.get(BulkImportExternallyManged.class);
final boolean isBulkImport = bulkImportExternallyManged == null && FlagsEnabled.isFlagEnabled(queryOptions, SQLiteIndexFlags.BULK_IMPORT);
final boolean isSuspendSyncAndJournaling = FlagsEnabled.isFlagEnabled(queryOptions, SQLiteIndexFlags.BULK_IMPORT_SUSPEND_SYNC_AND_JOURNALING);
final boolean isBulkImport = bulkImportExternallyManged == null && FlagsEnabled.isFlagEnabled(queryOptions, EngineFlags.BULK_IMPORT);
final boolean isSuspendSyncAndJournaling = FlagsEnabled.isFlagEnabled(queryOptions, EngineFlags.BULK_IMPORT_SUSPEND_SYNC_AND_JOURNALING);
if ((bulkImportExternallyManged != null || isBulkImport) && !objectSet.isEmpty()) {
// Drop the SQLite index temporarily (if any) to speed up bulk import...
DBQueries.dropIndexOnTable(tableName, connection);
Expand Down Expand Up @@ -537,7 +538,7 @@ public boolean removeAll(final ObjectSet<O> objectSet, final QueryOptions queryO
}

final Connection connection = connectionManager.getConnection(this, queryOptions);
final boolean isBulkImport = queryOptions.get(BulkImportExternallyManged.class) != null || FlagsEnabled.isFlagEnabled(queryOptions, SQLiteIndexFlags.BULK_IMPORT);
final boolean isBulkImport = queryOptions.get(BulkImportExternallyManged.class) != null || FlagsEnabled.isFlagEnabled(queryOptions, EngineFlags.BULK_IMPORT);
if (isBulkImport) {
// It's a bulk import, avoid creating the index on the SQLite table...
DBQueries.createIndexTable(tableName, primaryKeyAttribute.getAttributeType(), getAttribute().getAttributeType(), connection);
Expand Down Expand Up @@ -637,7 +638,7 @@ void createTableIndexIfNeeded(final Connection connection){
* @throws IllegalStateException if the ConnectionManager is not found.
*/
ConnectionManager getConnectionManager(final QueryOptions queryOptions){
ConnectionManager connectionManager = queryOptions.get(ConnectionManager.class);
ConnectionManager connectionManager = queryOptions.getConnectionManager();
if (connectionManager == null)
throw new IllegalStateException("A ConnectionManager is required but was not provided in the QueryOptions.");
return connectionManager;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ public Index<O> getEffectiveIndex() {

static <O, K extends Comparable<K>> Persistence<O, K> getPersistenceFromQueryOptions(QueryOptions queryOptions) {
@SuppressWarnings("unchecked")
Persistence<O, K> persistence = (Persistence<O, K>) queryOptions.get(Persistence.class);
Persistence<O, K> persistence = (Persistence<O, K>) queryOptions.getPersistence();
if (persistence == null) {
throw new IllegalStateException("A required Persistence object was not supplied in query options");
}
Expand All @@ -90,7 +90,7 @@ static <O, K extends Comparable<K>> Persistence<O, K> getPersistenceFromQueryOpt

static <O> QueryEngine<O> getQueryEngineFromQueryOptions(QueryOptions queryOptions) {
@SuppressWarnings("unchecked")
QueryEngine<O> queryEngine = (QueryEngine<O>) queryOptions.get(QueryEngine.class);
QueryEngine<O> queryEngine = (QueryEngine<O>) queryOptions.getQueryEngine();
if (queryEngine == null) {
throw new IllegalStateException("The QueryEngine was not supplied in query options");
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,14 +25,6 @@
*/
public class SQLiteIndexFlags {

/**
* A flag which if enabled causes the SQLiteIndex to temporarily drop the index on a table prior to adding objects,
* then to restore the index after objects have been added.
* <p/>
* This should not be used if other concurrent operations might also be ongoing on the collection. It is intended
* for use when the collection is first being populated or similar, such as at application startup.
*/
public static String BULK_IMPORT = "BULK_IMPORT";

/**
* <p> A 2-values flag that enables externally managed bulk import and specifies it's status.
Expand All @@ -49,11 +41,4 @@ public enum BulkImportExternallyManged {
LAST;
};

/**
* <p> Switches off the 'synchronous' and 'journal_mode' pragmas before executing a bulk import.
* Executing a bulk import with 'synchronous' and 'journal_mode' OFF can significantly increase the performances of the operation
* at a cost of a slightly higher risk of database corruption in case of system crashes or the power loses.
* <p> The default values will be re-instated after the import.
*/
public static String BULK_IMPORT_SUSPEND_SYNC_AND_JOURNALING = "BULK_IMPORT_SUSPEND_SYNC_AND_JOURNALING";
}
Original file line number Diff line number Diff line change
Expand Up @@ -71,10 +71,10 @@ public void close() {
* @return The existing QueryOptions's CloseableRequestResources or a new instance.
*/
public static CloseableRequestResources forQueryOptions(final QueryOptions queryOptions) {
CloseableRequestResources closeableRequestResources = queryOptions.get(CloseableRequestResources.class);
CloseableRequestResources closeableRequestResources = queryOptions.getCloseableRequestResources();
if (closeableRequestResources == null) {
closeableRequestResources = new CloseableRequestResources();
queryOptions.put(CloseableRequestResources.class, closeableRequestResources);
queryOptions.setCloseableRequestResources(closeableRequestResources);
}
return closeableRequestResources;
}
Expand All @@ -86,7 +86,7 @@ public static CloseableRequestResources forQueryOptions(final QueryOptions query
* @param queryOptions The {@link QueryOptions}
*/
public static void closeForQueryOptions(QueryOptions queryOptions) {
closeQuietly(queryOptions.get(CloseableRequestResources.class));
closeQuietly(queryOptions.getCloseableRequestResources());

}
public static void closeQuietly(Closeable closeable) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -138,7 +138,7 @@ public AttributeIndex<A, O> getBackingIndex() {
public boolean supportsQuery(Query<O> query, QueryOptions queryOptions) {
// Extract the root query from the query options, and check if it contains the filter query...
@SuppressWarnings("unchecked")
Query<O> rootQuery = (Query<O>) queryOptions.get(CollectionQueryEngine.ROOT_QUERY);
Query<O> rootQuery = (Query<O>) queryOptions.getRootQuery();

return supportsQueryInternal(backingIndex(), filterQuery, rootQuery, query, queryOptions);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -173,8 +173,8 @@ else if (!primaryKeyAttribute.equals(persistence.getPrimaryKeyAttribute())) {
*/
@Override
public void openRequestScopeResources(QueryOptions queryOptions) {
if (queryOptions.get(ConnectionManager.class) == null) {
queryOptions.put(ConnectionManager.class, new RequestScopeConnectionManager(this));
if (queryOptions.getConnectionManager() == null) {
queryOptions.setConnectionManager(new RequestScopeConnectionManager(this));
}
}

Expand All @@ -186,7 +186,7 @@ public void openRequestScopeResources(QueryOptions queryOptions) {
*/
@Override
public void closeRequestScopeResources(QueryOptions queryOptions) {
ConnectionManager connectionManager = queryOptions.get(ConnectionManager.class);
ConnectionManager connectionManager = queryOptions.getConnectionManager();
if (connectionManager instanceof RequestScopeConnectionManager) {
((RequestScopeConnectionManager) connectionManager).close();
queryOptions.remove(ConnectionManager.class);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -190,8 +190,8 @@ public SQLiteDiskIdentityIndex<A, O> createIdentityIndex() {
*/
@Override
public void openRequestScopeResources(QueryOptions queryOptions) {
if (queryOptions.get(ConnectionManager.class) == null) {
queryOptions.put(ConnectionManager.class, new RequestScopeConnectionManager(this));
if (queryOptions.getConnectionManager() == null) {
queryOptions.setConnectionManager(new RequestScopeConnectionManager(this));
}
}

Expand All @@ -203,7 +203,7 @@ public void openRequestScopeResources(QueryOptions queryOptions) {
*/
@Override
public void closeRequestScopeResources(QueryOptions queryOptions) {
ConnectionManager connectionManager = queryOptions.get(ConnectionManager.class);
ConnectionManager connectionManager = queryOptions.getConnectionManager();
if (connectionManager instanceof RequestScopeConnectionManager) {
((RequestScopeConnectionManager) connectionManager).close();
queryOptions.remove(ConnectionManager.class);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
import com.googlecode.cqengine.persistence.disk.DiskPersistence;
import com.googlecode.cqengine.persistence.support.sqlite.SQLiteObjectStore;
import com.googlecode.cqengine.persistence.support.sqlite.SQLiteOffHeapIdentityIndex;
import com.googlecode.cqengine.query.option.EngineFlags;
import com.googlecode.cqengine.query.option.QueryOptions;
import org.sqlite.SQLiteConfig;
import org.sqlite.SQLiteDataSource;
Expand All @@ -43,7 +44,6 @@
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;

import static com.googlecode.cqengine.persistence.support.PersistenceFlags.READ_REQUEST;
import static com.googlecode.cqengine.query.QueryFactory.noQueryOptions;
import static com.googlecode.cqengine.query.option.FlagsEnabled.isFlagEnabled;

Expand Down Expand Up @@ -136,7 +136,7 @@ public String getInstanceName() {
@Override
public Connection getConnection(Index<?> index, QueryOptions queryOptions) {
// Acquire a read lock IFF the READ_REQUEST flag has been set, otherwise acquire a write lock by default...
final Lock connectionLock = isFlagEnabled(queryOptions, READ_REQUEST)
final Lock connectionLock = isFlagEnabled(queryOptions, EngineFlags.READ_REQUEST)
? readWriteLock.readLock() : readWriteLock.writeLock();

connectionLock.lock();
Expand Down Expand Up @@ -268,8 +268,8 @@ public SQLiteOffHeapIdentityIndex<A, O> createIdentityIndex() {
*/
@Override
public void openRequestScopeResources(QueryOptions queryOptions) {
if (queryOptions.get(ConnectionManager.class) == null) {
queryOptions.put(ConnectionManager.class, new RequestScopeConnectionManager(this));
if (queryOptions.getConnectionManager() == null) {
queryOptions.setConnectionManager(new RequestScopeConnectionManager(this));
}
}

Expand All @@ -281,7 +281,7 @@ public void openRequestScopeResources(QueryOptions queryOptions) {
*/
@Override
public void closeRequestScopeResources(QueryOptions queryOptions) {
ConnectionManager connectionManager = queryOptions.get(ConnectionManager.class);
ConnectionManager connectionManager = queryOptions.getConnectionManager();
if (connectionManager instanceof RequestScopeConnectionManager) {
((RequestScopeConnectionManager) connectionManager).close();
queryOptions.remove(ConnectionManager.class);
Expand Down
Loading