Merge lp:~nwilliams/akiban-server/abstract-store into lp:~akiban-technologies/akiban-server/trunk

Proposed by Nathan Williams
Status: Merged
Merged at revision: 2659
Proposed branch: lp:~nwilliams/akiban-server/abstract-store
Merge into: lp:~akiban-technologies/akiban-server/trunk
Diff against target: 2631 lines (+822/-847)
24 files modified
src/main/java/com/akiban/ais/model/UserTable.java (+4/-0)
src/main/java/com/akiban/qp/persistitadapter/OneTableRowCollector.java (+4/-6)
src/main/java/com/akiban/qp/persistitadapter/OperatorBasedRowCollector.java (+13/-14)
src/main/java/com/akiban/qp/persistitadapter/OperatorStore.java (+9/-8)
src/main/java/com/akiban/qp/persistitadapter/PersistitAdapter.java (+10/-24)
src/main/java/com/akiban/qp/persistitadapter/PersistitGroupRow.java (+1/-0)
src/main/java/com/akiban/qp/persistitadapter/indexrow/PersistitIndexRow.java (+1/-1)
src/main/java/com/akiban/qp/row/AbstractRow.java (+5/-0)
src/main/java/com/akiban/server/PersistitAccumulatorTableStatusCache.java (+52/-23)
src/main/java/com/akiban/server/TableStatus.java (+8/-8)
src/main/java/com/akiban/server/manage/ManageMXBean.java (+0/-6)
src/main/java/com/akiban/server/manage/ManageMXBeanImpl.java (+0/-22)
src/main/java/com/akiban/server/service/dxl/BasicDDLFunctions.java (+1/-1)
src/main/java/com/akiban/server/service/dxl/BasicDMLFunctions.java (+7/-33)
src/main/java/com/akiban/server/store/AbstractStore.java (+487/-0)
src/main/java/com/akiban/server/store/DelegatingStore.java (+57/-30)
src/main/java/com/akiban/server/store/PersistitStore.java (+126/-618)
src/main/java/com/akiban/server/store/PersistitStoreSchemaManager.java (+1/-5)
src/main/java/com/akiban/server/store/Store.java (+27/-42)
src/main/java/com/akiban/server/store/statistics/IndexStatisticsServiceImpl.java (+2/-2)
src/main/java/com/akiban/server/store/statistics/PersistitStoreIndexStatistics.java (+3/-0)
src/test/java/com/akiban/server/test/it/keyupdate/FixCountStarIT.java (+1/-1)
src/test/java/com/akiban/server/test/it/rowtests/ObjectToKeyIT.java (+1/-1)
src/test/java/com/akiban/server/test/it/store/AbstractScanBase.java (+2/-2)
To merge this branch: bzr merge lp:~nwilliams/akiban-server/abstract-store
Reviewer Review Type Date Requested Status
Thomas Jones-Low Needs Fixing
Mike McMahon Approve
Review via email: mp+164745@code.launchpad.net

Description of the change

Pull general methods from PersistitStore into AbstractStore and cleanup PersistitException on interfaces.

Particularly, don't declare to throw anything on TableStatus or Store. Minor cascading cleanup that removes try/catch/wrap from higher level classes down into implementations.

Additionally, remove deferred indexing methods as they have been broken for a long time (bug767737) and are unused.

To post a comment you must log in.
Revision history for this message
Mike McMahon (mmcm) wrote :

Looks as described.

review: Approve
Revision history for this message
Thomas Jones-Low (tjoneslo) wrote :

There were 2 failures during build/test:

* job server-build failed at build number 4030: http://172.16.20.104:8080/job/server-build/4030/

* view must-pass failed: server-build is yellow

review: Needs Fixing
Revision history for this message
Thomas Jones-Low (tjoneslo) wrote :

Build system failure, not merge proposal failure. Trying again.

Revision history for this message
Thomas Jones-Low (tjoneslo) wrote :

There were 2 failures during build/test:

* job server-build failed at build number 4032: http://172.16.20.104:8080/job/server-build/4032/

* view must-pass failed: server-build is yellow

review: Needs Fixing
Revision history for this message
Nathan Williams (nwilliams) wrote :

Manually ran ITs on sleepy.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'src/main/java/com/akiban/ais/model/UserTable.java'
--- src/main/java/com/akiban/ais/model/UserTable.java 2013-04-07 01:22:07 +0000
+++ src/main/java/com/akiban/ais/model/UserTable.java 2013-05-20 14:47:34 +0000
@@ -168,6 +168,10 @@
168 return Collections.unmodifiableList(candidateChildJoins);168 return Collections.unmodifiableList(candidateChildJoins);
169 }169 }
170170
171 public boolean hasChildren() {
172 return !getCandidateChildJoins().isEmpty();
173 }
174
171 public Join getParentJoin()175 public Join getParentJoin()
172 {176 {
173 Join parentJoin = null;177 Join parentJoin = null;
174178
=== modified file 'src/main/java/com/akiban/qp/persistitadapter/OneTableRowCollector.java'
--- src/main/java/com/akiban/qp/persistitadapter/OneTableRowCollector.java 2013-03-22 20:05:57 +0000
+++ src/main/java/com/akiban/qp/persistitadapter/OneTableRowCollector.java 2013-05-20 14:47:34 +0000
@@ -26,15 +26,13 @@
26import com.akiban.server.api.dml.scan.NewRow;26import com.akiban.server.api.dml.scan.NewRow;
27import com.akiban.server.rowdata.RowData;27import com.akiban.server.rowdata.RowData;
28import com.akiban.server.rowdata.RowDef;28import com.akiban.server.rowdata.RowDef;
29import com.akiban.server.service.config.ConfigurationService;
30import com.akiban.server.service.session.Session;29import com.akiban.server.service.session.Session;
31import com.akiban.server.store.PersistitStore;30import com.akiban.server.store.Store;
3231
33public class OneTableRowCollector extends OperatorBasedRowCollector32public class OneTableRowCollector extends OperatorBasedRowCollector
34{33{
35 OneTableRowCollector(ConfigurationService config,34 OneTableRowCollector(Session session,
36 Session session,35 Store store,
37 PersistitStore store,
38 RowDef rowDef,36 RowDef rowDef,
39 int indexId,37 int indexId,
40 int scanFlags,38 int scanFlags,
@@ -43,7 +41,7 @@
43 RowData end,41 RowData end,
44 ColumnSelector endColumns)42 ColumnSelector endColumns)
45 {43 {
46 super(store, session, config);44 super(store, session);
47 // rootmostQueryTable45 // rootmostQueryTable
48 queryRootTable = rowDef.userTable();46 queryRootTable = rowDef.userTable();
49 queryRootType = schema.userTableRowType(queryRootTable);47 queryRootType = schema.userTableRowType(queryRootTable);
5048
=== modified file 'src/main/java/com/akiban/qp/persistitadapter/OperatorBasedRowCollector.java'
--- src/main/java/com/akiban/qp/persistitadapter/OperatorBasedRowCollector.java 2013-04-30 22:35:43 +0000
+++ src/main/java/com/akiban/qp/persistitadapter/OperatorBasedRowCollector.java 2013-05-20 14:47:34 +0000
@@ -23,6 +23,8 @@
23import com.akiban.qp.operator.Limit;23import com.akiban.qp.operator.Limit;
24import com.akiban.qp.operator.Operator;24import com.akiban.qp.operator.Operator;
25import com.akiban.qp.operator.SimpleQueryContext;25import com.akiban.qp.operator.SimpleQueryContext;
26import com.akiban.qp.operator.StoreAdapter;
27import com.akiban.qp.row.AbstractRow;
26import com.akiban.qp.row.Row;28import com.akiban.qp.row.Row;
27import com.akiban.qp.rowtype.*;29import com.akiban.qp.rowtype.*;
28import com.akiban.qp.rowtype.Schema;30import com.akiban.qp.rowtype.Schema;
@@ -38,6 +40,7 @@
38import com.akiban.server.service.session.Session;40import com.akiban.server.service.session.Session;
39import com.akiban.server.store.PersistitStore;41import com.akiban.server.store.PersistitStore;
40import com.akiban.server.store.RowCollector;42import com.akiban.server.store.RowCollector;
43import com.akiban.server.store.Store;
41import com.akiban.server.types3.Types3Switch;44import com.akiban.server.types3.Types3Switch;
42import com.akiban.util.GrowableByteBuffer;45import com.akiban.util.GrowableByteBuffer;
43import com.akiban.util.ShareHolder;46import com.akiban.util.ShareHolder;
@@ -78,12 +81,12 @@
78 // the current row across these two invocations.81 // the current row across these two invocations.
79 boolean wasHeld = false;82 boolean wasHeld = false;
80 boolean wroteToPayload = false;83 boolean wroteToPayload = false;
81 PersistitGroupRow row;84 AbstractRow row;
82 if (currentRow.isEmpty()) {85 if (currentRow.isEmpty()) {
83 row = (PersistitGroupRow) cursor.next();86 row = (AbstractRow) cursor.next();
84 } else {87 } else {
85 wasHeld = true;88 wasHeld = true;
86 row = (PersistitGroupRow) currentRow.get();89 row = (AbstractRow) currentRow.get();
87 currentRow.release();90 currentRow.release();
88 }91 }
89 if (row == null) {92 if (row == null) {
@@ -117,7 +120,7 @@
117 public RowData collectNextRow()120 public RowData collectNextRow()
118 {121 {
119 RowData rowData = null;122 RowData rowData = null;
120 PersistitGroupRow row = (PersistitGroupRow) cursor.next();123 AbstractRow row = (AbstractRow) cursor.next();
121 if (row == null) {124 if (row == null) {
122 close();125 close();
123 } else {126 } else {
@@ -196,9 +199,8 @@
196199
197 // OperatorBasedRowCollector interface200 // OperatorBasedRowCollector interface
198201
199 public static OperatorBasedRowCollector newCollector(ConfigurationService config,202 public static OperatorBasedRowCollector newCollector(Session session,
200 Session session,203 Store store,
201 PersistitStore store,
202 int scanFlags,204 int scanFlags,
203 RowDef rowDef,205 RowDef rowDef,
204 int indexId,206 int indexId,
@@ -217,8 +219,7 @@
217 throw new IllegalArgumentException("Must scan a UserTable: " + rowDef);219 throw new IllegalArgumentException("Must scan a UserTable: " + rowDef);
218 }220 }
219 OperatorBasedRowCollector rowCollector =221 OperatorBasedRowCollector rowCollector =
220 new OneTableRowCollector(config,222 new OneTableRowCollector(session,
221 session,
222 store,223 store,
223 rowDef,224 rowDef,
224 indexId,225 indexId,
@@ -234,12 +235,10 @@
234 return rowCollector;235 return rowCollector;
235 }236 }
236 237
237 protected OperatorBasedRowCollector(PersistitStore store, Session session, ConfigurationService config)238 protected OperatorBasedRowCollector(Store store, Session session)
238 {239 {
239 this.schema = SchemaCache.globalSchema(store.getAIS(session));240 this.schema = SchemaCache.globalSchema(store.getAIS(session));
240 // Passing null to PersistitAdapter's TreeService argument. TreeService is only needed for sorting,241 this.adapter = store.createAdapter(session, schema);
241 // which OBRC doesn't use.
242 this.adapter = new PersistitAdapter(schema, store, null, session, config);
243 this.rowCollectorId = idCounter.getAndIncrement();242 this.rowCollectorId = idCounter.getAndIncrement();
244 }243 }
245244
@@ -397,7 +396,7 @@
397396
398 private long rowCollectorId;397 private long rowCollectorId;
399 protected final Schema schema;398 protected final Schema schema;
400 protected PersistitAdapter adapter;399 protected StoreAdapter adapter;
401 protected UserTable queryRootTable;400 protected UserTable queryRootTable;
402 protected UserTableRowType queryRootType;401 protected UserTableRowType queryRootType;
403 protected TableIndex predicateIndex;402 protected TableIndex predicateIndex;
404403
=== modified file 'src/main/java/com/akiban/qp/persistitadapter/OperatorStore.java'
--- src/main/java/com/akiban/qp/persistitadapter/OperatorStore.java 2013-04-30 22:35:43 +0000
+++ src/main/java/com/akiban/qp/persistitadapter/OperatorStore.java 2013-05-20 14:47:34 +0000
@@ -48,7 +48,6 @@
48import com.akiban.server.store.SchemaManager;48import com.akiban.server.store.SchemaManager;
49import com.akiban.server.types.ToObjectValueTarget;49import com.akiban.server.types.ToObjectValueTarget;
50import com.akiban.server.types.ValueSource;50import com.akiban.server.types.ValueSource;
51import com.akiban.server.types3.Types3Switch;
52import com.akiban.sql.optimizer.rule.PlanGenerator;51import com.akiban.sql.optimizer.rule.PlanGenerator;
53import com.akiban.util.tap.InOutTap;52import com.akiban.util.tap.InOutTap;
54import com.akiban.util.tap.PointTap;53import com.akiban.util.tap.PointTap;
@@ -86,7 +85,6 @@
8685
87 @Override86 @Override
88 public void updateRow(Session session, RowData oldRowData, RowData newRowData, ColumnSelector columnSelector, Index[] indexes)87 public void updateRow(Session session, RowData oldRowData, RowData newRowData, ColumnSelector columnSelector, Index[] indexes)
89 throws PersistitException
90 {88 {
91 if(indexes != null) {89 if(indexes != null) {
92 throw new IllegalStateException("Unexpected indexes: " + Arrays.toString(indexes));90 throw new IllegalStateException("Unexpected indexes: " + Arrays.toString(indexes));
@@ -169,7 +167,7 @@
169 }167 }
170168
171 @Override169 @Override
172 public void writeRow(Session session, RowData rowData) throws PersistitException {170 public void writeRow(Session session, RowData rowData) {
173 INSERT_TOTAL.in();171 INSERT_TOTAL.in();
174 INSERT_MAINTENANCE.in();172 INSERT_MAINTENANCE.in();
175 try {173 try {
@@ -194,7 +192,7 @@
194 }192 }
195193
196 @Override194 @Override
197 public void deleteRow(Session session, RowData rowData, boolean deleteIndexes, boolean cascadeDelete) throws PersistitException {195 public void deleteRow(Session session, RowData rowData, boolean deleteIndexes, boolean cascadeDelete) {
198 DELETE_TOTAL.in();196 DELETE_TOTAL.in();
199 DELETE_MAINTENANCE.in();197 DELETE_MAINTENANCE.in();
200 try {198 try {
@@ -288,14 +286,14 @@
288 BitSet columnDifferences,286 BitSet columnDifferences,
289 OperatorStoreGIHandler handler,287 OperatorStoreGIHandler handler,
290 OperatorStoreGIHandler.Action action)288 OperatorStoreGIHandler.Action action)
291 throws PersistitException
292 {289 {
293 UserTable userTable = ais.getUserTable(rowData.getRowDefId());290 UserTable userTable = ais.getUserTable(rowData.getRowDefId());
294 if(canSkipMaintenance(userTable)) {291 if(canSkipMaintenance(userTable)) {
295 return;292 return;
296 }293 }
297 Exchange hEx = adapter.takeExchange(userTable.getGroup());294 Exchange hEx = null;
298 try {295 try {
296 hEx = adapter.takeExchange(userTable.getGroup());
299 // the "false" at the end of constructHKey toggles whether the RowData should be modified to increment297 // the "false" at the end of constructHKey toggles whether the RowData should be modified to increment
300 // the hidden PK field, if there is one. For PK-less rows, this field have already been incremented by now,298 // the hidden PK field, if there is one. For PK-less rows, this field have already been incremented by now,
301 // so we don't want to increment it again299 // so we don't want to increment it again
@@ -316,8 +314,12 @@
316 SKIP_MAINTENANCE.hit();314 SKIP_MAINTENANCE.hit();
317 }315 }
318 }316 }
317 } catch(PersistitException e) {
318 throw PersistitAdapter.wrapPersistitException(session, e);
319 } finally {319 } finally {
320 adapter.returnExchange(hEx);320 if(hEx != null) {
321 adapter.returnExchange(hEx);
322 }
321 }323 }
322 }324 }
323325
@@ -357,7 +359,6 @@
357 AkibanInformationSchema ais, 359 AkibanInformationSchema ais,
358 PersistitAdapter adapter, 360 PersistitAdapter adapter,
359 RowData rowData)361 RowData rowData)
360 throws PersistitException
361 {362 {
362 UserTable uTable = ais.getUserTable(rowData.getRowDefId());363 UserTable uTable = ais.getUserTable(rowData.getRowDefId());
363364
364365
=== modified file 'src/main/java/com/akiban/qp/persistitadapter/PersistitAdapter.java'
--- src/main/java/com/akiban/qp/persistitadapter/PersistitAdapter.java 2013-04-11 05:51:16 +0000
+++ src/main/java/com/akiban/qp/persistitadapter/PersistitAdapter.java 2013-05-20 14:47:34 +0000
@@ -129,10 +129,6 @@
129 } catch (InvalidOperationException e) {129 } catch (InvalidOperationException e) {
130 rollbackIfNeeded(e);130 rollbackIfNeeded(e);
131 throw e;131 throw e;
132 } catch (PersistitException e) {
133 rollbackIfNeeded(e);
134 handlePersistitException(e);
135 assert false;
136 }132 }
137 finally {133 finally {
138 leaveUpdateStep(oldStep);134 leaveUpdateStep(oldStep);
@@ -149,10 +145,6 @@
149 } catch (InvalidOperationException e) {145 } catch (InvalidOperationException e) {
150 rollbackIfNeeded(e);146 rollbackIfNeeded(e);
151 throw e;147 throw e;
152 } catch (PersistitException e) {
153 rollbackIfNeeded(e);
154 handlePersistitException(e);
155 assert false;
156 }148 }
157 finally {149 finally {
158 leaveUpdateStep(oldStep);150 leaveUpdateStep(oldStep);
@@ -170,10 +162,6 @@
170 } catch (InvalidOperationException e) {162 } catch (InvalidOperationException e) {
171 rollbackIfNeeded(e);163 rollbackIfNeeded(e);
172 throw e;164 throw e;
173 } catch (PersistitException e) {
174 rollbackIfNeeded(e);
175 handlePersistitException(e);
176 assert false;
177 }165 }
178 finally {166 finally {
179 leaveUpdateStep(oldStep);167 leaveUpdateStep(oldStep);
@@ -203,10 +191,6 @@
203 } catch (InvalidOperationException e) {191 } catch (InvalidOperationException e) {
204 rollbackIfNeeded(e);192 rollbackIfNeeded(e);
205 throw e;193 throw e;
206 } catch (PersistitException e) {
207 rollbackIfNeeded(e);
208 handlePersistitException(e);
209 assert false;
210 }194 }
211 finally {195 finally {
212 leaveUpdateStep(oldStep);196 leaveUpdateStep(oldStep);
@@ -216,11 +200,7 @@
216 @Override200 @Override
217 public long rowCount(RowType tableType) {201 public long rowCount(RowType tableType) {
218 RowDef rowDef = tableType.userTable().rowDef();202 RowDef rowDef = tableType.userTable().rowDef();
219 try {203 return rowDef.getTableStatus().getRowCount();
220 return rowDef.getTableStatus().getRowCount();
221 } catch(PersistitInterruptedException e) {
222 throw new QueryCanceledException(getSession());
223 }
224 }204 }
225205
226 @Override206 @Override
@@ -235,7 +215,7 @@
235 key = persistitKeyValueSource.key();215 key = persistitKeyValueSource.key();
236 depth = persistitKeyValueSource.depth();216 depth = persistitKeyValueSource.depth();
237 } else {217 } else {
238 key = persistit.getKey();218 key = persistit.createKey();
239 collator.append(key, valueSource.getString());219 collator.append(key, valueSource.getString());
240 depth = 0;220 depth = 0;
241 }221 }
@@ -325,7 +305,10 @@
325 public static boolean isFromInterruption(Exception e) {305 public static boolean isFromInterruption(Exception e) {
326 Throwable cause = e.getCause();306 Throwable cause = e.getCause();
327 return (e instanceof PersistitInterruptedException) ||307 return (e instanceof PersistitInterruptedException) ||
328 ((cause != null) && (cause instanceof InterruptedIOException || cause instanceof InterruptedException));308 ((cause != null) &&
309 (cause instanceof PersistitInterruptedException ||
310 cause instanceof InterruptedIOException ||
311 cause instanceof InterruptedException));
329 }312 }
330313
331 public static RuntimeException wrapPersistitException(Session session, PersistitException e)314 public static RuntimeException wrapPersistitException(Session session, PersistitException e)
@@ -418,7 +401,10 @@
418401
419 // For use by this class402 // For use by this class
420 private void rollbackIfNeeded(Exception e) {403 private void rollbackIfNeeded(Exception e) {
421 if((e instanceof DuplicateKeyException) || (e instanceof PersistitException) || isFromInterruption(e)) {404 if((e instanceof DuplicateKeyException) ||
405 (e instanceof PersistitException) ||
406 (e instanceof PersistitAdapterException) ||
407 isFromInterruption(e)) {
422 Transaction txn = transaction();408 Transaction txn = transaction();
423 if(txn.isActive()) {409 if(txn.isActive()) {
424 txn.rollback();410 txn.rollback();
425411
=== modified file 'src/main/java/com/akiban/qp/persistitadapter/PersistitGroupRow.java'
--- src/main/java/com/akiban/qp/persistitadapter/PersistitGroupRow.java 2013-03-22 20:05:57 +0000
+++ src/main/java/com/akiban/qp/persistitadapter/PersistitGroupRow.java 2013-05-20 14:47:34 +0000
@@ -159,6 +159,7 @@
159 } while (exception != null);159 } while (exception != null);
160 }160 }
161161
162 @Override
162 public RowData rowData()163 public RowData rowData()
163 {164 {
164 return rowData;165 return rowData;
165166
=== modified file 'src/main/java/com/akiban/qp/persistitadapter/indexrow/PersistitIndexRow.java'
--- src/main/java/com/akiban/qp/persistitadapter/indexrow/PersistitIndexRow.java 2013-03-22 20:05:57 +0000
+++ src/main/java/com/akiban/qp/persistitadapter/indexrow/PersistitIndexRow.java 2013-05-20 14:47:34 +0000
@@ -128,7 +128,7 @@
128 protected PersistitIndexRow(PersistitAdapter adapter, IndexRowType indexRowType)128 protected PersistitIndexRow(PersistitAdapter adapter, IndexRowType indexRowType)
129 {129 {
130 super(adapter);130 super(adapter);
131 this.keyState = adapter.persistit().getKey();131 this.keyState = adapter.persistit().createKey();
132 resetForWrite(indexRowType.index(), keyState);132 resetForWrite(indexRowType.index(), keyState);
133 this.indexRowType = indexRowType;133 this.indexRowType = indexRowType;
134 this.leafmostTable = (UserTable) index.leafMostTable();134 this.leafmostTable = (UserTable) index.leafMostTable();
135135
=== modified file 'src/main/java/com/akiban/qp/row/AbstractRow.java'
--- src/main/java/com/akiban/qp/row/AbstractRow.java 2013-03-22 20:05:57 +0000
+++ src/main/java/com/akiban/qp/row/AbstractRow.java 2013-05-20 14:47:34 +0000
@@ -22,6 +22,7 @@
22import com.akiban.qp.rowtype.IndexRowType;22import com.akiban.qp.rowtype.IndexRowType;
23import com.akiban.qp.rowtype.RowType;23import com.akiban.qp.rowtype.RowType;
24import com.akiban.server.Quote;24import com.akiban.server.Quote;
25import com.akiban.server.rowdata.RowData;
25import com.akiban.server.types.ValueSource;26import com.akiban.server.types.ValueSource;
26import com.akiban.server.types.util.ValueSources;27import com.akiban.server.types.util.ValueSources;
27import com.akiban.server.types3.TClass;28import com.akiban.server.types3.TClass;
@@ -166,6 +167,10 @@
166 return builder.toString();167 return builder.toString();
167 }168 }
168169
170 public RowData rowData() {
171 throw new UnsupportedOperationException();
172 }
173
169 // for use by subclasses174 // for use by subclasses
170 protected void afterRelease() {}175 protected void afterRelease() {}
171 protected void beforeAcquire() {}176 protected void beforeAcquire() {}
172177
=== modified file 'src/main/java/com/akiban/server/PersistitAccumulatorTableStatusCache.java'
--- src/main/java/com/akiban/server/PersistitAccumulatorTableStatusCache.java 2013-04-11 06:15:45 +0000
+++ src/main/java/com/akiban/server/PersistitAccumulatorTableStatusCache.java 2013-05-20 14:47:34 +0000
@@ -18,6 +18,7 @@
18package com.akiban.server;18package com.akiban.server;
1919
20import com.akiban.qp.memoryadapter.MemoryTableFactory;20import com.akiban.qp.memoryadapter.MemoryTableFactory;
21import com.akiban.qp.persistitadapter.PersistitAdapter;
21import com.akiban.server.error.PersistitAdapterException;22import com.akiban.server.error.PersistitAdapterException;
22import com.akiban.server.rowdata.IndexDef;23import com.akiban.server.rowdata.IndexDef;
23import com.akiban.server.rowdata.RowDef;24import com.akiban.server.rowdata.RowDef;
@@ -97,18 +98,30 @@
97 }98 }
9899
99 @Override100 @Override
100 public long getAutoIncrement() throws PersistitInterruptedException {101 public long getAutoIncrement() {
101 return autoIncrement.getSnapshot();102 try {
102 }103 return autoIncrement.getSnapshot();
103104 } catch(PersistitInterruptedException e) {
104 @Override105 throw PersistitAdapter.wrapPersistitException(null, e);
105 public int getOrdinal() throws PersistitInterruptedException {106 }
106 return (int) ordinal.getSnapshot();107 }
107 }108
108109 @Override
109 @Override110 public int getOrdinal() {
110 public long getRowCount() throws PersistitInterruptedException {111 try {
111 return rowCount.getSnapshot();112 return (int) ordinal.getSnapshot();
113 } catch(PersistitInterruptedException e) {
114 throw PersistitAdapter.wrapPersistitException(null, e);
115 }
116 }
117
118 @Override
119 public long getRowCount() {
120 try {
121 return rowCount.getSnapshot();
122 } catch(PersistitInterruptedException e) {
123 throw PersistitAdapter.wrapPersistitException(null, e);
124 }
112 }125 }
113126
114 @Override127 @Override
@@ -127,8 +140,12 @@
127 }140 }
128141
129 @Override142 @Override
130 public long getUniqueID() throws PersistitInterruptedException {143 public long getUniqueID() {
131 return uniqueID.getSnapshot();144 try {
145 return uniqueID.getSnapshot();
146 } catch(PersistitInterruptedException e) {
147 throw PersistitAdapter.wrapPersistitException(null, e);
148 }
132 }149 }
133150
134 @Override151 @Override
@@ -151,23 +168,31 @@
151 rowCount.sumAdd(count);168 rowCount.sumAdd(count);
152 }169 }
153170
154 public void setOrdinal(int ordinal) throws PersistitInterruptedException {171 public void setOrdinal(int ordinal) {
155 this.ordinal.set(ordinal);172 try {
173 this.ordinal.set(ordinal);
174 } catch(PersistitInterruptedException e) {
175 throw PersistitAdapter.wrapPersistitException(null, e);
176 }
156 }177 }
157178
158 @Override179 @Override
159 public long createNewUniqueID() throws PersistitInterruptedException {180 public long createNewUniqueID() {
160 return uniqueID.seqAllocate();181 return uniqueID.seqAllocate();
161 }182 }
162183
163 @Override184 @Override
164 public void truncate() throws PersistitInterruptedException {185 public void truncate() {
165 internalSetRowCount(0);186 try {
166 internalSetAutoIncrement(0, true);187 internalSetRowCount(0);
188 internalSetAutoIncrement(0, true);
189 } catch(PersistitInterruptedException e) {
190 throw PersistitAdapter.wrapPersistitException(null, e);
191 }
167 }192 }
168193
169 @Override194 @Override
170 public void setAutoIncrement(long value) throws PersistitInterruptedException {195 public void setAutoIncrement(long value) {
171 internalSetAutoIncrement(value, false);196 internalSetAutoIncrement(value, false);
172 }197 }
173198
@@ -189,8 +214,12 @@
189 rowCount.set(rowCountValue);214 rowCount.set(rowCountValue);
190 }215 }
191216
192 private void internalSetAutoIncrement(long autoIncrementValue, boolean evenIfLess) throws PersistitInterruptedException {217 private void internalSetAutoIncrement(long autoIncrementValue, boolean evenIfLess) {
193 autoIncrement.set(autoIncrementValue, evenIfLess);218 try {
219 autoIncrement.set(autoIncrementValue, evenIfLess);
220 } catch(PersistitInterruptedException e) {
221 throw PersistitAdapter.wrapPersistitException(null, e);
222 }
194 }223 }
195 }224 }
196225
197226
=== modified file 'src/main/java/com/akiban/server/TableStatus.java'
--- src/main/java/com/akiban/server/TableStatus.java 2013-04-11 06:15:45 +0000
+++ src/main/java/com/akiban/server/TableStatus.java 2013-05-20 14:47:34 +0000
@@ -34,34 +34,34 @@
34 void rowsWritten(long count);34 void rowsWritten(long count);
3535
36 /** Reset, but do not remove, the state of a table. */36 /** Reset, but do not remove, the state of a table. */
37 void truncate() throws PersistitInterruptedException;37 void truncate();
3838
39 /** Set the auto-increment value of a given table. */39 /** Set the auto-increment value of a given table. */
40 void setAutoIncrement(long value) throws PersistitInterruptedException;40 void setAutoIncrement(long value);
4141
42 /** Set the RowDef of a given table.*/42 /** Set the RowDef of a given table.*/
43 void setRowDef(RowDef rowDef);43 void setRowDef(RowDef rowDef);
4444
45 /** Create a brand new, unique ID for the given table. */45 /** Create a brand new, unique ID for the given table. */
46 long createNewUniqueID() throws PersistitInterruptedException;46 long createNewUniqueID();
4747
48 /** Set the ordinal value of a given table. */48 /** Set the ordinal value of a given table. */
49 void setOrdinal(int value) throws PersistitInterruptedException;49 void setOrdinal(int value);
5050
51 /**51 /**
52 * @return Current auto-increment value of the assocated table.52 * @return Current auto-increment value of the assocated table.
53 */53 */
54 long getAutoIncrement() throws PersistitInterruptedException;54 long getAutoIncrement();
5555
56 /**56 /**
57 * @return Ordinal of the associated table.57 * @return Ordinal of the associated table.
58 */58 */
59 int getOrdinal() throws PersistitInterruptedException;59 int getOrdinal();
6060
61 /**61 /**
62 * @return Current number of rows in the associated table.62 * @return Current number of rows in the associated table.
63 */63 */
64 long getRowCount() throws PersistitInterruptedException;64 long getRowCount();
6565
66 /**66 /**
67 * @return Approximate number of rows in the associated table.67 * @return Approximate number of rows in the associated table.
@@ -71,7 +71,7 @@
71 /**71 /**
72 * @return The <b>last</b> unique value used for the associated table.72 * @return The <b>last</b> unique value used for the associated table.
73 */73 */
74 long getUniqueID() throws PersistitInterruptedException;74 long getUniqueID();
7575
76 /** @return The table ID this status is for */76 /** @return The table ID this status is for */
77 int getTableID();77 int getTableID();
7878
=== modified file 'src/main/java/com/akiban/server/manage/ManageMXBean.java'
--- src/main/java/com/akiban/server/manage/ManageMXBean.java 2013-03-22 20:05:57 +0000
+++ src/main/java/com/akiban/server/manage/ManageMXBean.java 2013-05-20 14:47:34 +0000
@@ -25,15 +25,9 @@
2525
26 int getJmxPort();26 int getJmxPort();
2727
28 boolean isDeferIndexesEnabled();
29
30 void setDeferIndexes(final boolean defer);
31
32 void buildIndexes(final String arg, final boolean deferIndexes);28 void buildIndexes(final String arg, final boolean deferIndexes);
3329
34 void deleteIndexes(final String arg);30 void deleteIndexes(final String arg);
3531
36 void flushIndexes();
37
38 String getVersionString();32 String getVersionString();
39}33}
4034
=== modified file 'src/main/java/com/akiban/server/manage/ManageMXBeanImpl.java'
--- src/main/java/com/akiban/server/manage/ManageMXBeanImpl.java 2013-03-22 20:05:57 +0000
+++ src/main/java/com/akiban/server/manage/ManageMXBeanImpl.java 2013-05-20 14:47:34 +0000
@@ -52,16 +52,6 @@
52 }52 }
5353
54 @Override54 @Override
55 public boolean isDeferIndexesEnabled() {
56 return getStore().isDeferIndexes();
57 }
58
59 @Override
60 public void setDeferIndexes(final boolean defer) {
61 getStore().setDeferIndexes(defer);
62 }
63
64 @Override
65 public void buildIndexes(final String arg, final boolean deferIndexes) {55 public void buildIndexes(final String arg, final boolean deferIndexes) {
66 Session session = createSession();56 Session session = createSession();
67 try {57 try {
@@ -88,18 +78,6 @@
88 }78 }
8979
90 @Override80 @Override
91 public void flushIndexes() {
92 Session session = createSession();
93 try {
94 getStore().flushIndexes(session);
95 } catch(Exception t) {
96 throw new RuntimeException(t);
97 } finally {
98 session.close();
99 }
100 }
101
102 @Override
103 public String getVersionString() {81 public String getVersionString() {
104 return AkServer.VERSION_STRING;82 return AkServer.VERSION_STRING;
105 }83 }
10684
=== modified file 'src/main/java/com/akiban/server/service/dxl/BasicDDLFunctions.java'
--- src/main/java/com/akiban/server/service/dxl/BasicDDLFunctions.java 2013-04-22 02:00:55 +0000
+++ src/main/java/com/akiban/server/service/dxl/BasicDDLFunctions.java 2013-05-20 14:47:34 +0000
@@ -1161,7 +1161,7 @@
1161 if (expected != actual) {1161 if (expected != actual) {
1162 PersistitStore pStore = this.store().getPersistitStore();1162 PersistitStore pStore = this.store().getPersistitStore();
1163 if (index.isTableIndex()) {1163 if (index.isTableIndex()) {
1164 pStore.getTableStatus(((TableIndex) index).getTable()).setRowCount(actual);1164 index.leafMostTable().rowDef().getTableStatus().setRowCount(actual);
1165 }1165 }
1166 else {1166 else {
1167 final Exchange ex = pStore.getExchange(session, index);1167 final Exchange ex = pStore.getExchange(session, index);
11681168
=== modified file 'src/main/java/com/akiban/server/service/dxl/BasicDMLFunctions.java'
--- src/main/java/com/akiban/server/service/dxl/BasicDMLFunctions.java 2013-03-22 20:05:57 +0000
+++ src/main/java/com/akiban/server/service/dxl/BasicDMLFunctions.java 2013-05-20 14:47:34 +0000
@@ -581,22 +581,14 @@
581 {581 {
582 logger.trace("writing a row");582 logger.trace("writing a row");
583 final RowData rowData = niceRowToRowData(row);583 final RowData rowData = niceRowToRowData(row);
584 try {584 store().writeRow(session, rowData);
585 store().writeRow(session, rowData);
586 } catch (PersistitException ex) {
587 throw new PersistitAdapterException(ex);
588 }
589 }585 }
590586
591 @Override587 @Override
592 public void writeRows(Session session, List<RowData> rows) {588 public void writeRows(Session session, List<RowData> rows) {
593 logger.trace("writing {} rows", rows.size());589 logger.trace("writing {} rows", rows.size());
594 try {590 for(RowData rowData : rows) {
595 for(RowData rowData : rows) {591 store().writeRow(session, rowData);
596 store().writeRow(session, rowData);
597 }
598 } catch (PersistitException ex) {
599 throw new PersistitAdapterException(ex);
600 }592 }
601 }593 }
602594
@@ -605,11 +597,7 @@
605 {597 {
606 logger.trace("deleting a row (cascade: {})", cascadeDelete);598 logger.trace("deleting a row (cascade: {})", cascadeDelete);
607 final RowData rowData = niceRowToRowData(row);599 final RowData rowData = niceRowToRowData(row);
608 try {600 store().deleteRow(session, rowData, true, cascadeDelete);
609 store().deleteRow(session, rowData, true, cascadeDelete);
610 } catch (PersistitException ex) {
611 throw new PersistitAdapterException(ex);
612 }
613 }601 }
614602
615 private RowData niceRowToRowData(NewRow row) 603 private RowData niceRowToRowData(NewRow row)
@@ -636,12 +624,7 @@
636 tableId624 tableId
637 );625 );
638626
639 try {627 store().updateRow(session, oldData, newData, columnSelector, null);
640 store().updateRow(session, oldData, newData, columnSelector, null);
641 } catch (PersistitException ex) {
642 throw new PersistitAdapterException(ex);
643 }
644
645 }628 }
646629
647 private void checkForModifiedCursors(630 private void checkForModifiedCursors(
@@ -749,12 +732,7 @@
749 final UserTable utable = table.isUserTable() ? (UserTable)table : null;732 final UserTable utable = table.isUserTable() ? (UserTable)table : null;
750733
751 if(utable == null || canFastTruncate(session, utable)) {734 if(utable == null || canFastTruncate(session, utable)) {
752 try {735 store().truncateGroup(session, table.getGroup());
753 store().truncateGroup(session, table.getGroup());
754 } catch (PersistitException ex) {
755 throw new PersistitAdapterException(ex);
756 }
757
758 return;736 return;
759 }737 }
760738
@@ -810,11 +788,7 @@
810 thrown = e;788 thrown = e;
811 }789 }
812 }790 }
813 try {791 store().truncateTableStatus(session, tableId);
814 store().truncateTableStatus(session, tableId);
815 } catch (PersistitException ex) {
816 throw new PersistitAdapterException(ex);
817 }
818 if (thrown != null) {792 if (thrown != null) {
819 throw thrown;793 throw thrown;
820 }794 }
821795
=== added file 'src/main/java/com/akiban/server/store/AbstractStore.java'
--- src/main/java/com/akiban/server/store/AbstractStore.java 1970-01-01 00:00:00 +0000
+++ src/main/java/com/akiban/server/store/AbstractStore.java 2013-05-20 14:47:34 +0000
@@ -0,0 +1,487 @@
1/**
2 * Copyright (C) 2009-2013 Akiban Technologies, Inc.
3 *
4 * This program is free software: you can redistribute it and/or modify
5 * it under the terms of the GNU Affero General Public License as published by
6 * the Free Software Foundation, either version 3 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU Affero General Public License for more details.
13 *
14 * You should have received a copy of the GNU Affero General Public License
15 * along with this program. If not, see <http://www.gnu.org/licenses/>.
16 */
17
18package com.akiban.server.store;
19
20import com.akiban.ais.model.Group;
21import com.akiban.ais.model.Index;
22import com.akiban.ais.model.NopVisitor;
23import com.akiban.ais.model.Table;
24import com.akiban.ais.model.TableName;
25import com.akiban.ais.model.UserTable;
26import com.akiban.qp.persistitadapter.OperatorBasedRowCollector;
27import com.akiban.server.TableStatistics;
28import com.akiban.server.TableStatus;
29import com.akiban.server.api.dml.ColumnSelector;
30import com.akiban.server.api.dml.scan.ScanLimit;
31import com.akiban.server.error.CursorCloseBadException;
32import com.akiban.server.error.CursorIsUnknownException;
33import com.akiban.server.error.NoSuchTableException;
34import com.akiban.server.error.RowDefNotFoundException;
35import com.akiban.server.rowdata.IndexDef;
36import com.akiban.server.rowdata.RowData;
37import com.akiban.server.rowdata.RowDef;
38import com.akiban.server.service.session.Session;
39import com.akiban.server.service.tree.TreeLink;
40import com.akiban.server.store.statistics.Histogram;
41import com.akiban.server.store.statistics.HistogramEntry;
42import com.akiban.server.store.statistics.IndexStatistics;
43import com.akiban.server.store.statistics.IndexStatisticsService;
44import com.akiban.util.tap.InOutTap;
45import com.akiban.util.tap.Tap;
46import com.persistit.Key;
47import org.slf4j.Logger;
48import org.slf4j.LoggerFactory;
49
50import java.util.ArrayList;
51import java.util.Arrays;
52import java.util.BitSet;
53import java.util.Collection;
54import java.util.Collections;
55import java.util.List;
56
57public abstract class AbstractStore implements Store {
58 private static final Logger LOG = LoggerFactory.getLogger(AbstractStore.class.getName());
59 private static final InOutTap NEW_COLLECTOR_TAP = Tap.createTimer("read: new_collector");
60 private static final Session.MapKey<Integer,List<RowCollector>> COLLECTORS = Session.MapKey.mapNamed("collectors");
61
62 protected IndexStatisticsService indexStatisticsService;
63
64 //
65 // AbstractStore
66 //
67
68 protected RowDef rowDefFromExplicitOrId(Session session, RowData rowData) {
69 RowDef rowDef = rowData.getExplicitRowDef();
70 if(rowDef == null) {
71 rowDef = getRowDef(session, rowData.getRowDefId());
72 }
73 return rowDef;
74 }
75
76 protected boolean hasNullIndexSegments(RowData rowData, Index index)
77 {
78 IndexDef indexDef = index.indexDef();
79 assert indexDef.getRowDef().getRowDefId() == rowData.getRowDefId();
80 for (int i : indexDef.getFields()) {
81 if (rowData.isNull(i)) {
82 return true;
83 }
84 }
85 return false;
86 }
87
88 /** Convert from new-format histogram to old for adapter. */
89 protected TableStatistics.Histogram indexStatisticsToHistogram(Session session, Index index, Key key) {
90 IndexStatistics stats = indexStatisticsService.getIndexStatistics(session, index);
91 if (stats == null) {
92 return null;
93 }
94 Histogram fromHistogram = stats.getHistogram(0, index.getKeyColumns().size());
95 if (fromHistogram == null) {
96 return null;
97 }
98 IndexDef indexDef = index.indexDef();
99 RowDef indexRowDef = indexDef.getRowDef();
100 TableStatistics.Histogram toHistogram = new TableStatistics.Histogram(index.getIndexId());
101 RowData indexRowData = new RowData(new byte[4096]);
102 Object[] indexValues = new Object[indexRowDef.getFieldCount()];
103 long count = 0;
104 for (HistogramEntry entry : fromHistogram.getEntries()) {
105 // Decode the key.
106 int keylen = entry.getKeyBytes().length;
107 System.arraycopy(entry.getKeyBytes(), 0, key.getEncodedBytes(), 0, keylen);
108 key.setEncodedSize(keylen);
109 key.indexTo(0);
110 int depth = key.getDepth();
111 // Copy key fields to index row.
112 for (int field : indexDef.getFields()) {
113 if (--depth >= 0) {
114 indexValues[field] = key.decode();
115 } else {
116 indexValues[field] = null;
117 }
118 }
119 indexRowData.createRow(indexRowDef, indexValues);
120 // Partial counts to running total less than key.
121 count += entry.getLessCount();
122 toHistogram.addSample(new TableStatistics.HistogramSample(indexRowData.copy(), count));
123 count += entry.getEqualCount();
124 }
125 // Add final entry with all nulls.
126 Arrays.fill(indexValues, null);
127 indexRowData.createRow(indexRowDef, indexValues);
128 toHistogram.addSample(new TableStatistics.HistogramSample(indexRowData.copy(), count));
129 return toHistogram;
130 }
131
132 protected static boolean bytesEqual(byte[] a, int aoffset, int asize, byte[] b, int boffset, int bsize) {
133 if (asize != bsize) {
134 return false;
135 }
136 for (int i = 0; i < asize; i++) {
137 if (a[i + aoffset] != b[i + boffset]) {
138 return false;
139 }
140 }
141 return true;
142 }
143
144 protected static boolean fieldsEqual(RowDef rowDef, RowData a, RowData b, int[] fieldIndexes)
145 {
146 for (int fieldIndex : fieldIndexes) {
147 long aloc = rowDef.fieldLocation(a, fieldIndex);
148 long bloc = rowDef.fieldLocation(b, fieldIndex);
149 if (!bytesEqual(a.getBytes(), (int) aloc, (int) (aloc >>> 32),
150 b.getBytes(), (int) bloc, (int) (bloc >>> 32))) {
151 return false;
152 }
153 }
154 return true;
155 }
156
157 protected static boolean fieldEqual(RowDef rowDef, RowData a, RowData b, int fieldPosition)
158 {
159 long aloc = rowDef.fieldLocation(a, fieldPosition);
160 long bloc = rowDef.fieldLocation(b, fieldPosition);
161 return bytesEqual(a.getBytes(), (int) aloc, (int) (aloc >>> 32),
162 b.getBytes(), (int) bloc, (int) (bloc >>> 32));
163 }
164
165 protected BitSet analyzeFieldChanges(Session session, RowDef rowDef, RowData oldRow, RowData newRow)
166 {
167 BitSet tablesRequiringHKeyMaintenance;
168 assert oldRow.getRowDefId() == newRow.getRowDefId();
169 int fields = rowDef.getFieldCount();
170 // Find the PK and FK fields
171 BitSet keyField = new BitSet(fields);
172 for (int pkFieldPosition : rowDef.getPKIndex().indexDef().getFields()) {
173 keyField.set(pkFieldPosition, true);
174 }
175 for (int fkFieldPosition : rowDef.getParentJoinFields()) {
176 keyField.set(fkFieldPosition, true);
177 }
178 // Find whether and where key fields differ
179 boolean allEqual = true;
180 for (int keyFieldPosition = keyField.nextSetBit(0);
181 allEqual && keyFieldPosition >= 0;
182 keyFieldPosition = keyField.nextSetBit(keyFieldPosition + 1)) {
183 boolean fieldEqual = fieldEqual(rowDef, oldRow, newRow, keyFieldPosition);
184 if (!fieldEqual) {
185 allEqual = false;
186 }
187 }
188 if (allEqual) {
189 tablesRequiringHKeyMaintenance = null;
190 } else {
191 // A PK or FK field has changed, so the update has to be done as delete/insert. To minimize hkey
192 // propagation work, find which tables (descendents of the updated table) are affected by hkey
193 // changes.
194 tablesRequiringHKeyMaintenance = hKeyDependentTableOrdinals(session, oldRow.getRowDefId());
195 }
196 return tablesRequiringHKeyMaintenance;
197 }
198
199 private BitSet hKeyDependentTableOrdinals(Session session, int rowDefId)
200 {
201 RowDef rowDef = getRowDef(session, rowDefId);
202 UserTable table = rowDef.userTable();
203 BitSet ordinals = new BitSet();
204 for (UserTable hKeyDependentTable : table.hKeyDependentTables()) {
205 int ordinal = hKeyDependentTable.rowDef().getOrdinal();
206 ordinals.set(ordinal, true);
207 }
208 return ordinals;
209 }
210
211
212 //
213 // Store methods
214 //
215
216 @Override
217 public RowDef getRowDef(Session session, int rowDefID) {
218 Table table = getAIS(session).getUserTable(rowDefID);
219 if(table == null) {
220 throw new RowDefNotFoundException(rowDefID);
221 }
222 return table.rowDef();
223 }
224
225 @Override
226 public RowDef getRowDef(Session session, TableName tableName) {
227 Table table = getAIS(session).getTable(tableName);
228 if(table == null) {
229 throw new NoSuchTableException(tableName);
230 }
231 return table.rowDef();
232 }
233
234 @Override
235 public RowCollector newRowCollector(Session session,
236 int scanFlags,
237 int rowDefId,
238 int indexId,
239 byte[] columnBitMap,
240 RowData start,
241 ColumnSelector startColumns,
242 RowData end,
243 ColumnSelector endColumns,
244 ScanLimit scanLimit)
245 {
246 NEW_COLLECTOR_TAP.in();
247 RowCollector rc;
248 try {
249 if(start != null && startColumns == null) {
250 startColumns = createNonNullFieldSelector(start);
251 }
252 if(end != null && endColumns == null) {
253 endColumns = createNonNullFieldSelector(end);
254 }
255 RowDef rowDef = checkRequest(session, rowDefId, start, startColumns, end, endColumns);
256 rc = OperatorBasedRowCollector.newCollector(session,
257 this,
258 scanFlags,
259 rowDef,
260 indexId,
261 columnBitMap,
262 start,
263 startColumns,
264 end,
265 endColumns,
266 scanLimit);
267 } finally {
268 NEW_COLLECTOR_TAP.out();
269 }
270 return rc;
271 }
272
273 @Override
274 public void addSavedRowCollector(final Session session,
275 final RowCollector rc) {
276 final Integer tableId = rc.getTableId();
277 final List<RowCollector> list = collectorsForTableId(session, tableId);
278 if (!list.isEmpty()) {
279 LOG.debug("Note: Nested RowCollector on tableId={} depth={}", tableId, list.size() + 1);
280 assert list.get(list.size() - 1) != rc : "Redundant call";
281 //
282 // This disallows the patch because we agreed not to fix the
283 // bug. However, these changes fix a memory leak, which is
284 // important for robustness.
285 //
286 // throw new StoreException(122, "Bug 255 workaround is disabled");
287 }
288 list.add(rc);
289 }
290
291 @Override
292 public RowCollector getSavedRowCollector(final Session session,
293 final int tableId) throws CursorIsUnknownException {
294 final List<RowCollector> list = collectorsForTableId(session, tableId);
295 if (list.isEmpty()) {
296 LOG.debug("Nested RowCollector on tableId={} depth={}", tableId, (list.size() + 1));
297 throw new CursorIsUnknownException(tableId);
298 }
299 return list.get(list.size() - 1);
300 }
301
302 @Override
303 public void removeSavedRowCollector(final Session session,
304 final RowCollector rc) throws CursorIsUnknownException {
305 final Integer tableId = rc.getTableId();
306 final List<RowCollector> list = collectorsForTableId(session, tableId);
307 if (list.isEmpty()) {
308 throw new CursorIsUnknownException (tableId);
309 }
310 final RowCollector removed = list.remove(list.size() - 1);
311 if (removed != rc) {
312 throw new CursorCloseBadException(tableId);
313 }
314 }
315
316 // This is to avoid circular dependencies in Guicer.
317 // TODO: There is still a functional circularity: store needs
318 // stats to clear them when deleting a group; stats need store to
319 // persist the stats. It would be better to separate out the
320 // higher level store functions from what other services require.
321 @Override
322 public void setIndexStatistics(IndexStatisticsService indexStatisticsService) {
323 this.indexStatisticsService = indexStatisticsService;
324 }
325
326 @Override
327 public TableStatistics getTableStatistics(final Session session, int tableId) {
328 final RowDef rowDef = getRowDef(session, tableId);
329 final TableStatistics ts = new TableStatistics(tableId);
330 final TableStatus status = rowDef.getTableStatus();
331 ts.setAutoIncrementValue(status.getAutoIncrement());
332 ts.setRowCount(status.getRowCount());
333 // TODO - get correct values
334 ts.setMeanRecordLength(100);
335 ts.setBlockSize(8192);
336 for(Index index : rowDef.getIndexes()) {
337 if(index.isSpatial()) {
338 continue;
339 }
340 TableStatistics.Histogram histogram = indexStatisticsToHistogram(session, index, createKey());
341 if(histogram != null) {
342 ts.addHistogram(histogram);
343 }
344 }
345 return ts;
346 }
347
348 @Override
349 public long getRowCount(Session session, boolean exact, RowData start, RowData end, byte[] columnBitMap) {
350 // TODO: Compute a reasonable value. The value 2 is special because it is not 0 or 1 but will
351 // still induce MySQL to use an index rather than a full table scan.
352 return 2;
353 }
354
355 @Override
356 public void dropGroup(final Session session, Group group) {
357 group.getRoot().traverseTableAndDescendants(new NopVisitor() {
358 @Override
359 public void visitUserTable(UserTable table) {
360 removeTrees(session, table);
361 }
362 });
363 }
364
365 @Override
366 public void truncateGroup(final Session session, final Group group) {
367 final List<Index> indexes = new ArrayList<>();
368 // Collect indexes, truncate table statuses
369 group.getRoot().traverseTableAndDescendants(new NopVisitor() {
370 @Override
371 public void visitUserTable(UserTable table) {
372 indexes.addAll(table.getIndexesIncludingInternal());
373 table.rowDef().getTableStatus().truncate();
374 }
375 });
376
377 indexes.addAll(group.getIndexes());
378 truncateIndexes(session, indexes);
379
380 // Truncate the group tree
381 truncateTree(session, group);
382 }
383
384 @Override
385 public void truncateTableStatus(final Session session, final int rowDefId) {
386 getRowDef(session, rowDefId).getTableStatus().truncate();
387 }
388
389 @Override
390 public void truncateIndexes(Session session, Collection<? extends Index> indexes) {
391 for(Index index : indexes) {
392 truncateTree(session, index.indexDef());
393 }
394 // Delete any statistics associated with index.
395 indexStatisticsService.deleteIndexStatistics(session, indexes);
396 }
397
398 @Override
399 public void deleteIndexes(final Session session, final Collection<? extends Index> indexes) {
400 for(Index index : indexes) {
401 final IndexDef indexDef = index.indexDef();
402 if(indexDef != null) {
403 removeTree(session, indexDef);
404 }
405 }
406 indexStatisticsService.deleteIndexStatistics(session, indexes);
407 }
408
409 @Override
410 public void removeTrees(Session session, UserTable table) {
411 // Table indexes
412 for(Index index : table.getIndexesIncludingInternal()) {
413 removeTree(session, index.indexDef());
414 }
415 indexStatisticsService.deleteIndexStatistics(session, table.getIndexesIncludingInternal());
416
417 // Group indexes
418 for(Index index : table.getGroupIndexes()) {
419 removeTree(session, index.indexDef());
420 }
421 indexStatisticsService.deleteIndexStatistics(session, table.getGroupIndexes());
422
423 // Sequence
424 if(table.getIdentityColumn() != null) {
425 deleteSequences(session, Collections.singleton(table.getIdentityColumn().getIdentityGenerator()));
426 }
427
428 // And the group tree
429 removeTree(session, table.getGroup());
430 }
431
432 @Override
433 public void removeTrees(Session session, Collection<? extends TreeLink> treeLinks) {
434 for(TreeLink link : treeLinks) {
435 removeTree(session, link);
436 }
437 }
438
439
440 //
441 // Internal
442 //
443
444 private List<RowCollector> collectorsForTableId(final Session session, final int tableId) {
445 List<RowCollector> list = session.get(COLLECTORS, tableId);
446 if (list == null) {
447 list = new ArrayList<>();
448 session.put(COLLECTORS, tableId, list);
449 }
450 return list;
451 }
452
453 private RowDef checkRequest(Session session, int rowDefId, RowData start, ColumnSelector startColumns,
454 RowData end, ColumnSelector endColumns) throws IllegalArgumentException {
455 if (start != null) {
456 if (startColumns == null) {
457 throw new IllegalArgumentException("non-null start row requires non-null ColumnSelector");
458 }
459 if( start.getRowDefId() != rowDefId) {
460 throw new IllegalArgumentException("Start and end RowData must specify the same rowDefId");
461 }
462 }
463 if (end != null) {
464 if (endColumns == null) {
465 throw new IllegalArgumentException("non-null end row requires non-null ColumnSelector");
466 }
467 if (end.getRowDefId() != rowDefId) {
468 throw new IllegalArgumentException("Start and end RowData must specify the same rowDefId");
469 }
470 }
471 final RowDef rowDef = getRowDef(session, rowDefId);
472 if (rowDef == null) {
473 throw new IllegalArgumentException("No RowDef for rowDefId " + rowDefId);
474 }
475 return rowDef;
476 }
477
478 private static ColumnSelector createNonNullFieldSelector(final RowData rowData) {
479 assert rowData != null;
480 return new ColumnSelector() {
481 @Override
482 public boolean includesColumn(int columnPosition) {
483 return !rowData.isNull(columnPosition);
484 }
485 };
486 }
487}
0488
=== modified file 'src/main/java/com/akiban/server/store/DelegatingStore.java'
--- src/main/java/com/akiban/server/store/DelegatingStore.java 2013-03-22 20:05:57 +0000
+++ src/main/java/com/akiban/server/store/DelegatingStore.java 2013-05-20 14:47:34 +0000
@@ -17,10 +17,14 @@
1717
18package com.akiban.server.store;18package com.akiban.server.store;
1919
20import com.akiban.ais.model.AkibanInformationSchema;
20import com.akiban.ais.model.Group;21import com.akiban.ais.model.Group;
21import com.akiban.ais.model.Index;22import com.akiban.ais.model.Index;
22import com.akiban.ais.model.Sequence;23import com.akiban.ais.model.Sequence;
23import com.akiban.ais.model.Table;24import com.akiban.ais.model.TableName;
25import com.akiban.ais.model.UserTable;
26import com.akiban.qp.operator.StoreAdapter;
27import com.akiban.qp.rowtype.Schema;
24import com.akiban.server.rowdata.RowData;28import com.akiban.server.rowdata.RowData;
25import com.akiban.server.rowdata.RowDef;29import com.akiban.server.rowdata.RowDef;
26import com.akiban.server.TableStatistics;30import com.akiban.server.TableStatistics;
@@ -30,7 +34,8 @@
30import com.akiban.server.service.Service;34import com.akiban.server.service.Service;
31import com.akiban.server.service.session.Session;35import com.akiban.server.service.session.Session;
32import com.akiban.server.service.tree.TreeLink;36import com.akiban.server.service.tree.TreeLink;
33import com.persistit.exception.PersistitException;37import com.akiban.server.store.statistics.IndexStatisticsService;
38import com.persistit.Key;
3439
35import java.util.Collection;40import java.util.Collection;
3641
@@ -42,7 +47,8 @@
42 this.delegate = delegate;47 this.delegate = delegate;
43 }48 }
4449
45 protected S getDelegate() {50 // TODO: Ditch DelegatingStore altogether
51 public S getDelegate() {
46 return delegate;52 return delegate;
47 }53 }
4854
@@ -62,11 +68,22 @@
62 delegate.crash();68 delegate.crash();
63 }69 }
6470
71 @Override
72 public AkibanInformationSchema getAIS(Session session) {
73 return delegate.getAIS(session);
74 }
75
76 @Override
65 public RowDef getRowDef(Session session, int rowDefID) {77 public RowDef getRowDef(Session session, int rowDefID) {
66 return delegate.getRowDef(session, rowDefID);78 return delegate.getRowDef(session, rowDefID);
67 }79 }
6880
69 @Override81 @Override
82 public RowDef getRowDef(Session session, TableName tableName) {
83 return delegate.getRowDef(session, tableName);
84 }
85
86 @Override
70 public void startBulkLoad(Session session) {87 public void startBulkLoad(Session session) {
71 delegate.startBulkLoad(session);88 delegate.startBulkLoad(session);
72 }89 }
@@ -81,15 +98,15 @@
81 delegate.finishBulkLoad(session);98 delegate.finishBulkLoad(session);
82 }99 }
83100
84 public void writeRow(Session session, RowData rowData) throws PersistitException {101 public void writeRow(Session session, RowData rowData) {
85 delegate.writeRow(session, rowData);102 delegate.writeRow(session, rowData);
86 }103 }
87104
88 public void deleteRow(Session session, RowData rowData, boolean deleteIndexes, boolean cascadeDelete) throws PersistitException {105 public void deleteRow(Session session, RowData rowData, boolean deleteIndexes, boolean cascadeDelete) {
89 delegate.deleteRow(session, rowData, deleteIndexes, cascadeDelete);106 delegate.deleteRow(session, rowData, deleteIndexes, cascadeDelete);
90 }107 }
91108
92 public void updateRow(Session session, RowData oldRowData, RowData newRowData, ColumnSelector columnSelector, Index[] indexes) throws PersistitException {109 public void updateRow(Session session, RowData oldRowData, RowData newRowData, ColumnSelector columnSelector, Index[] indexes) {
93 delegate.updateRow(session, oldRowData, newRowData, columnSelector, indexes);110 delegate.updateRow(session, oldRowData, newRowData, columnSelector, indexes);
94 }111 }
95112
@@ -97,11 +114,11 @@
97 delegate.dropGroup(session, group);114 delegate.dropGroup(session, group);
98 }115 }
99116
100 public void truncateGroup(Session session, Group group) throws PersistitException {117 public void truncateGroup(Session session, Group group) {
101 delegate.truncateGroup(session, group);118 delegate.truncateGroup(session, group);
102 }119 }
103120
104 public void truncateTableStatus(Session session, int rowDefId) throws PersistitException {121 public void truncateTableStatus(Session session, int rowDefId) {
105 delegate.truncateTableStatus(session, rowDefId);122 delegate.truncateTableStatus(session, rowDefId);
106 }123 }
107124
@@ -117,11 +134,6 @@
117 delegate.removeSavedRowCollector(session, rc);134 delegate.removeSavedRowCollector(session, rc);
118 }135 }
119136
120 @SuppressWarnings("deprecation")
121 public RowCollector newRowCollector(Session session, int rowDefId, int indexId, int scanFlags, RowData start, RowData end, byte[] columnBitMap, ScanLimit scanLimit) {
122 return delegate.newRowCollector(session, rowDefId, indexId, scanFlags, start, end, columnBitMap, scanLimit);
123 }
124
125 public RowCollector newRowCollector(Session session, int scanFlags, int rowDefId, int indexId, byte[] columnBitMap, RowData start, ColumnSelector startColumns, RowData end, ColumnSelector endColumns, ScanLimit scanLimit) {137 public RowCollector newRowCollector(Session session, int scanFlags, int rowDefId, int indexId, byte[] columnBitMap, RowData start, ColumnSelector startColumns, RowData end, ColumnSelector endColumns, ScanLimit scanLimit) {
126 return delegate.newRowCollector(session, scanFlags, rowDefId, indexId, columnBitMap, start, startColumns, end, endColumns, scanLimit);138 return delegate.newRowCollector(session, scanFlags, rowDefId, indexId, columnBitMap, start, startColumns, end, endColumns, scanLimit);
127 }139 }
@@ -134,10 +146,6 @@
134 return delegate.getTableStatistics(session, tableId);146 return delegate.getTableStatistics(session, tableId);
135 }147 }
136148
137 public void flushIndexes(Session session) {
138 delegate.flushIndexes(session);
139 }
140
141 public void buildIndexes(Session session, Collection<? extends Index> indexes, boolean defer) {149 public void buildIndexes(Session session, Collection<? extends Index> indexes, boolean defer) {
142 delegate.buildIndexes(session, indexes, defer);150 delegate.buildIndexes(session, indexes, defer);
143 }151 }
@@ -146,22 +154,11 @@
146 delegate.deleteIndexes(session, indexes);154 delegate.deleteIndexes(session, indexes);
147 }155 }
148156
149 public void deleteSequences (Session session, Collection<? extends Sequence> sequences) {157 @Override
150 delegate.deleteSequences(session, sequences);158 public void removeTrees(Session session, UserTable table) {
151 }
152
153 public void removeTrees(Session session, Table table) {
154 delegate.removeTrees(session, table);159 delegate.removeTrees(session, table);
155 }160 }
156161
157 public boolean isDeferIndexes() {
158 return delegate.isDeferIndexes();
159 }
160
161 public void setDeferIndexes(boolean defer) {
162 delegate.setDeferIndexes(defer);
163 }
164
165 @Override162 @Override
166 public void truncateIndexes(Session session, Collection<? extends Index> indexes) {163 public void truncateIndexes(Session session, Collection<? extends Index> indexes) {
167 delegate.truncateIndexes(session, indexes);164 delegate.truncateIndexes(session, indexes);
@@ -171,4 +168,34 @@
171 public void removeTrees(Session session, Collection<? extends TreeLink> treeLinks) {168 public void removeTrees(Session session, Collection<? extends TreeLink> treeLinks) {
172 delegate.removeTrees(session, treeLinks);169 delegate.removeTrees(session, treeLinks);
173 }170 }
171
172 @Override
173 public StoreAdapter createAdapter(Session session, Schema schema) {
174 return delegate.createAdapter(session, schema);
175 }
176
177 @Override
178 public void setIndexStatistics(IndexStatisticsService indexStatistics) {
179 delegate.setIndexStatistics(indexStatistics);
180 }
181
182 @Override
183 public void truncateTree(Session session, TreeLink treeLink) {
184 delegate.truncateTree(session, treeLink);
185 }
186
187 @Override
188 public Key createKey() {
189 return delegate.createKey();
190 }
191
192 @Override
193 public void deleteSequences(Session session, Collection<? extends Sequence> sequences) {
194 delegate.deleteSequences(session, sequences);
195 }
196
197 @Override
198 public void removeTree(Session session, TreeLink treeLink) {
199 delegate.removeTree(session, treeLink);
200 }
174}201}
175202
=== modified file 'src/main/java/com/akiban/server/store/PersistitStore.java'
--- src/main/java/com/akiban/server/store/PersistitStore.java 2013-05-03 00:59:49 +0000
+++ src/main/java/com/akiban/server/store/PersistitStore.java 2013-05-20 14:47:34 +0000
@@ -20,19 +20,18 @@
20import com.akiban.ais.model.*;20import com.akiban.ais.model.*;
21import com.akiban.ais.model.Index.IndexType;21import com.akiban.ais.model.Index.IndexType;
22import com.akiban.qp.operator.StoreAdapter;22import com.akiban.qp.operator.StoreAdapter;
23import com.akiban.qp.persistitadapter.OperatorBasedRowCollector;
24import com.akiban.qp.persistitadapter.PersistitAdapter;23import com.akiban.qp.persistitadapter.PersistitAdapter;
25import com.akiban.qp.persistitadapter.PersistitHKey;24import com.akiban.qp.persistitadapter.PersistitHKey;
26import com.akiban.qp.persistitadapter.indexrow.PersistitIndexRow;25import com.akiban.qp.persistitadapter.indexrow.PersistitIndexRow;
27import com.akiban.qp.persistitadapter.indexrow.PersistitIndexRowBuffer;26import com.akiban.qp.persistitadapter.indexrow.PersistitIndexRowBuffer;
28import com.akiban.qp.rowtype.IndexRowType;27import com.akiban.qp.rowtype.IndexRowType;
28import com.akiban.qp.rowtype.Schema;
29import com.akiban.qp.util.SchemaCache;29import com.akiban.qp.util.SchemaCache;
30import com.akiban.server.*;30import com.akiban.server.*;
31import com.akiban.server.api.dml.ColumnSelector;31import com.akiban.server.api.dml.ColumnSelector;
32import com.akiban.server.api.dml.scan.LegacyRowWrapper;32import com.akiban.server.api.dml.scan.LegacyRowWrapper;
33import com.akiban.server.api.dml.scan.NewRow;33import com.akiban.server.api.dml.scan.NewRow;
34import com.akiban.server.api.dml.scan.NiceRow;34import com.akiban.server.api.dml.scan.NiceRow;
35import com.akiban.server.api.dml.scan.ScanLimit;
36import com.akiban.server.collation.CString;35import com.akiban.server.collation.CString;
37import com.akiban.server.collation.CStringKeyCoder;36import com.akiban.server.collation.CStringKeyCoder;
38import com.akiban.server.error.*;37import com.akiban.server.error.*;
@@ -46,10 +45,6 @@
46import com.akiban.server.service.transaction.TransactionService;45import com.akiban.server.service.transaction.TransactionService;
47import com.akiban.server.service.tree.TreeLink;46import com.akiban.server.service.tree.TreeLink;
48import com.akiban.server.service.tree.TreeService;47import com.akiban.server.service.tree.TreeService;
49import com.akiban.server.store.statistics.Histogram;
50import com.akiban.server.store.statistics.HistogramEntry;
51import com.akiban.server.store.statistics.IndexStatistics;
52import com.akiban.server.store.statistics.IndexStatisticsService;
53import com.akiban.util.tap.InOutTap;48import com.akiban.util.tap.InOutTap;
54import com.akiban.util.tap.PointTap;49import com.akiban.util.tap.PointTap;
55import com.akiban.util.tap.Tap;50import com.akiban.util.tap.Tap;
@@ -69,9 +64,8 @@
69import java.util.concurrent.atomic.AtomicLong;64import java.util.concurrent.atomic.AtomicLong;
70import java.util.concurrent.atomic.AtomicReference;65import java.util.concurrent.atomic.AtomicReference;
7166
72public class PersistitStore implements Store, Service {67public class PersistitStore extends AbstractStore implements Service
7368{
74 private static final Session.MapKey<Integer, List<RowCollector>> COLLECTORS = Session.MapKey.mapNamed("collectors");
75 private static final AtomicReference<Bulkload> activeBulkload = new AtomicReference<>();69 private static final AtomicReference<Bulkload> activeBulkload = new AtomicReference<>();
7670
77 private static final Logger LOG = LoggerFactory71 private static final Logger LOG = LoggerFactory
@@ -85,8 +79,6 @@
8579
86 private static final InOutTap TABLE_INDEX_MAINTENANCE_TAP = Tap.createTimer("index: maintain_table");80 private static final InOutTap TABLE_INDEX_MAINTENANCE_TAP = Tap.createTimer("index: maintain_table");
8781
88 private static final InOutTap NEW_COLLECTOR_TAP = Tap.createTimer("read: new_collector");
89
90 // an InOutTap would be nice, but pre-propagateDownGroup optimization, propagateDownGroup was called recursively82 // an InOutTap would be nice, but pre-propagateDownGroup optimization, propagateDownGroup was called recursively
91 // (via writeRow). PointTap handles this correctly, InOutTap does not, currently.83 // (via writeRow). PointTap handles this correctly, InOutTap does not, currently.
92 private static final PointTap PROPAGATE_HKEY_CHANGE_TAP = Tap.createCount("write: propagate_hkey_change");84 private static final PointTap PROPAGATE_HKEY_CHANGE_TAP = Tap.createCount("write: propagate_hkey_change");
@@ -102,10 +94,6 @@
10294
103 private final static int MAX_ROW_SIZE = 5000000;95 private final static int MAX_ROW_SIZE = 5000000;
10496
105 private final static int MAX_INDEX_TRANCHE_SIZE = 10 * 1024 * 1024;
106
107 private final static int KEY_STATE_SIZE_OVERHEAD = 50;
108
109 private final static byte[] EMPTY_BYTE_ARRAY = new byte[0];97 private final static byte[] EMPTY_BYTE_ARRAY = new byte[0];
110 98
111 private boolean writeLockEnabled;99 private boolean writeLockEnabled;
@@ -126,12 +114,6 @@
126114
127 private DisplayFilter originalDisplayFilter;115 private DisplayFilter originalDisplayFilter;
128116
129 private volatile IndexStatisticsService indexStatistics;
130
131 private final Map<Tree, SortedSet<KeyState>> deferredIndexKeys = new HashMap<>();
132
133 private int deferredIndexKeyLimit = MAX_INDEX_TRANCHE_SIZE;
134
135 private FullTextIndexService fullTextService;117 private FullTextIndexService fullTextService;
136118
137 private RowDataValueCoder valueCoder;119 private RowDataValueCoder valueCoder;
@@ -161,6 +143,12 @@
161 this.transactionService = transactionService;143 this.transactionService = transactionService;
162 }144 }
163145
146
147 //
148 // FullText change tracking
149 // TODO: Move out of PersistitStore
150 //
151
164 public void setFullTextService(FullTextIndexService service)152 public void setFullTextService(FullTextIndexService service)
165 {153 {
166 fullTextService = service;154 fullTextService = service;
@@ -579,14 +567,15 @@
579 }567 }
580568
581 @Override569 @Override
570 public Key createKey() {
571 return treeService.createKey();
572 }
573
574 @Override
582 public PersistitStore getPersistitStore() {575 public PersistitStore getPersistitStore() {
583 return this;576 return this;
584 }577 }
585578
586 public TreeService treeService() {
587 return treeService;
588 }
589
590 public Persistit getDb() {579 public Persistit getDb() {
591 return treeService.getDb();580 return treeService.getDb();
592 }581 }
@@ -603,11 +592,6 @@
603 return treeService.getExchange(session, index.indexDef());592 return treeService.getExchange(session, index.indexDef());
604 }593 }
605594
606 public Key getKey()
607 {
608 return treeService.getKey();
609 }
610
611 public void releaseExchange(final Session session, final Exchange exchange) {595 public void releaseExchange(final Session session, final Exchange exchange) {
612 treeService.releaseExchange(session, exchange);596 treeService.releaseExchange(session, exchange);
613 }597 }
@@ -744,6 +728,7 @@
744728
745 // --------------------- Implement Store interface --------------------729 // --------------------- Implement Store interface --------------------
746730
731 @Override
747 public AkibanInformationSchema getAIS(Session session) {732 public AkibanInformationSchema getAIS(Session session) {
748 Bulkload bulkload = activeBulkload.get();733 Bulkload bulkload = activeBulkload.get();
749 if (bulkload != null)734 if (bulkload != null)
@@ -751,32 +736,18 @@
751 return schemaManager.getAis(session);736 return schemaManager.getAis(session);
752 }737 }
753738
754 public RowDef getRowDef(Session session, TableName tableName) {
755 Table table = getAIS(session).getTable(tableName);
756 if(table == null) {
757 throw new NoSuchTableException(tableName);
758 }
759 return table.rowDef();
760 }
761
762 @Override
763 public RowDef getRowDef(Session session, int rowDefID) {
764 Table table = getAIS(session).getUserTable(rowDefID);
765 if(table == null) {
766 throw new RowDefNotFoundException(rowDefID);
767 }
768 return table.rowDef();
769 }
770
771 @Override739 @Override
772 public void writeRow(Session session, RowData rowData)740 public void writeRow(Session session, RowData rowData)
773 throws PersistitException
774 {741 {
775 Bulkload bulkload = activeBulkload.get();742 Bulkload bulkload = activeBulkload.get();
776 if (bulkload != null)743 try {
777 writeRowBulk(session, rowData, bulkload);744 if (bulkload != null)
778 else745 writeRowBulk(session, rowData, bulkload);
779 writeRowStandard(session, rowData, null, true);746 else
747 writeRowStandard(session, rowData, null, true);
748 } catch(PersistitException e) {
749 throw PersistitAdapter.wrapPersistitException(session, e);
750 }
780 }751 }
781752
782 private void writeRowStandard(Session session,753 private void writeRowStandard(Session session,
@@ -804,7 +775,7 @@
804 // in a good position to report a meaningful uniqueness violation, e.g. on the PK, since we don't have775 // in a good position to report a meaningful uniqueness violation, e.g. on the PK, since we don't have
805 // the PK value handy. Instead, rely on PK validation when indexes are maintained.776 // the PK value handy. Instead, rely on PK validation when indexes are maintained.
806777
807 packRowData(hEx, rowDef, rowData);778 packRowData(hEx, rowData);
808 // Store the h-row779 // Store the h-row
809 hEx.store();780 hEx.store();
810 if (rowDef.isAutoIncrement()) {781 if (rowDef.isAutoIncrement()) {
@@ -824,7 +795,7 @@
824 // bug1112940: Bump row count *after* uniqueness checks in insertIntoIndex795 // bug1112940: Bump row count *after* uniqueness checks in insertIntoIndex
825 rowDef.getTableStatus().rowsWritten(1);796 rowDef.getTableStatus().rowsWritten(1);
826797
827 if (propagateHKeyChanges && hasChildren(rowDef.userTable())) {798 if (propagateHKeyChanges && rowDef.userTable().hasChildren()) {
828 // The row being inserted might be the parent of orphan rows799 // The row being inserted might be the parent of orphan rows
829 // already present. The hkeys of these800 // already present. The hkeys of these
830 // orphan rows need to be maintained. The hkeys of interest801 // orphan rows need to be maintained. The hkeys of interest
@@ -860,17 +831,13 @@
860 }831 }
861 propagateDownGroup(session, hEx, tablesRequiringHKeyMaintenance, indexRow, true, false);832 propagateDownGroup(session, hEx, tablesRequiringHKeyMaintenance, indexRow, true, false);
862 }833 }
863
864 if (deferredIndexKeyLimit <= 0) {
865 putAllDeferredIndexKeys(session);
866 }
867 } finally {834 } finally {
868 WRITE_ROW_TAP.out();835 WRITE_ROW_TAP.out();
869 releaseExchange(session, hEx);836 releaseExchange(session, hEx);
870 }837 }
871 }838 }
872839
873 private void writeRowBulk(Session session, RowData rowData, Bulkload bulkload) throws PersistitException {840 private void writeRowBulk(Session session, RowData rowData, Bulkload bulkload) {
874 final RowDef rowDef = writeRowCheck(session, rowData, true);841 final RowDef rowDef = writeRowCheck(session, rowData, true);
875 if(session.get(StoreAdapter.STORE_ADAPTER_KEY) == null) {842 if(session.get(StoreAdapter.STORE_ADAPTER_KEY) == null) {
876 // Attaches itself to the session843 // Attaches itself to the session
@@ -908,25 +875,27 @@
908 // Group table875 // Group table
909 Key groupTableKey = bulkload.groupTableKey.get();876 Key groupTableKey = bulkload.groupTableKey.get();
910 Value groupTableValue = bulkload.groupTableValue.get();877 Value groupTableValue = bulkload.groupTableValue.get();
911 constructHKey(session, groupTableKey, rowDef, rowData, true, hiddenPk); // invokes key.clear()
912 groupTableValue.clear();
913 packRowData(groupTableValue, rowDef, rowData);
914 try {878 try {
879 constructHKey(session, groupTableKey, rowDef, rowData, true, hiddenPk); // invokes key.clear()
880 groupTableValue.clear();
881 packRowData(groupTableValue, rowData);
915 Tree tree = treeService.populateTreeCache(rowDef.getGroup()).getTree();882 Tree tree = treeService.populateTreeCache(rowDef.getGroup()).getTree();
916 bulkload.groupBuilder.treeBuilder.store(tree, groupTableKey, groupTableValue);883 bulkload.groupBuilder.treeBuilder.store(tree, groupTableKey, groupTableValue);
884
885 PersistitIndexRowBuffer indexRow = new PersistitIndexRowBuffer(adapter(session));
886 for (Index index : rowDef.getIndexes()) {
887 StorageAction action = index.isPrimaryKey() ? bulkload.pkStorage : bulkload.groupBuilder;
888 insertIntoIndex(session, index, rowData, groupTableKey, indexRow, deferIndexes, action);
889 }
917 } catch (InvalidOperationException e) {890 } catch (InvalidOperationException e) {
918 throw e;891 throw e;
892 } catch (PersistitException e) {
893 throw PersistitAdapter.wrapPersistitException(session, e);
919 } catch (Exception e) {894 } catch (Exception e) {
920 LOG.error("while merging PKs", e);895 LOG.error("while merging PKs", e);
921 throw new BulkloadException("unknown exception (see log): " + e.getMessage());896 throw new BulkloadException("unknown exception (see log): " + e.getMessage());
922 }897 }
923898
924 PersistitIndexRowBuffer indexRow = new PersistitIndexRowBuffer(adapter(session));
925 for (Index index : rowDef.getIndexes()) {
926 StorageAction action = index.isPrimaryKey() ? bulkload.pkStorage : bulkload.groupBuilder;
927 insertIntoIndex(session, index, rowData, groupTableKey, indexRow, deferIndexes, action);
928 }
929
930 insertedRowsCount.incrementAndGet();899 insertedRowsCount.incrementAndGet();
931 }900 }
932901
@@ -1030,18 +999,17 @@
1030 }999 }
10311000
1032 @Override1001 @Override
1033 public void deleteRow(Session session, RowData rowData, boolean deleteIndexes, boolean cascadeDelete) throws PersistitException1002 public void deleteRow(Session session, RowData rowData, boolean deleteIndexes, boolean cascadeDelete)
1034 {1003 {
1035 deleteRow(session, rowData, deleteIndexes, cascadeDelete, null, true);1004 deleteRow(session, rowData, deleteIndexes, cascadeDelete, null, true);
1036 }1005 }
1037 1006
1038 private void deleteRow(Session session, RowData rowData, boolean deleteIndexes, boolean cascadeDelete, 1007 private void deleteRow(Session session, RowData rowData, boolean deleteIndexes, boolean cascadeDelete,
1039 BitSet tablesRequiringHKeyMaintenance, boolean propagateHKeyChanges)1008 BitSet tablesRequiringHKeyMaintenance, boolean propagateHKeyChanges)
1040 throws PersistitException
1041 {1009 {
1042 RowDef rowDef = writeCheck(session, rowData, false);1010 RowDef rowDef = writeCheck(session, rowData, false);
1043 Exchange hEx = null;1011 Exchange hEx = null;
10441012
1045 DELETE_ROW_TAP.in();1013 DELETE_ROW_TAP.in();
1046 try {1014 try {
1047 hEx = getExchange(session, rowDef);1015 hEx = getExchange(session, rowDef);
@@ -1075,9 +1043,11 @@
1075 // The row being deleted might be the parent of rows that1043 // The row being deleted might be the parent of rows that
1076 // now become orphans. The hkeys1044 // now become orphans. The hkeys
1077 // of these rows need to be maintained.1045 // of these rows need to be maintained.
1078 if(propagateHKeyChanges && hasChildren(rowDef.userTable())) {1046 if(propagateHKeyChanges && rowDef.userTable().hasChildren()) {
1079 propagateDownGroup(session, hEx, tablesRequiringHKeyMaintenance, indexRow, deleteIndexes, cascadeDelete);1047 propagateDownGroup(session, hEx, tablesRequiringHKeyMaintenance, indexRow, deleteIndexes, cascadeDelete);
1080 }1048 }
1049 } catch(PersistitException e) {
1050 throw PersistitAdapter.wrapPersistitException(session, e);
1081 } finally {1051 } finally {
1082 DELETE_ROW_TAP.out();1052 DELETE_ROW_TAP.out();
1083 releaseExchange(session, hEx);1053 releaseExchange(session, hEx);
@@ -1090,7 +1060,6 @@
1090 RowData newRowData,1060 RowData newRowData,
1091 ColumnSelector columnSelector,1061 ColumnSelector columnSelector,
1092 Index[] indexes)1062 Index[] indexes)
1093 throws PersistitException
1094 {1063 {
1095 updateRow(session, oldRowData, newRowData, columnSelector, indexes, (indexes != null), true);1064 updateRow(session, oldRowData, newRowData, columnSelector, indexes, (indexes != null), true);
1096 }1065 }
@@ -1102,7 +1071,6 @@
1102 Index[] indexesToMaintain,1071 Index[] indexesToMaintain,
1103 boolean indexesAsInsert,1072 boolean indexesAsInsert,
1104 boolean propagateHKeyChanges)1073 boolean propagateHKeyChanges)
1105 throws PersistitException
1106 {1074 {
1107 int rowDefId = oldRowData.getRowDefId();1075 int rowDefId = oldRowData.getRowDefId();
1108 if (newRowData.getRowDefId() != rowDefId) {1076 if (newRowData.getRowDefId() != rowDefId) {
@@ -1147,7 +1115,7 @@
1147 : null;1115 : null;
1148 if (tablesRequiringHKeyMaintenance == null) {1116 if (tablesRequiringHKeyMaintenance == null) {
1149 // No PK or FK fields have changed. Just update the row.1117 // No PK or FK fields have changed. Just update the row.
1150 packRowData(hEx, newRowDef, mergedRowData);1118 packRowData(hEx, mergedRowData);
1151 // Store the h-row1119 // Store the h-row
1152 hEx.store();1120 hEx.store();
1153 // Update the indexes (new row)1121 // Update the indexes (new row)
@@ -1169,58 +1137,14 @@
1169 deleteRow(session, oldRowData, true, false, tablesRequiringHKeyMaintenance, true);1137 deleteRow(session, oldRowData, true, false, tablesRequiringHKeyMaintenance, true);
1170 writeRowStandard(session, mergedRowData, tablesRequiringHKeyMaintenance, true); // May throw DuplicateKeyException1138 writeRowStandard(session, mergedRowData, tablesRequiringHKeyMaintenance, true); // May throw DuplicateKeyException
1171 }1139 }
1140 } catch(PersistitException e) {
1141 throw PersistitAdapter.wrapPersistitException(session, e);
1172 } finally {1142 } finally {
1173 UPDATE_ROW_TAP.out();1143 UPDATE_ROW_TAP.out();
1174 releaseExchange(session, hEx);1144 releaseExchange(session, hEx);
1175 }1145 }
1176 }1146 }
11771147
1178 private BitSet analyzeFieldChanges(Session session, RowDef rowDef, RowData oldRow, RowData newRow)
1179 {
1180 BitSet tablesRequiringHKeyMaintenance;
1181 assert oldRow.getRowDefId() == newRow.getRowDefId();
1182 int fields = rowDef.getFieldCount();
1183 // Find the PK and FK fields
1184 BitSet keyField = new BitSet(fields);
1185 for (int pkFieldPosition : rowDef.getPKIndex().indexDef().getFields()) {
1186 keyField.set(pkFieldPosition, true);
1187 }
1188 for (int fkFieldPosition : rowDef.getParentJoinFields()) {
1189 keyField.set(fkFieldPosition, true);
1190 }
1191 // Find whether and where key fields differ
1192 boolean allEqual = true;
1193 for (int keyFieldPosition = keyField.nextSetBit(0);
1194 allEqual && keyFieldPosition >= 0;
1195 keyFieldPosition = keyField.nextSetBit(keyFieldPosition + 1)) {
1196 boolean fieldEqual = fieldEqual(rowDef, oldRow, newRow, keyFieldPosition);
1197 if (!fieldEqual) {
1198 allEqual = false;
1199 }
1200 }
1201 if (allEqual) {
1202 tablesRequiringHKeyMaintenance = null;
1203 } else {
1204 // A PK or FK field has changed, so the update has to be done as delete/insert. To minimize hkey
1205 // propagation work, find which tables (descendents of the updated table) are affected by hkey
1206 // changes.
1207 tablesRequiringHKeyMaintenance = hKeyDependentTableOrdinals(session, oldRow.getRowDefId());
1208 }
1209 return tablesRequiringHKeyMaintenance;
1210 }
1211
1212 private BitSet hKeyDependentTableOrdinals(Session session, int rowDefId)
1213 {
1214 RowDef rowDef = getRowDef(session, rowDefId);
1215 UserTable table = rowDef.userTable();
1216 BitSet ordinals = new BitSet();
1217 for (UserTable hKeyDependentTable : table.hKeyDependentTables()) {
1218 int ordinal = hKeyDependentTable.rowDef().getOrdinal();
1219 ordinals.set(ordinal, true);
1220 }
1221 return ordinals;
1222 }
1223
1224 private void checkNoGroupIndexes(Table table) {1148 private void checkNoGroupIndexes(Table table) {
1225 if (updateGroupIndexes && !table.getGroupIndexes().isEmpty()) {1149 if (updateGroupIndexes && !table.getGroupIndexes().isEmpty()) {
1226 throw new UnsupportedOperationException("PersistitStore can't update group indexes; found on " + table);1150 throw new UnsupportedOperationException("PersistitStore can't update group indexes; found on " + table);
@@ -1278,308 +1202,42 @@
1278 }1202 }
12791203
1280 @Override1204 @Override
1281 public void dropGroup(Session session, Group group) {1205 public void truncateGroup(final Session session, final Group group) {
1282 for(Table table : group.getRoot().getAIS().getUserTables().values()) {
1283 if(table.getGroup() == group) {
1284 removeTrees(session, table);
1285 }
1286 }
1287 // tableStatusCache entries updated elsewhere
1288 }
1289
1290 @Override
1291 public void truncateGroup(final Session session, final Group group) throws PersistitException {
1292 List<Index> indexes = new ArrayList<>();1206 List<Index> indexes = new ArrayList<>();
1293 // Collect indexes, truncate table statuses
1294 for(UserTable table : group.getRoot().getAIS().getUserTables().values()) {
1295 if(table.getGroup() == group) {
1296 indexes.addAll(table.getIndexesIncludingInternal());
1297 table.rowDef().getTableStatus().truncate();
1298 }
1299 }
1300 indexes.addAll(group.getIndexes());
1301 truncateIndexes(session, indexes);
1302
1303 // Truncate the group tree1207 // Truncate the group tree
1304 final Exchange hEx = getExchange(session, group);1208 final Exchange hEx = getExchange(session, group);
1305 hEx.removeAll();1209 try {
1306 releaseExchange(session, hEx);1210 // Collect indexes, truncate table statuses
1307 }1211 for(UserTable table : group.getRoot().getAIS().getUserTables().values()) {
1212 if(table.getGroup() == group) {
1213 indexes.addAll(table.getIndexesIncludingInternal());
1214 table.rowDef().getTableStatus().truncate();
1215 }
1216 }
1217 indexes.addAll(group.getIndexes());
1218 truncateIndexes(session, indexes);
13081219
1309 // This is to avoid circular dependencies in Guicer. 1220 hEx.removeAll();
1310 // TODO: There is still a functional circularity: store needs1221 } catch(PersistitException e) {
1311 // stats to clear them when deleting a group; stats need store to1222 throw PersistitAdapter.wrapPersistitException(session, e);
1312 // persist the stats. It would be better to separate out the1223 } finally {
1313 // higher level store functions from what other services require.1224 releaseExchange(session, hEx);
1314 public void setIndexStatistics(IndexStatisticsService indexStatistics) {1225 }
1315 this.indexStatistics = indexStatistics;
1316 }1226 }
13171227
1318 @Override1228 @Override
1319 public void truncateIndexes(Session session, Collection<? extends Index> indexes) {1229 public void truncateIndexes(Session session, Collection<? extends Index> indexes) {
1230 super.truncateIndexes(session, indexes);
1320 for(Index index : indexes) {1231 for(Index index : indexes) {
1321 Exchange iEx = getExchange(session, index);1232 if(index.isGroupIndex()) {
1322 try {1233 try {
1323 iEx.removeAll();1234 Tree tree = index.indexDef().getTreeCache().getTree();
1324 if (index.isGroupIndex()) {1235 new AccumulatorAdapter(AccumulatorAdapter.AccumInfo.ROW_COUNT, tree).set(0);
1325 new AccumulatorAdapter(AccumulatorAdapter.AccumInfo.ROW_COUNT, iEx.getTree()).set(0);1236 } catch(PersistitInterruptedException e) {
1326 }1237 throw PersistitAdapter.wrapPersistitException(session, e);
1327 } catch (PersistitException e) {1238 }
1328 throw new PersistitAdapterException(e);1239 }
1329 }1240 }
1330 releaseExchange(session, iEx);
1331 }
1332 // Delete any statistics associated with index.
1333 indexStatistics.deleteIndexStatistics(session, indexes);
1334 }
1335
1336 @Override
1337 public void truncateTableStatus(final Session session, final int rowDefId) throws PersistitException {
1338 getRowDef(session, rowDefId).getTableStatus().truncate();
1339 }
1340
1341 @Override
1342 public RowCollector getSavedRowCollector(final Session session,
1343 final int tableId) throws CursorIsUnknownException {
1344 final List<RowCollector> list = collectorsForTableId(session, tableId);
1345 if (list.isEmpty()) {
1346 LOG.debug("Nested RowCollector on tableId={} depth={}", tableId, (list.size() + 1));
1347 throw new CursorIsUnknownException(tableId);
1348 }
1349 return list.get(list.size() - 1);
1350 }
1351
1352 @Override
1353 public void addSavedRowCollector(final Session session,
1354 final RowCollector rc) {
1355 final Integer tableId = rc.getTableId();
1356 final List<RowCollector> list = collectorsForTableId(session, tableId);
1357 if (!list.isEmpty()) {
1358 LOG.debug("Note: Nested RowCollector on tableId={} depth={}", tableId, list.size() + 1);
1359 assert list.get(list.size() - 1) != rc : "Redundant call";
1360 //
1361 // This disallows the patch because we agreed not to fix the
1362 // bug. However, these changes fix a memory leak, which is
1363 // important for robustness.
1364 //
1365 // throw new StoreException(122, "Bug 255 workaround is disabled");
1366 }
1367 list.add(rc);
1368 }
1369
1370 @Override
1371 public void removeSavedRowCollector(final Session session,
1372 final RowCollector rc) throws CursorIsUnknownException {
1373 final Integer tableId = rc.getTableId();
1374 final List<RowCollector> list = collectorsForTableId(session, tableId);
1375 if (list.isEmpty()) {
1376 throw new CursorIsUnknownException (tableId);
1377 }
1378 final RowCollector removed = list.remove(list.size() - 1);
1379 if (removed != rc) {
1380 throw new CursorCloseBadException (tableId);
1381 }
1382 }
1383
1384 private List<RowCollector> collectorsForTableId(final Session session,
1385 final int tableId) {
1386 List<RowCollector> list = session.get(COLLECTORS, tableId);
1387 if (list == null) {
1388 list = new ArrayList<>();
1389 session.put(COLLECTORS, tableId, list);
1390 }
1391 return list;
1392 }
1393
1394 private RowDef checkRequest(Session session, int rowDefId, RowData start, ColumnSelector startColumns,
1395 RowData end, ColumnSelector endColumns) throws IllegalArgumentException {
1396 if (start != null) {
1397 if (startColumns == null) {
1398 throw new IllegalArgumentException("non-null start row requires non-null ColumnSelector");
1399 }
1400 if( start.getRowDefId() != rowDefId) {
1401 throw new IllegalArgumentException("Start and end RowData must specify the same rowDefId");
1402 }
1403 }
1404 if (end != null) {
1405 if (endColumns == null) {
1406 throw new IllegalArgumentException("non-null end row requires non-null ColumnSelector");
1407 }
1408 if (end.getRowDefId() != rowDefId) {
1409 throw new IllegalArgumentException("Start and end RowData must specify the same rowDefId");
1410 }
1411 }
1412 final RowDef rowDef = getRowDef(session, rowDefId);
1413 if (rowDef == null) {
1414 throw new IllegalArgumentException("No RowDef for rowDefId " + rowDefId);
1415 }
1416 return rowDef;
1417 }
1418
1419 private static ColumnSelector createNonNullFieldSelector(final RowData rowData) {
1420 assert rowData != null;
1421 return new ColumnSelector() {
1422 @Override
1423 public boolean includesColumn(int columnPosition) {
1424 return !rowData.isNull(columnPosition);
1425 }
1426 };
1427 }
1428
1429 @Override
1430 public RowCollector newRowCollector(Session session,
1431 int rowDefId,
1432 int indexId,
1433 int scanFlags,
1434 RowData start,
1435 RowData end,
1436 byte[] columnBitMap,
1437 ScanLimit scanLimit)
1438 {
1439 return newRowCollector(session, scanFlags, rowDefId, indexId, columnBitMap, start, null, end, null, scanLimit);
1440 }
1441
1442 @Override
1443 public RowCollector newRowCollector(Session session,
1444 int scanFlags,
1445 int rowDefId,
1446 int indexId,
1447 byte[] columnBitMap,
1448 RowData start,
1449 ColumnSelector startColumns,
1450 RowData end,
1451 ColumnSelector endColumns,
1452 ScanLimit scanLimit)
1453 {
1454 NEW_COLLECTOR_TAP.in();
1455 RowCollector rc;
1456 try {
1457 if(start != null && startColumns == null) {
1458 startColumns = createNonNullFieldSelector(start);
1459 }
1460 if(end != null && endColumns == null) {
1461 endColumns = createNonNullFieldSelector(end);
1462 }
1463 RowDef rowDef = checkRequest(session, rowDefId, start, startColumns, end, endColumns);
1464 rc = OperatorBasedRowCollector.newCollector(config,
1465 session,
1466 this,
1467 scanFlags,
1468 rowDef,
1469 indexId,
1470 columnBitMap,
1471 start,
1472 startColumns,
1473 end,
1474 endColumns,
1475 scanLimit);
1476 } finally {
1477 NEW_COLLECTOR_TAP.out();
1478 }
1479 return rc;
1480 }
1481
1482 public final static long HACKED_ROW_COUNT = 2;
1483
1484 @Override
1485 public long getRowCount(final Session session, final boolean exact,
1486 final RowData start, final RowData end, final byte[] columnBitMap) {
1487 //
1488 // TODO: Compute a reasonable value. The value "2" is a hack -
1489 // special because it's not 0 or 1, but small enough to induce
1490 // MySQL to use an index rather than full table scan.
1491 //
1492 return HACKED_ROW_COUNT; // TODO: delete the HACKED_ROW_COUNT field when
1493 // this gets fixed
1494 // final int tableId = start.getRowDefId();
1495 // final TableStatus status = tableManager.getTableStatus(tableId);
1496 // return status.getRowCount();
1497 }
1498
1499 @Override
1500 public TableStatistics getTableStatistics(final Session session, int tableId) {
1501 final RowDef rowDef = getRowDef(session, tableId);
1502 final TableStatistics ts = new TableStatistics(tableId);
1503 final TableStatus status = rowDef.getTableStatus();
1504 try {
1505 ts.setAutoIncrementValue(status.getAutoIncrement());
1506 ts.setRowCount(status.getRowCount());
1507 // TODO - get correct values
1508 ts.setMeanRecordLength(100);
1509 ts.setBlockSize(8192);
1510 } catch (PersistitException e) {
1511 throw new PersistitAdapterException(e);
1512 }
1513 for (Index index : rowDef.getIndexes()) {
1514 if (index.isSpatial())
1515 continue;
1516 TableStatistics.Histogram histogram = indexStatisticsToHistogram(session,
1517 index);
1518 if (histogram != null) {
1519 ts.addHistogram(histogram);
1520 }
1521 }
1522 return ts;
1523 }
1524
1525 /** Convert from new-format histogram to old for adapter. */
1526 protected TableStatistics.Histogram indexStatisticsToHistogram(Session session,
1527 Index index) {
1528 IndexStatistics stats = indexStatistics.getIndexStatistics(session, index);
1529 if (stats == null) {
1530 return null;
1531 }
1532 Histogram fromHistogram = stats.getHistogram(0, index.getKeyColumns().size());
1533 if (fromHistogram == null) {
1534 return null;
1535 }
1536 IndexDef indexDef = index.indexDef();
1537 RowDef indexRowDef = indexDef.getRowDef();
1538 TableStatistics.Histogram toHistogram = new TableStatistics.Histogram(index.getIndexId());
1539 Key key = treeService.createKey();
1540 RowData indexRowData = new RowData(new byte[4096]);
1541 Object[] indexValues = new Object[indexRowDef.getFieldCount()];
1542 long count = 0;
1543 for (HistogramEntry entry : fromHistogram.getEntries()) {
1544 // Decode the key.
1545 int keylen = entry.getKeyBytes().length;
1546 System.arraycopy(entry.getKeyBytes(), 0, key.getEncodedBytes(), 0, keylen);
1547 key.setEncodedSize(keylen);
1548 key.indexTo(0);
1549 int depth = key.getDepth();
1550 // Copy key fields to index row.
1551 for (int field : indexDef.getFields()) {
1552 if (--depth >= 0) {
1553 indexValues[field] = key.decode();
1554 } else {
1555 indexValues[field] = null;
1556 }
1557 }
1558 indexRowData.createRow(indexRowDef, indexValues);
1559 // Partial counts to running total less than key.
1560 count += entry.getLessCount();
1561 toHistogram.addSample(new TableStatistics.HistogramSample(indexRowData.copy(),
1562 count));
1563 count += entry.getEqualCount();
1564 }
1565 // Add final entry with all nulls.
1566 Arrays.fill(indexValues, null);
1567 indexRowData.createRow(indexRowDef, indexValues);
1568 toHistogram.addSample(new TableStatistics.HistogramSample(indexRowData.copy(),
1569 count));
1570 return toHistogram;
1571 }
1572
1573 boolean hasNullIndexSegments(RowData rowData, Index index)
1574 {
1575 IndexDef indexDef = index.indexDef();
1576 assert indexDef.getRowDef().getRowDefId() == rowData.getRowDefId();
1577 for (int i : indexDef.getFields()) {
1578 if (rowData.isNull(i)) {
1579 return true;
1580 }
1581 }
1582 return false;
1583 }1241 }
15841242
1585 private void checkNotGroupIndex(Index index) {1243 private void checkNotGroupIndex(Index index) {
@@ -1607,24 +1265,13 @@
1607 {1265 {
1608 checkNotGroupIndex(index);1266 checkNotGroupIndex(index);
1609 Exchange iEx = getExchange(session, index);1267 Exchange iEx = getExchange(session, index);
1610 constructIndexRow(iEx, rowData, index, hkey, indexRow, true);1268 try {
1611 checkUniqueness(index, rowData, iEx);1269 constructIndexRow(iEx, rowData, index, hkey, indexRow, true);
1612 if (deferIndexes) {1270 checkUniqueness(index, rowData, iEx);
1613 // TODO: bug767737, deferred indexing does not handle uniqueness
1614 synchronized (deferredIndexKeys) {
1615 SortedSet<KeyState> keySet = deferredIndexKeys.get(iEx.getTree());
1616 if (keySet == null) {
1617 keySet = new TreeSet<>();
1618 deferredIndexKeys.put(iEx.getTree(), keySet);
1619 }
1620 KeyState ks = new KeyState(iEx.getKey());
1621 keySet.add(ks);
1622 deferredIndexKeyLimit -= (ks.getBytes().length + KEY_STATE_SIZE_OVERHEAD);
1623 }
1624 } else {
1625 storageAction.store(iEx);1271 storageAction.store(iEx);
1272 } finally {
1273 releaseExchange(session, iEx);
1626 }1274 }
1627 releaseExchange(session, iEx);
1628 }1275 }
16291276
1630 private void checkUniqueness(Index index, RowData rowData, Exchange iEx) throws PersistitException1277 private void checkUniqueness(Index index, RowData rowData, Exchange iEx) throws PersistitException
@@ -1661,22 +1308,6 @@
1661 return keyExistsInIndex;1308 return keyExistsInIndex;
1662 }1309 }
16631310
1664 private void putAllDeferredIndexKeys(final Session session) {
1665 synchronized (deferredIndexKeys) {
1666 for (final Map.Entry<Tree, SortedSet<KeyState>> entry : deferredIndexKeys
1667 .entrySet()) {
1668 final Exchange iEx = treeService.getExchange(session, entry.getKey());
1669 try {
1670 buildIndexAddKeys(entry.getValue(), iEx);
1671 entry.getValue().clear();
1672 } finally {
1673 treeService.releaseExchange(session, iEx);
1674 }
1675 }
1676 deferredIndexKeyLimit = MAX_INDEX_TRANCHE_SIZE;
1677 }
1678 }
1679
1680 private void updateIndex(Session session,1311 private void updateIndex(Session session,
1681 Index index,1312 Index index,
1682 RowDef rowDef,1313 RowDef rowDef,
@@ -1761,47 +1392,11 @@
1761 releaseExchange(session, iEx);1392 releaseExchange(session, iEx);
1762 }1393 }
17631394
1764 static boolean bytesEqual(byte[] a, int aoffset, int asize,1395 public void packRowData(final Exchange hEx,final RowData rowData) {
1765 byte[] b, int boffset, int bsize) {1396 packRowData(hEx.getValue(), rowData);
1766 if (asize != bsize) {1397 }
1767 return false;1398
1768 }1399 public void packRowData(final Value value, final RowData rowData) {
1769 for (int i = 0; i < asize; i++) {
1770 if (a[i + aoffset] != b[i + boffset]) {
1771 return false;
1772 }
1773 }
1774 return true;
1775 }
1776
1777 public static boolean fieldsEqual(RowDef rowDef, RowData a, RowData b, int[] fieldIndexes)
1778 {
1779 for (int fieldIndex : fieldIndexes) {
1780 long aloc = rowDef.fieldLocation(a, fieldIndex);
1781 long bloc = rowDef.fieldLocation(b, fieldIndex);
1782 if (!bytesEqual(a.getBytes(), (int) aloc, (int) (aloc >>> 32),
1783 b.getBytes(), (int) bloc, (int) (bloc >>> 32))) {
1784 return false;
1785 }
1786 }
1787 return true;
1788 }
1789
1790 public static boolean fieldEqual(RowDef rowDef, RowData a, RowData b, int fieldPosition)
1791 {
1792 long aloc = rowDef.fieldLocation(a, fieldPosition);
1793 long bloc = rowDef.fieldLocation(b, fieldPosition);
1794 return bytesEqual(a.getBytes(), (int) aloc, (int) (aloc >>> 32),
1795 b.getBytes(), (int) bloc, (int) (bloc >>> 32));
1796 }
1797
1798 public void packRowData(final Exchange hEx, final RowDef rowDef,
1799 final RowData rowData) {
1800 packRowData(hEx.getValue(), rowDef, rowData);
1801 }
1802
1803 public void packRowData(final Value value, final RowDef rowDef,
1804 final RowData rowData) {
1805 value.directPut(valueCoder, rowData, null);1400 value.directPut(valueCoder, rowData, null);
1806 }1401 }
18071402
@@ -1818,8 +1413,8 @@
1818 // rowData.prepareRow(0);1413 // rowData.prepareRow(0);
1819 }1414 }
18201415
1416 @Override
1821 public void buildIndexes(Session session, Collection<? extends Index> indexes, boolean defer) {1417 public void buildIndexes(Session session, Collection<? extends Index> indexes, boolean defer) {
1822 flushIndexes(session);
1823 Set<Group> groups = new HashSet<>();1418 Set<Group> groups = new HashSet<>();
1824 Map<Integer,RowDef> userRowDefs = new HashMap<>();1419 Map<Integer,RowDef> userRowDefs = new HashMap<>();
1825 Set<Index> indexesToBuild = new HashSet<>();1420 Set<Index> indexesToBuild = new HashSet<>();
@@ -1852,103 +1447,37 @@
1852 indexKeyCount++;1447 indexKeyCount++;
1853 }1448 }
1854 }1449 }
1855 if (deferredIndexKeyLimit <= 0) {
1856 putAllDeferredIndexKeys(session);
1857 }
1858 }1450 }
1859 }1451 }
1860 } catch (PersistitException e) {1452 } catch (PersistitException e) {
1861 throw new PersistitAdapterException(e);1453 throw new PersistitAdapterException(e);
1862 }1454 }
1863 flushIndexes(session);
1864 LOG.debug("Inserted {} index keys into group {}", indexKeyCount, group.getName());1455 LOG.debug("Inserted {} index keys into group {}", indexKeyCount, group.getName());
1865 }1456 }
1866 }1457 }
18671458
1868 @Override1459 @Override
1869 public void removeTrees(Session session, Collection<? extends TreeLink> treeLinks) {1460 public void removeTrees(Session session, UserTable table) {
1870 try {1461 super.removeTrees(session, table);
1871 for(TreeLink link : treeLinks) {1462
1872 if(!schemaManager.treeRemovalIsDelayed()) {1463 // TODO: Generalize. Knowing about FullTextService is wrong.
1873 Exchange ex = treeService.getExchange(session, link);1464 for(FullTextIndex idx : table.getOwnFullTextIndexes()) {
1874 ex.removeTree();1465 fullTextService.dropIndex(session, idx);
1875 // Do not releaseExchange, causes caching and leak for now unused tree
1876 }
1877 schemaManager.treeWasRemoved(session, link.getSchemaName(), link.getTreeName());
1878 }
1879 } catch (PersistitException e) {
1880 LOG.debug("Exception removing tree from Persistit", e);
1881 throw new PersistitAdapterException(e);
1882 }1466 }
1883 }1467 }
18841468
1885 @Override1469 @Override
1886 public void removeTrees(Session session, Table table) {
1887 Collection<TreeLink> treeLinks = new ArrayList<>();
1888
1889 // delete all fulltext indexes
1890 if (table.isUserTable())
1891 {
1892 for (FullTextIndex idx : ((UserTable)table).getOwnFullTextIndexes())
1893 fullTextService.dropIndex(session, idx);
1894 }
1895
1896 // Add all index trees
1897 final Collection<TableIndex> tableIndexes = table.isUserTable() ? ((UserTable)table).getIndexesIncludingInternal() : table.getIndexes();
1898 final Collection<GroupIndex> groupIndexes = table.getGroupIndexes();
1899 for(Index index : tableIndexes) {
1900 treeLinks.add(index.indexDef());
1901 }
1902 for(Index index : groupIndexes) {
1903 treeLinks.add(index.indexDef());
1904 }
1905 // Drop the sequence trees too.
1906 if (table.isUserTable() && ((UserTable)table).getIdentityColumn() != null) {
1907 treeLinks.add(((UserTable)table).getIdentityColumn().getIdentityGenerator());
1908 } else if (table.isGroupTable()) {
1909 for (UserTable userTable : table.getAIS().getUserTables().values()) {
1910 if (userTable.getGroup() == table.getGroup() &&
1911 userTable.getIdentityColumn() != null) {
1912 treeLinks.add(userTable.getIdentityColumn().getIdentityGenerator());
1913 }
1914 }
1915 }
1916
1917 // And the group tree
1918 treeLinks.add(table.getGroup());
1919 // And drop them all
1920 removeTrees(session, treeLinks);
1921 indexStatistics.deleteIndexStatistics(session, tableIndexes);
1922 indexStatistics.deleteIndexStatistics(session, groupIndexes);
1923 }
1924
1925 public void flushIndexes(final Session session) {
1926 try {
1927 putAllDeferredIndexKeys(session);
1928 } catch (PersistitAdapterException e) {
1929 LOG.debug("Exception while trying to flush deferred index keys", e);
1930 throw e;
1931 }
1932 }
1933
1934 public void deleteIndexes(final Session session, final Collection<? extends Index> indexes) {1470 public void deleteIndexes(final Session session, final Collection<? extends Index> indexes) {
1935 List<TreeLink> links = new ArrayList<>(indexes.size());1471 super.deleteIndexes(session, indexes);
1472 // TODO: Generalize. Knowing about FullTextService is wrong.
1936 for(Index index : indexes) {1473 for(Index index : indexes) {
1937 // no trees to drop1474 // no trees to drop
1938 if (index.getIndexType() == IndexType.FULL_TEXT)1475 if (index.getIndexType() == IndexType.FULL_TEXT)
1939 {1476 {
1940 fullTextService.dropIndex(session, (FullTextIndex)index);1477 fullTextService.dropIndex(session, (FullTextIndex)index);
1941 indexes.remove(index);1478 indexes.remove(index);
1942 continue;1479 }
1943 }
1944 final IndexDef indexDef = index.indexDef();
1945 if(indexDef == null) {
1946 throw new IllegalStateException("indexDef is null for index: " + index);
1947 }
1948 links.add(indexDef);
1949 }1480 }
1950 removeTrees(session, links);
1951 indexStatistics.deleteIndexStatistics(session, indexes);
1952 }1481 }
1953 1482
1954 @Override1483 @Override
@@ -1956,28 +1485,6 @@
1956 removeTrees(session, sequences);1485 removeTrees(session, sequences);
1957 }1486 }
19581487
1959 private void buildIndexAddKeys(final SortedSet<KeyState> keys,
1960 final Exchange iEx) {
1961 final long start = System.nanoTime();
1962 try {
1963 for (final KeyState keyState : keys) {
1964 keyState.copyTo(iEx.getKey());
1965 iEx.store();
1966 }
1967 } catch (PersistitException e) {
1968 LOG.error(e.getMessage());
1969 throw new PersistitAdapterException(e);
1970 }
1971 final long elapsed = System.nanoTime() - start;
1972 if (LOG.isInfoEnabled()) {
1973 LOG.debug("Index builder inserted {} keys into index tree {} in {} seconds", new Object[]{
1974 keys.size(),
1975 iEx.getTree().getName(),
1976 elapsed / 1000000000
1977 });
1978 }
1979 }
1980
1981 private RowData mergeRows(RowDef rowDef, RowData currentRow, RowData newRowData, ColumnSelector columnSelector) {1488 private RowData mergeRows(RowDef rowDef, RowData currentRow, RowData newRowData, ColumnSelector columnSelector) {
1982 NewRow mergedRow = NiceRow.fromRowData(currentRow, rowDef);1489 NewRow mergedRow = NiceRow.fromRowData(currentRow, rowDef);
1983 NewRow newRow = new LegacyRowWrapper(rowDef, newRowData);1490 NewRow newRow = new LegacyRowWrapper(rowDef, newRowData);
@@ -1990,24 +1497,6 @@
1990 return mergedRow.toRowData();1497 return mergedRow.toRowData();
1991 }1498 }
19921499
1993 private RowDef rowDefFromExplicitOrId(Session session, RowData rowData) {
1994 RowDef rowDef = rowData.getExplicitRowDef();
1995 if(rowDef == null) {
1996 rowDef = getRowDef(session, rowData.getRowDefId());
1997 }
1998 return rowDef;
1999 }
2000
2001 @Override
2002 public boolean isDeferIndexes() {
2003 return deferIndexes;
2004 }
2005
2006 @Override
2007 public void setDeferIndexes(final boolean defer) {
2008 deferIndexes = defer;
2009 }
2010
2011 private void lockAndCheckVersion(Session session, RowDef rowDef) {1500 private void lockAndCheckVersion(Session session, RowDef rowDef) {
2012 final LockService.Mode mode = LockService.Mode.SHARED;1501 final LockService.Mode mode = LockService.Mode.SHARED;
2013 final int tableID = rowDef.getRowDefId();1502 final int tableID = rowDef.getRowDefId();
@@ -2070,24 +1559,11 @@
2070 return visitor;1559 return visitor;
2071 }1560 }
20721561
2073 public TableStatus getTableStatus(Table table) {
2074 TableStatus ts = null;
2075 if(table.rowDef() != null) {
2076 ts = table.rowDef().getTableStatus();
2077 }
2078 return ts;
2079 }
2080
2081 private static PersistitAdapter adapter(Session session)1562 private static PersistitAdapter adapter(Session session)
2082 {1563 {
2083 return (PersistitAdapter) session.get(StoreAdapter.STORE_ADAPTER_KEY);1564 return (PersistitAdapter) session.get(StoreAdapter.STORE_ADAPTER_KEY);
2084 }1565 }
20851566
2086 private static boolean hasChildren(UserTable table) {
2087 // At runtime, getCandidateChildJoins() = getChildJoins() and doesn't involve building a temp list
2088 return !table.getCandidateChildJoins().isEmpty();
2089 }
2090
2091 private TreeBuilder createTreeBuilder(String name, float bufferBoolFraction) {1567 private TreeBuilder createTreeBuilder(String name, float bufferBoolFraction) {
2092 TreeBuilder tb = new TreeBuilder(getDb(), name, -1, bufferBoolFraction)1568 TreeBuilder tb = new TreeBuilder(getDb(), name, -1, bufferBoolFraction)
2093 // TODO: throw an Akiban dup-key exception once we can handle them1569 // TODO: throw an Akiban dup-key exception once we can handle them
@@ -2153,6 +1629,38 @@
2153 lockKeyAppender.clear();1629 lockKeyAppender.clear();
2154 }1630 }
21551631
1632 @Override
1633 public StoreAdapter createAdapter(Session session, Schema schema) {
1634 return new PersistitAdapter(schema, this, treeService, session, config);
1635 }
1636
1637 @Override
1638 public void truncateTree(Session session, TreeLink treeLink) {
1639 Exchange iEx = treeService.getExchange(session, treeLink);
1640 try {
1641 iEx.removeAll();
1642 } catch (PersistitException e) {
1643 throw PersistitAdapter.wrapPersistitException(session, e);
1644 } finally {
1645 releaseExchange(session, iEx);
1646 }
1647 }
1648
1649 @Override
1650 public void removeTree(Session session, TreeLink treeLink) {
1651 try {
1652 if(!schemaManager.treeRemovalIsDelayed()) {
1653 Exchange ex = treeService.getExchange(session, treeLink);
1654 ex.removeTree();
1655 // Do not releaseExchange, causes caching and leak for now unused tree
1656 }
1657 schemaManager.treeWasRemoved(session, treeLink.getSchemaName(), treeLink.getTreeName());
1658 } catch (PersistitException e) {
1659 LOG.debug("Exception removing tree from Persistit", e);
1660 throw PersistitAdapter.wrapPersistitException(session, e);
1661 }
1662 }
1663
2156 private class Bulkload {1664 private class Bulkload {
21571665
2158 Bulkload(final Persistit persistit, AkibanInformationSchema ais) {1666 Bulkload(final Persistit persistit, AkibanInformationSchema ais) {
21591667
=== modified file 'src/main/java/com/akiban/server/store/PersistitStoreSchemaManager.java'
--- src/main/java/com/akiban/server/store/PersistitStoreSchemaManager.java 2013-04-11 18:35:20 +0000
+++ src/main/java/com/akiban/server/store/PersistitStoreSchemaManager.java 2013-05-20 14:47:34 +0000
@@ -474,11 +474,7 @@
474 for(ChangedTableDescription desc : alteredTables) {474 for(ChangedTableDescription desc : alteredTables) {
475 if(desc.isNewGroup()) {475 if(desc.isNewGroup()) {
476 UserTable oldTable = oldAIS.getUserTable(desc.getOldName());476 UserTable oldTable = oldAIS.getUserTable(desc.getOldName());
477 try {477 oldTable.rowDef().getTableStatus().setOrdinal(0);
478 oldTable.rowDef().getTableStatus().setOrdinal(0);
479 } catch(PersistitException e) {
480 throw wrapPersistitException(session, e);
481 }
482 }478 }
483 }479 }
484480
485481
=== modified file 'src/main/java/com/akiban/server/store/Store.java'
--- src/main/java/com/akiban/server/store/Store.java 2013-04-14 00:26:23 +0000
+++ src/main/java/com/akiban/server/store/Store.java 2013-05-20 14:47:34 +0000
@@ -17,57 +17,40 @@
1717
18package com.akiban.server.store;18package com.akiban.server.store;
1919
20import com.akiban.ais.model.AkibanInformationSchema;
20import com.akiban.ais.model.Group;21import com.akiban.ais.model.Group;
21import com.akiban.ais.model.Index;22import com.akiban.ais.model.Index;
22import com.akiban.ais.model.Sequence;23import com.akiban.ais.model.Sequence;
23import com.akiban.ais.model.Table;24import com.akiban.ais.model.TableName;
25import com.akiban.ais.model.UserTable;
26import com.akiban.qp.operator.StoreAdapter;
27import com.akiban.qp.rowtype.Schema;
24import com.akiban.server.TableStatistics;28import com.akiban.server.TableStatistics;
25import com.akiban.server.api.dml.ColumnSelector;29import com.akiban.server.api.dml.ColumnSelector;
26import com.akiban.server.api.dml.scan.ScanLimit;30import com.akiban.server.api.dml.scan.ScanLimit;
27import com.akiban.server.rowdata.RowData;31import com.akiban.server.rowdata.RowData;
28import com.akiban.server.rowdata.RowDef;32import com.akiban.server.rowdata.RowDef;
29import com.akiban.server.service.session.Session;33import com.akiban.server.service.session.Session;
34import com.akiban.server.service.tree.KeyCreator;
30import com.akiban.server.service.tree.TreeLink;35import com.akiban.server.service.tree.TreeLink;
31import com.persistit.exception.PersistitException;36import com.akiban.server.store.statistics.IndexStatisticsService;
32import com.persistit.exception.RollbackException;
3337
34import java.util.Collection;38import java.util.Collection;
3539
36/**40public interface Store extends KeyCreator {
37 * An abstraction for a layer that stores and retrieves data
38 *
39 * @author peter
40 *
41 */
42public interface Store {
4341
44 /** Get the RowDef for the given ID. Note, a transaction should be active before calling this. */42 /** Get the RowDef for the given ID. Note, a transaction should be active before calling this. */
45 RowDef getRowDef(Session session, int rowDefID);43 RowDef getRowDef(Session session, int rowDefID);
4644 RowDef getRowDef(Session session, TableName tableName);
47 void writeRow(Session session, RowData rowData) throws PersistitException;45 AkibanInformationSchema getAIS(Session session);
4846
49 void deleteRow(Session session, RowData rowData, boolean deleteIndexes, boolean cascadeDelete) throws PersistitException;47 void writeRow(Session session, RowData rowData);
48
49 void deleteRow(Session session, RowData rowData, boolean deleteIndexes, boolean cascadeDelete);
5050
51 void updateRow(Session session, RowData oldRowData,51 void updateRow(Session session, RowData oldRowData,
52 RowData newRowData,52 RowData newRowData,
53 ColumnSelector columnSelector, Index[] indexes) throws PersistitException;53 ColumnSelector columnSelector, Index[] indexes);
54
55 /**
56 * See {@link #newRowCollector(Session, int, int, int, byte[], RowData, ColumnSelector, RowData, ColumnSelector, ScanLimit)}
57 * for parameter descriptions.
58 * @throws Exception
59 *
60 * @deprecated This constructor is ambiguous and may not return the expected rows. Fields from <code>start</code>
61 * and <code>end</code> that are <code>NULL</code> are considered to be <b>unset</b>.
62 */
63 RowCollector newRowCollector(Session session,
64 int rowDefId,
65 int indexId,
66 int scanFlags,
67 RowData start,
68 RowData end,
69 byte[] columnBitMap,
70 ScanLimit scanLimit);
7154
72 /**55 /**
73 * Create a new RowCollector.56 * Create a new RowCollector.
@@ -134,13 +117,10 @@
134 * Truncate the given group. This includes indexes from all tables, group117 * Truncate the given group. This includes indexes from all tables, group
135 * indexes, the group itself, and all table statuses.118 * indexes, the group itself, and all table statuses.
136 */119 */
137 void truncateGroup(Session session, Group group) throws PersistitException;120 void truncateGroup(Session session, Group group);
138121
139 void truncateTableStatus(Session session, int rowDefId) throws RollbackException, PersistitException;122 void truncateTableStatus(Session session, int rowDefId);
140123
141 boolean isDeferIndexes();
142 void setDeferIndexes(boolean b);
143 void flushIndexes(Session session);
144 void deleteIndexes(Session session, Collection<? extends Index> indexes);124 void deleteIndexes(Session session, Collection<? extends Index> indexes);
145 void buildIndexes(Session session, Collection<? extends Index> indexes, boolean deferIndexes);125 void buildIndexes(Session session, Collection<? extends Index> indexes, boolean deferIndexes);
146126
@@ -149,10 +129,11 @@
149 * Remove all trees, and their contents, associated with the given table.129 * Remove all trees, and their contents, associated with the given table.
150 * @param session Session130 * @param session Session
151 * @param table Table131 * @param table Table
152 * @throws PersistitException 132 * @throws Exception
153 * @throws Exception
154 */133 */
155 void removeTrees(Session session, Table table);134 void removeTrees(Session session, UserTable table);
135 void removeTree(Session session, TreeLink treeLink);
136 void truncateTree(Session session, TreeLink treeLink);
156137
157 /**138 /**
158 * Low level operation. Removes the given trees and <i>only</i> the given trees.139 * Low level operation. Removes the given trees and <i>only</i> the given trees.
@@ -171,4 +152,8 @@
171 void finishBulkLoad(Session session);152 void finishBulkLoad(Session session);
172153
173 boolean isBulkloading();154 boolean isBulkloading();
155
156 void setIndexStatistics(IndexStatisticsService indexStatistics);
157
158 StoreAdapter createAdapter(Session session, Schema schema);
174}159}
175160
=== modified file 'src/main/java/com/akiban/server/store/statistics/IndexStatisticsServiceImpl.java'
--- src/main/java/com/akiban/server/store/statistics/IndexStatisticsServiceImpl.java 2013-04-11 05:51:16 +0000
+++ src/main/java/com/akiban/server/store/statistics/IndexStatisticsServiceImpl.java 2013-05-20 14:47:34 +0000
@@ -146,7 +146,7 @@
146 if (table.hasMemoryTableFactory()) {146 if (table.hasMemoryTableFactory()) {
147 return table.getMemoryTableFactory().rowCount();147 return table.getMemoryTableFactory().rowCount();
148 } else {148 } else {
149 return store.getTableStatus(table).getRowCount();149 return table.rowDef().getTableStatus().getRowCount();
150 }150 }
151 }151 }
152 final Exchange ex = store.getExchange(session, index);152 final Exchange ex = store.getExchange(session, index);
@@ -161,7 +161,7 @@
161 @Override161 @Override
162 public long countEntriesApproximate(Session session, Index index) {162 public long countEntriesApproximate(Session session, Index index) {
163 if (index.isTableIndex()) {163 if (index.isTableIndex()) {
164 return store.getTableStatus(((TableIndex)index).getTable()).getApproximateRowCount();164 return index.leafMostTable().rowDef().getTableStatus().getApproximateRowCount();
165 }165 }
166 final Exchange ex = store.getExchange(session, index);166 final Exchange ex = store.getExchange(session, index);
167 try {167 try {
168168
=== modified file 'src/main/java/com/akiban/server/store/statistics/PersistitStoreIndexStatistics.java'
--- src/main/java/com/akiban/server/store/statistics/PersistitStoreIndexStatistics.java 2013-03-22 20:05:57 +0000
+++ src/main/java/com/akiban/server/store/statistics/PersistitStoreIndexStatistics.java 2013-05-20 14:47:34 +0000
@@ -284,6 +284,9 @@
284 RowData rowData = new RowData(new byte[INITIAL_ROW_SIZE]);284 RowData rowData = new RowData(new byte[INITIAL_ROW_SIZE]);
285 RowDef indexStatisticsRowDef = getIndexStatsRowDef(session);285 RowDef indexStatisticsRowDef = getIndexStatsRowDef(session);
286 RowDef indexStatisticsEntryRowDef = getIndexStatsEntryRowDef(session);286 RowDef indexStatisticsEntryRowDef = getIndexStatsEntryRowDef(session);
287 if(index.indexDef() == null) {
288 return;
289 }
287 int tableId = index.indexDef().getRowDef().getRowDefId();290 int tableId = index.indexDef().getRowDef().getRowDefId();
288 int indexId = index.getIndexId();291 int indexId = index.getIndexId();
289 // Delete index_statistics_entry rows.292 // Delete index_statistics_entry rows.
290293
=== modified file 'src/test/java/com/akiban/server/test/it/keyupdate/FixCountStarIT.java'
--- src/test/java/com/akiban/server/test/it/keyupdate/FixCountStarIT.java 2013-04-11 05:51:16 +0000
+++ src/test/java/com/akiban/server/test/it/keyupdate/FixCountStarIT.java 2013-05-20 14:47:34 +0000
@@ -95,7 +95,7 @@
95 public void run() {95 public void run() {
96 if (index.isTableIndex()) {96 if (index.isTableIndex()) {
97 TableIndex tIndex = (TableIndex) index;97 TableIndex tIndex = (TableIndex) index;
98 store().getPersistitStore().getTableStatus(tIndex.getTable()).setRowCount(newVal);98 tIndex.leafMostTable().rowDef().getTableStatus().setRowCount(newVal);
99 }99 }
100 else {100 else {
101 PersistitStore store = store().getPersistitStore();101 PersistitStore store = store().getPersistitStore();
102102
=== modified file 'src/test/java/com/akiban/server/test/it/rowtests/ObjectToKeyIT.java'
--- src/test/java/com/akiban/server/test/it/rowtests/ObjectToKeyIT.java 2013-03-22 20:05:57 +0000
+++ src/test/java/com/akiban/server/test/it/rowtests/ObjectToKeyIT.java 2013-05-20 14:47:34 +0000
@@ -38,7 +38,7 @@
38 }38 }
3939
40 private void testObjectToKey(FieldDef field, Object... testValues) throws PersistitException {40 private void testObjectToKey(FieldDef field, Object... testValues) throws PersistitException {
41 Key key = persistitStore().getKey();41 Key key = persistitStore().createKey();
42 PersistitKeyAppender appender = PersistitKeyAppender.create(key);42 PersistitKeyAppender appender = PersistitKeyAppender.create(key);
43 for(Object inObj : testValues) {43 for(Object inObj : testValues) {
44 key.clear();44 key.clear();
4545
=== modified file 'src/test/java/com/akiban/server/test/it/store/AbstractScanBase.java'
--- src/test/java/com/akiban/server/test/it/store/AbstractScanBase.java 2013-03-27 04:42:10 +0000
+++ src/test/java/com/akiban/server/test/it/store/AbstractScanBase.java 2013-05-20 14:47:34 +0000
@@ -139,8 +139,8 @@
139 final byte[] columnBitMap, final int indexId) throws Exception {139 final byte[] columnBitMap, final int indexId) throws Exception {
140 int scanCount = 0;140 int scanCount = 0;
141 result.clear();141 result.clear();
142 final RowCollector rc = store().newRowCollector(session(), rowDefId, indexId,142 final RowCollector rc = store().newRowCollector(session(), scanFlags, rowDefId, indexId, columnBitMap,
143 scanFlags, start, end, columnBitMap, null);143 start, null, end, null, null);
144 if (VERBOSE) {144 if (VERBOSE) {
145 System.out.println("Test " + test);145 System.out.println("Test " + test);
146 }146 }

Subscribers

People subscribed via source and target branches