From 121886bc0c92389610408e3b415abb992ad8a212 Mon Sep 17 00:00:00 2001 From: "Brian S. O'Neill" Date: Wed, 4 May 2011 00:20:02 +0000 Subject: Add support for Query controller and timeouts; remove vestigial support for interrupts. --- .../carbonado/repo/indexed/IndexedStorage.java | 44 ++++++++++ .../carbonado/repo/indexed/ManagedIndex.java | 18 ++++- .../repo/jdbc/H2ExceptionTransformer.java | 8 +- .../repo/jdbc/JDBCExceptionTransformer.java | 20 +++++ .../amazon/carbonado/repo/jdbc/JDBCStorage.java | 92 ++++++++++++++++++--- .../repo/jdbc/OracleExceptionTransformer.java | 7 ++ .../carbonado/repo/logging/LoggingQuery.java | 94 ++++++++++++++++++++++ .../com/amazon/carbonado/repo/map/MapStorage.java | 49 +++++++++++ .../carbonado/repo/sleepycat/BDBStorage.java | 56 ++++++++++++- 9 files changed, 371 insertions(+), 17 deletions(-) (limited to 'src/main/java/com/amazon/carbonado/repo') diff --git a/src/main/java/com/amazon/carbonado/repo/indexed/IndexedStorage.java b/src/main/java/com/amazon/carbonado/repo/indexed/IndexedStorage.java index 4635f2c..d115a3b 100644 --- a/src/main/java/com/amazon/carbonado/repo/indexed/IndexedStorage.java +++ b/src/main/java/com/amazon/carbonado/repo/indexed/IndexedStorage.java @@ -191,14 +191,26 @@ class IndexedStorage implements Storage, StorageAccess return new MergeSortBuffer(); } + public SortBuffer createSortBuffer(Query.Controller controller) { + return new MergeSortBuffer(controller); + } + public long countAll() throws FetchException { return mMasterStorage.query().count(); } + public long countAll(Query.Controller controller) throws FetchException { + return mMasterStorage.query().count(controller); + } + public Cursor fetchAll() throws FetchException { return mMasterStorage.query().fetch(); } + public Cursor fetchAll(Query.Controller controller) throws FetchException { + return mMasterStorage.query().fetch(controller); + } + public Cursor fetchOne(StorableIndex index, Object[] identityValues) throws FetchException @@ -207,6 +219,15 @@ class IndexedStorage implements Storage, StorageAccess return indexInfo.fetchOne(this, identityValues); } + public Cursor fetchOne(StorableIndex index, + Object[] identityValues, + Query.Controller controller) + throws FetchException + { + ManagedIndex indexInfo = (ManagedIndex) mAllIndexInfoMap.get(index); + return indexInfo.fetchOne(this, identityValues, controller); + } + public Query indexEntryQuery(StorableIndex index) throws FetchException { @@ -221,6 +242,14 @@ class IndexedStorage implements Storage, StorageAccess return indexInfo.fetchFromIndexEntryQuery(this, indexEntryQuery); } + public Cursor fetchFromIndexEntryQuery(StorableIndex index, Query indexEntryQuery, + Query.Controller controller) + throws FetchException + { + ManagedIndex indexInfo = (ManagedIndex) mAllIndexInfoMap.get(index); + return indexInfo.fetchFromIndexEntryQuery(this, indexEntryQuery, controller); + } + public Cursor fetchSubset(StorableIndex index, Object[] identityValues, BoundaryType rangeStartBoundary, @@ -235,6 +264,21 @@ class IndexedStorage implements Storage, StorageAccess throw new UnsupportedOperationException(); } + public Cursor fetchSubset(StorableIndex index, + Object[] identityValues, + BoundaryType rangeStartBoundary, + Object rangeStartValue, + BoundaryType rangeEndBoundary, + Object rangeEndValue, + boolean reverseRange, + boolean reverseOrder, + Query.Controller controller) + throws FetchException + { + // This method should never be called since a query was returned by indexEntryQuery. + throw new UnsupportedOperationException(); + } + private void registerIndex(ManagedIndex managedIndex) throws RepositoryException { diff --git a/src/main/java/com/amazon/carbonado/repo/indexed/ManagedIndex.java b/src/main/java/com/amazon/carbonado/repo/indexed/ManagedIndex.java index 2bb2f49..6c28619 100644 --- a/src/main/java/com/amazon/carbonado/repo/indexed/ManagedIndex.java +++ b/src/main/java/com/amazon/carbonado/repo/indexed/ManagedIndex.java @@ -172,6 +172,13 @@ class ManagedIndex implements IndexEntryAccessor { Cursor fetchOne(IndexedStorage storage, Object[] identityValues) throws FetchException + { + return fetchOne(storage, identityValues, null); + } + + Cursor fetchOne(IndexedStorage storage, Object[] identityValues, + Query.Controller controller) + throws FetchException { Query query = mSingleMatchQuery; @@ -184,13 +191,20 @@ class ManagedIndex implements IndexEntryAccessor { mSingleMatchQuery = query = mIndexEntryStorage.query(filter); } - return fetchFromIndexEntryQuery(storage, query.withValues(identityValues)); + return fetchFromIndexEntryQuery(storage, query.withValues(identityValues), controller); } Cursor fetchFromIndexEntryQuery(IndexedStorage storage, Query indexEntryQuery) throws FetchException { - return new IndexedCursor(indexEntryQuery.fetch(), storage, mAccessor); + return fetchFromIndexEntryQuery(storage, indexEntryQuery, null); + } + + Cursor fetchFromIndexEntryQuery(IndexedStorage storage, Query indexEntryQuery, + Query.Controller controller) + throws FetchException + { + return new IndexedCursor(indexEntryQuery.fetch(controller), storage, mAccessor); } @Override diff --git a/src/main/java/com/amazon/carbonado/repo/jdbc/H2ExceptionTransformer.java b/src/main/java/com/amazon/carbonado/repo/jdbc/H2ExceptionTransformer.java index e760f58..d10856a 100644 --- a/src/main/java/com/amazon/carbonado/repo/jdbc/H2ExceptionTransformer.java +++ b/src/main/java/com/amazon/carbonado/repo/jdbc/H2ExceptionTransformer.java @@ -28,9 +28,15 @@ import java.sql.SQLException; */ class H2ExceptionTransformer extends JDBCExceptionTransformer { public static int DUPLICATE_KEY = 23001; + public static int PROCESSING_CANCELED = 90051; @Override public boolean isUniqueConstraintError(SQLException e) { - return DUPLICATE_KEY == e.getErrorCode(); + return super.isUniqueConstraintError(e) || DUPLICATE_KEY == e.getErrorCode(); + } + + @Override + public boolean isTimeoutError(SQLException e) { + return super.isTimeoutError(e) || PROCESSING_CANCELED == e.getErrorCode(); } } diff --git a/src/main/java/com/amazon/carbonado/repo/jdbc/JDBCExceptionTransformer.java b/src/main/java/com/amazon/carbonado/repo/jdbc/JDBCExceptionTransformer.java index f72c717..4780140 100644 --- a/src/main/java/com/amazon/carbonado/repo/jdbc/JDBCExceptionTransformer.java +++ b/src/main/java/com/amazon/carbonado/repo/jdbc/JDBCExceptionTransformer.java @@ -23,9 +23,11 @@ import java.sql.SQLException; import com.amazon.carbonado.ConstraintException; import com.amazon.carbonado.FetchDeadlockException; import com.amazon.carbonado.FetchException; +import com.amazon.carbonado.FetchTimeoutException; import com.amazon.carbonado.PersistDeadlockException; import com.amazon.carbonado.PersistDeniedException; import com.amazon.carbonado.PersistException; +import com.amazon.carbonado.PersistTimeoutException; import com.amazon.carbonado.UniqueConstraintException; import com.amazon.carbonado.spi.ExceptionTransformer; @@ -59,6 +61,8 @@ class JDBCExceptionTransformer extends ExceptionTransformer { */ public static String SQLSTATE_DEADLOCK_WITH_ROLLBACK = "40001"; + public static String SQLSTATE_PROCESSING_CANCELED = "57014"; + /** * Examines the SQLSTATE code of the given SQL exception and determines if * it is a generic constaint violation. @@ -103,6 +107,16 @@ class JDBCExceptionTransformer extends ExceptionTransformer { return false; } + public boolean isTimeoutError(SQLException e) { + if (e != null) { + String sqlstate = e.getSQLState(); + if (sqlstate != null) { + return SQLSTATE_PROCESSING_CANCELED.equals(sqlstate); + } + } + return false; + } + JDBCExceptionTransformer() { } @@ -117,6 +131,9 @@ class JDBCExceptionTransformer extends ExceptionTransformer { if (isDeadlockError(se)) { return new FetchDeadlockException(e); } + if (isTimeoutError(se)) { + return new FetchTimeoutException(e); + } } return null; } @@ -141,6 +158,9 @@ class JDBCExceptionTransformer extends ExceptionTransformer { if (isDeadlockError(se)) { return new PersistDeadlockException(e); } + if (isTimeoutError(se)) { + return new PersistTimeoutException(e); + } } return null; } diff --git a/src/main/java/com/amazon/carbonado/repo/jdbc/JDBCStorage.java b/src/main/java/com/amazon/carbonado/repo/jdbc/JDBCStorage.java index a49a150..bbe5589 100644 --- a/src/main/java/com/amazon/carbonado/repo/jdbc/JDBCStorage.java +++ b/src/main/java/com/amazon/carbonado/repo/jdbc/JDBCStorage.java @@ -27,6 +27,7 @@ import java.sql.ResultSet; import java.sql.SQLException; import java.util.List; import java.util.Map; +import java.util.concurrent.TimeUnit; import org.apache.commons.logging.LogFactory; @@ -34,6 +35,7 @@ import com.amazon.carbonado.Cursor; import com.amazon.carbonado.FetchException; import com.amazon.carbonado.IsolationLevel; import com.amazon.carbonado.PersistException; +import com.amazon.carbonado.Query; import com.amazon.carbonado.Repository; import com.amazon.carbonado.RepositoryException; import com.amazon.carbonado.Storable; @@ -42,6 +44,7 @@ import com.amazon.carbonado.SupportException; import com.amazon.carbonado.Transaction; import com.amazon.carbonado.Trigger; import com.amazon.carbonado.capability.IndexInfo; +import com.amazon.carbonado.cursor.ControllerCursor; import com.amazon.carbonado.cursor.EmptyCursor; import com.amazon.carbonado.cursor.LimitCursor; import com.amazon.carbonado.filter.AndFilter; @@ -329,6 +332,28 @@ class JDBCStorage extends StandardQueryFactory return new JDBCQuery(filter, values, ordering, hints); } + static PreparedStatement prepareStatement(Connection con, String sql, + Query.Controller controller) + throws SQLException + { + PreparedStatement ps = con.prepareStatement(sql); + + if (controller != null) { + long timeout = controller.getTimeout(); + if (timeout >= 0) { + TimeUnit unit = controller.getTimeoutUnit(); + if (unit != null) { + long seconds = unit.toSeconds(timeout); + int intSeconds = seconds <= 0 ? 1 : + (seconds <= Integer.MAX_VALUE ? ((int) seconds) : 0); + ps.setQueryTimeout(intSeconds); + } + } + } + + return ps; + } + public S instantiate(ResultSet rs) throws SQLException { return (S) mInstanceFactory.instantiate(this, rs, FIRST_RESULT_INDEX); } @@ -668,12 +693,21 @@ class JDBCStorage extends StandardQueryFactory } } + @Override public Cursor fetch(FilterValues values) throws FetchException { + return fetch(values, null); + } + + @Override + public Cursor fetch(FilterValues values, Query.Controller controller) + throws FetchException + { TransactionScope scope = mRepository.localTransactionScope(); boolean forUpdate = scope.isForUpdate(); Connection con = getConnection(); try { - PreparedStatement ps = con.prepareStatement(prepareSelect(values, forUpdate)); + PreparedStatement ps = + prepareStatement(con, prepareSelect(values, forUpdate), controller); Integer fetchSize = mRepository.getFetchSize(); if (fetchSize != null) { ps.setFetchSize(fetchSize); @@ -681,7 +715,8 @@ class JDBCStorage extends StandardQueryFactory try { setParameters(ps, values); - return new JDBCCursor(JDBCStorage.this, scope, con, ps); + return ControllerCursor.apply + (new JDBCCursor(JDBCStorage.this, scope, con, ps), controller); } catch (Exception e) { // in case of exception, close statement try { @@ -705,6 +740,14 @@ class JDBCStorage extends StandardQueryFactory @Override public Cursor fetchSlice(FilterValues values, long from, Long to) throws FetchException + { + return fetchSlice(values, from, to, null); + } + + @Override + public Cursor fetchSlice(FilterValues values, long from, Long to, + Query.Controller controller) + throws FetchException { if (to != null && (to - from) <= 0) { return EmptyCursor.the(); @@ -716,17 +759,17 @@ class JDBCStorage extends StandardQueryFactory switch (option) { case NOT_SUPPORTED: default: - return super.fetchSlice(values, from, to); + return super.fetchSlice(values, from, to, controller); case LIMIT_ONLY: if (from > 0 || to == null) { - return super.fetchSlice(values, from, to); + return super.fetchSlice(values, from, to, controller); } select = prepareSelect(values, false); select = mSupportStrategy.buildSelectWithSlice(select, false, true); break; case OFFSET_ONLY: if (from <= 0) { - return super.fetchSlice(values, from, to); + return super.fetchSlice(values, from, to, controller); } select = prepareSelect(values, false); select = mSupportStrategy.buildSelectWithSlice(select, true, false); @@ -746,7 +789,7 @@ class JDBCStorage extends StandardQueryFactory Connection con = getConnection(); try { - PreparedStatement ps = con.prepareStatement(select); + PreparedStatement ps = prepareStatement(con, select, controller); Integer fetchSize = mRepository.getFetchSize(); if (fetchSize != null) { ps.setFetchSize(fetchSize); @@ -760,7 +803,10 @@ class JDBCStorage extends StandardQueryFactory switch (option) { case OFFSET_ONLY: ps.setLong(psOrdinal, from); - Cursor c = new JDBCCursor(JDBCStorage.this, scope, con, ps); + Cursor c = + ControllerCursor.apply + (new JDBCCursor(JDBCStorage.this, scope, con, ps), + controller); return new LimitCursor(c, to - from); case LIMIT_AND_OFFSET: ps.setLong(psOrdinal, to - from); @@ -782,7 +828,8 @@ class JDBCStorage extends StandardQueryFactory ps.setLong(psOrdinal, to); } - return new JDBCCursor(JDBCStorage.this, scope, con, ps); + return ControllerCursor.apply + (new JDBCCursor(JDBCStorage.this, scope, con, ps), controller); } catch (Exception e) { // in case of exception, close statement try { @@ -805,9 +852,17 @@ class JDBCStorage extends StandardQueryFactory @Override public long count(FilterValues values) throws FetchException { + return count(values, null); + } + + @Override + public long count(FilterValues values, Query.Controller controller) + throws FetchException + { Connection con = getConnection(); try { - PreparedStatement ps = con.prepareStatement(prepareCount(values)); + PreparedStatement ps = prepareStatement(con, prepareCount(values), controller); + try { setParameters(ps, values); ResultSet rs = ps.executeQuery(); @@ -827,10 +882,12 @@ class JDBCStorage extends StandardQueryFactory } } + @Override public Filter getFilter() { return mFilter; } + @Override public OrderingList getOrdering() { return mOrdering; } @@ -846,6 +903,7 @@ class JDBCStorage extends StandardQueryFactory return true; } + @Override public boolean printPlan(Appendable app, int indentLevel, FilterValues values) throws IOException { @@ -862,7 +920,9 @@ class JDBCStorage extends StandardQueryFactory /** * Delete operation is included in cursor factory for ease of implementation. */ - int executeDelete(FilterValues filterValues) throws PersistException { + int executeDelete(FilterValues filterValues, Query.Controller controller) + throws PersistException + { Connection con; try { con = getConnection(); @@ -870,7 +930,8 @@ class JDBCStorage extends StandardQueryFactory throw e.toPersistException(); } try { - PreparedStatement ps = con.prepareStatement(prepareDelete(filterValues)); + PreparedStatement ps = + prepareStatement(con, prepareDelete(filterValues), controller); try { setParameters(ps, filterValues); return ps.executeUpdate(); @@ -976,13 +1037,18 @@ class JDBCStorage extends StandardQueryFactory @Override public void deleteAll() throws PersistException { + deleteAll(null); + } + + @Override + public void deleteAll(Controller controller) throws PersistException { if (mTriggerManager.getDeleteTrigger() != null) { // Super implementation loads one at time and calls // delete. This allows delete trigger to be invoked on each. - super.deleteAll(); + super.deleteAll(controller); } else { try { - ((Executor) executor()).executeDelete(getFilterValues()); + ((Executor) executor()).executeDelete(getFilterValues(), controller); } catch (RepositoryException e) { throw e.toPersistException(); } diff --git a/src/main/java/com/amazon/carbonado/repo/jdbc/OracleExceptionTransformer.java b/src/main/java/com/amazon/carbonado/repo/jdbc/OracleExceptionTransformer.java index ad63941..ebaafd7 100644 --- a/src/main/java/com/amazon/carbonado/repo/jdbc/OracleExceptionTransformer.java +++ b/src/main/java/com/amazon/carbonado/repo/jdbc/OracleExceptionTransformer.java @@ -32,6 +32,8 @@ class OracleExceptionTransformer extends JDBCExceptionTransformer { public static int DEADLOCK_DETECTED = 60; + public static int PROCESSING_CANCELED = 1013; + @Override public boolean isUniqueConstraintError(SQLException e) { if (isConstraintError(e)) { @@ -63,4 +65,9 @@ class OracleExceptionTransformer extends JDBCExceptionTransformer { } return false; } + + @Override + public boolean isTimeoutError(SQLException e) { + return super.isTimeoutError(e) || e != null && PROCESSING_CANCELED == e.getErrorCode(); + } } diff --git a/src/main/java/com/amazon/carbonado/repo/logging/LoggingQuery.java b/src/main/java/com/amazon/carbonado/repo/logging/LoggingQuery.java index 08be6e3..5dc4d3b 100644 --- a/src/main/java/com/amazon/carbonado/repo/logging/LoggingQuery.java +++ b/src/main/java/com/amazon/carbonado/repo/logging/LoggingQuery.java @@ -164,6 +164,15 @@ class LoggingQuery implements Query { return mQuery.fetch(); } + @Override + public Cursor fetch(Controller controller) throws FetchException { + Log log = mStorage.mLog; + if (log.isEnabled()) { + log.write("Query.fetch(controller) on " + this + ", controller: " + controller); + } + return mQuery.fetch(controller); + } + @Override public Cursor fetchSlice(long from, Long to) throws FetchException { Log log = mStorage.mLog; @@ -174,6 +183,16 @@ class LoggingQuery implements Query { return mQuery.fetchSlice(from, to); } + @Override + public Cursor fetchSlice(long from, Long to, Controller controller) throws FetchException { + Log log = mStorage.mLog; + if (log.isEnabled()) { + log.write("Query.fetchSlice(start, to, controller) on " + this + + ", from: " + from + ", to: " + to + ", controller: " + controller); + } + return mQuery.fetchSlice(from, to, controller); + } + @Override public Cursor fetchAfter(T start) throws FetchException { Log log = mStorage.mLog; @@ -183,6 +202,18 @@ class LoggingQuery implements Query { return mQuery.fetchAfter(start); } + @Override + public Cursor fetchAfter(T start, Controller controller) + throws FetchException + { + Log log = mStorage.mLog; + if (log.isEnabled()) { + log.write("Query.fetchAfter(start, controller) on " + this + ", start: " + start + + ", controller: " + controller); + } + return mQuery.fetchAfter(start, controller); + } + @Override public S loadOne() throws FetchException { Log log = mStorage.mLog; @@ -192,6 +223,15 @@ class LoggingQuery implements Query { return mQuery.loadOne(); } + @Override + public S loadOne(Controller controller) throws FetchException { + Log log = mStorage.mLog; + if (log.isEnabled()) { + log.write("Query.loadOne() on " + this + ", controller: " + controller); + } + return mQuery.loadOne(controller); + } + @Override public S tryLoadOne() throws FetchException { Log log = mStorage.mLog; @@ -201,6 +241,15 @@ class LoggingQuery implements Query { return mQuery.tryLoadOne(); } + @Override + public S tryLoadOne(Controller controller) throws FetchException { + Log log = mStorage.mLog; + if (log.isEnabled()) { + log.write("Query.tryLoadOne(controller) on " + this + ", controller: " + controller); + } + return mQuery.tryLoadOne(controller); + } + @Override public void deleteOne() throws PersistException { Log log = mStorage.mLog; @@ -210,6 +259,15 @@ class LoggingQuery implements Query { mQuery.deleteOne(); } + @Override + public void deleteOne(Controller controller) throws PersistException { + Log log = mStorage.mLog; + if (log.isEnabled()) { + log.write("Query.deleteOne(controller) on " + this + ", controller: " + controller); + } + mQuery.deleteOne(controller); + } + @Override public boolean tryDeleteOne() throws PersistException { Log log = mStorage.mLog; @@ -219,6 +277,15 @@ class LoggingQuery implements Query { return mQuery.tryDeleteOne(); } + @Override + public boolean tryDeleteOne(Controller controller) throws PersistException { + Log log = mStorage.mLog; + if (log.isEnabled()) { + log.write("Query.tryDeleteOne(controller) on " + this + ", controller: " + controller); + } + return mQuery.tryDeleteOne(controller); + } + @Override public void deleteAll() throws PersistException { Log log = mStorage.mLog; @@ -228,6 +295,15 @@ class LoggingQuery implements Query { mQuery.deleteAll(); } + @Override + public void deleteAll(Controller controller) throws PersistException { + Log log = mStorage.mLog; + if (log.isEnabled()) { + log.write("Query.deleteAll(controller) on " + this + ", controller: " + controller); + } + mQuery.deleteAll(controller); + } + @Override public long count() throws FetchException { Log log = mStorage.mLog; @@ -237,6 +313,15 @@ class LoggingQuery implements Query { return mQuery.count(); } + @Override + public long count(Controller controller) throws FetchException { + Log log = mStorage.mLog; + if (log.isEnabled()) { + log.write("Query.count(controller) on " + this + ", controller: " + controller); + } + return mQuery.count(controller); + } + @Override public boolean exists() throws FetchException { Log log = mStorage.mLog; @@ -246,6 +331,15 @@ class LoggingQuery implements Query { return mQuery.exists(); } + @Override + public boolean exists(Controller controller) throws FetchException { + Log log = mStorage.mLog; + if (log.isEnabled()) { + log.write("Query.exists(controller) on " + this + ", controller: " + controller); + } + return mQuery.exists(controller); + } + @Override public boolean printNative() { return mQuery.printNative(); diff --git a/src/main/java/com/amazon/carbonado/repo/map/MapStorage.java b/src/main/java/com/amazon/carbonado/repo/map/MapStorage.java index c84d8e3..c9c17b6 100644 --- a/src/main/java/com/amazon/carbonado/repo/map/MapStorage.java +++ b/src/main/java/com/amazon/carbonado/repo/map/MapStorage.java @@ -47,6 +47,7 @@ import com.amazon.carbonado.Trigger; import com.amazon.carbonado.capability.IndexInfo; import com.amazon.carbonado.cursor.ArraySortBuffer; +import com.amazon.carbonado.cursor.ControllerCursor; import com.amazon.carbonado.cursor.EmptyCursor; import com.amazon.carbonado.cursor.FilteredCursor; import com.amazon.carbonado.cursor.SingletonCursor; @@ -540,6 +541,10 @@ class MapStorage } public long countAll() throws FetchException { + return countAll(null); + } + + public long countAll(Query.Controller controller) throws FetchException { try { TransactionScope scope = mRepo.localTransactionScope(); MapTransaction txn = scope.getTxn(); @@ -578,8 +583,19 @@ class MapStorage } } + public Cursor fetchAll(Query.Controller controller) throws FetchException { + return ControllerCursor.apply(fetchAll(), controller); + } + public Cursor fetchOne(StorableIndex index, Object[] identityValues) throws FetchException + { + return fetchOne(index, identityValues, null); + } + + public Cursor fetchOne(StorableIndex index, Object[] identityValues, + Query.Controller controller) + throws FetchException { try { S key = prepare(); @@ -643,6 +659,12 @@ class MapStorage return null; } + public Cursor fetchFromIndexEntryQuery(StorableIndex index, Query indexEntryQuery, + Query.Controller controller) + { + return null; + } + public Cursor fetchSubset(StorableIndex index, Object[] identityValues, BoundaryType rangeStartBoundary, @@ -770,6 +792,28 @@ class MapStorage return cursor; } + public Cursor fetchSubset(StorableIndex index, + Object[] identityValues, + BoundaryType rangeStartBoundary, + Object rangeStartValue, + BoundaryType rangeEndBoundary, + Object rangeEndValue, + boolean reverseRange, + boolean reverseOrder, + Query.Controller controller) + throws FetchException + { + return ControllerCursor.apply(fetchSubset(index, + identityValues, + rangeStartBoundary, + rangeStartValue, + rangeEndBoundary, + rangeEndValue, + reverseRange, + reverseOrder), + controller); + } + private List> createPkPropList() { return new ArrayList>(mInfo.getPrimaryKey().getProperties()); } @@ -806,6 +850,11 @@ class MapStorage return new ArraySortBuffer(); } + public SortBuffer createSortBuffer(Query.Controller controller) { + // ArraySortBuffer doesn't support controller. + return new ArraySortBuffer(); + } + public static interface InstanceFactory { Storable instantiate(DelegateSupport support); } diff --git a/src/main/java/com/amazon/carbonado/repo/sleepycat/BDBStorage.java b/src/main/java/com/amazon/carbonado/repo/sleepycat/BDBStorage.java index f4d8f24..c0f882e 100644 --- a/src/main/java/com/amazon/carbonado/repo/sleepycat/BDBStorage.java +++ b/src/main/java/com/amazon/carbonado/repo/sleepycat/BDBStorage.java @@ -45,6 +45,7 @@ import com.amazon.carbonado.UniqueConstraintException; import com.amazon.carbonado.capability.IndexInfo; +import com.amazon.carbonado.cursor.ControllerCursor; import com.amazon.carbonado.cursor.EmptyCursor; import com.amazon.carbonado.cursor.MergeSortBuffer; import com.amazon.carbonado.cursor.SingletonCursor; @@ -263,22 +264,45 @@ abstract class BDBStorage implements Storage, Storag return new MergeSortBuffer(); } + public SortBuffer createSortBuffer(Query.Controller controller) { + return new MergeSortBuffer(controller); + } + public long countAll() throws FetchException { // Return -1 to indicate default algorithm should be used. return -1; } + public long countAll(Query.Controller controller) throws FetchException { + // Return -1 to indicate default algorithm should be used. + return -1; + } + public Cursor fetchAll() throws FetchException { + return fetchAll(null); + } + + public Cursor fetchAll(Query.Controller controller) throws FetchException { return fetchSubset(null, null, BoundaryType.OPEN, null, BoundaryType.OPEN, null, - false, false); + false, false, + controller); } public Cursor fetchOne(StorableIndex index, Object[] identityValues) throws FetchException { + return fetchOne(index, identityValues, null); + } + + public Cursor fetchOne(StorableIndex index, + Object[] identityValues, + Query.Controller controller) + throws FetchException + { + // Note: Controller is never called. byte[] key = mStorableCodec.encodePrimaryKey(identityValues); byte[] value = mRawSupport.tryLoad(null, key); if (value == null) { @@ -296,6 +320,13 @@ abstract class BDBStorage implements Storage, Storag throw new UnsupportedOperationException(); } + public Cursor fetchFromIndexEntryQuery(StorableIndex index, Query indexEntryQuery, + Query.Controller controller) + { + // This method should never be called since null was returned by indexEntryQuery. + throw new UnsupportedOperationException(); + } + public Cursor fetchSubset(StorableIndex index, Object[] identityValues, BoundaryType rangeStartBoundary, @@ -378,6 +409,7 @@ abstract class BDBStorage implements Storage, Storag getPrimaryDatabase()); cursor.open(); + return cursor; } catch (Exception e) { throw toFetchException(e); @@ -387,6 +419,28 @@ abstract class BDBStorage implements Storage, Storag } } + public Cursor fetchSubset(StorableIndex index, + Object[] identityValues, + BoundaryType rangeStartBoundary, + Object rangeStartValue, + BoundaryType rangeEndBoundary, + Object rangeEndValue, + boolean reverseRange, + boolean reverseOrder, + Query.Controller controller) + throws FetchException + { + return ControllerCursor.apply(fetchSubset(index, + identityValues, + rangeStartBoundary, + rangeStartValue, + rangeEndBoundary, + rangeEndValue, + reverseRange, + reverseOrder), + controller); + } + private byte[] createBound(Object[] exactValues, byte[] exactKey, Object rangeValue, StorableCodec codec) { Object[] values = {rangeValue}; -- cgit v1.2.3