Merge lp:~nwilliams/akiban-server/abstract-store into lp:~akiban-technologies/akiban-server/trunk
- abstract-store
- Merge into trunk
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 |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Thomas Jones-Low | Needs Fixing | ||
Mike McMahon | Approve | ||
Review via email: mp+164745@code.launchpad.net |
Commit message
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.
Thomas Jones-Low (tjoneslo) wrote : | # |
There were 2 failures during build/test:
* job server-build failed at build number 4030: http://
* view must-pass failed: server-build is yellow
Thomas Jones-Low (tjoneslo) wrote : | # |
Build system failure, not merge proposal failure. Trying again.
Thomas Jones-Low (tjoneslo) wrote : | # |
There were 2 failures during build/test:
* job server-build failed at build number 4032: http://
* view must-pass failed: server-build is yellow
Nathan Williams (nwilliams) wrote : | # |
Manually ran ITs on sleepy.
Preview Diff
1 | === modified file 'src/main/java/com/akiban/ais/model/UserTable.java' |
2 | --- src/main/java/com/akiban/ais/model/UserTable.java 2013-04-07 01:22:07 +0000 |
3 | +++ src/main/java/com/akiban/ais/model/UserTable.java 2013-05-20 14:47:34 +0000 |
4 | @@ -168,6 +168,10 @@ |
5 | return Collections.unmodifiableList(candidateChildJoins); |
6 | } |
7 | |
8 | + public boolean hasChildren() { |
9 | + return !getCandidateChildJoins().isEmpty(); |
10 | + } |
11 | + |
12 | public Join getParentJoin() |
13 | { |
14 | Join parentJoin = null; |
15 | |
16 | === modified file 'src/main/java/com/akiban/qp/persistitadapter/OneTableRowCollector.java' |
17 | --- src/main/java/com/akiban/qp/persistitadapter/OneTableRowCollector.java 2013-03-22 20:05:57 +0000 |
18 | +++ src/main/java/com/akiban/qp/persistitadapter/OneTableRowCollector.java 2013-05-20 14:47:34 +0000 |
19 | @@ -26,15 +26,13 @@ |
20 | import com.akiban.server.api.dml.scan.NewRow; |
21 | import com.akiban.server.rowdata.RowData; |
22 | import com.akiban.server.rowdata.RowDef; |
23 | -import com.akiban.server.service.config.ConfigurationService; |
24 | import com.akiban.server.service.session.Session; |
25 | -import com.akiban.server.store.PersistitStore; |
26 | +import com.akiban.server.store.Store; |
27 | |
28 | public class OneTableRowCollector extends OperatorBasedRowCollector |
29 | { |
30 | - OneTableRowCollector(ConfigurationService config, |
31 | - Session session, |
32 | - PersistitStore store, |
33 | + OneTableRowCollector(Session session, |
34 | + Store store, |
35 | RowDef rowDef, |
36 | int indexId, |
37 | int scanFlags, |
38 | @@ -43,7 +41,7 @@ |
39 | RowData end, |
40 | ColumnSelector endColumns) |
41 | { |
42 | - super(store, session, config); |
43 | + super(store, session); |
44 | // rootmostQueryTable |
45 | queryRootTable = rowDef.userTable(); |
46 | queryRootType = schema.userTableRowType(queryRootTable); |
47 | |
48 | === modified file 'src/main/java/com/akiban/qp/persistitadapter/OperatorBasedRowCollector.java' |
49 | --- src/main/java/com/akiban/qp/persistitadapter/OperatorBasedRowCollector.java 2013-04-30 22:35:43 +0000 |
50 | +++ src/main/java/com/akiban/qp/persistitadapter/OperatorBasedRowCollector.java 2013-05-20 14:47:34 +0000 |
51 | @@ -23,6 +23,8 @@ |
52 | import com.akiban.qp.operator.Limit; |
53 | import com.akiban.qp.operator.Operator; |
54 | import com.akiban.qp.operator.SimpleQueryContext; |
55 | +import com.akiban.qp.operator.StoreAdapter; |
56 | +import com.akiban.qp.row.AbstractRow; |
57 | import com.akiban.qp.row.Row; |
58 | import com.akiban.qp.rowtype.*; |
59 | import com.akiban.qp.rowtype.Schema; |
60 | @@ -38,6 +40,7 @@ |
61 | import com.akiban.server.service.session.Session; |
62 | import com.akiban.server.store.PersistitStore; |
63 | import com.akiban.server.store.RowCollector; |
64 | +import com.akiban.server.store.Store; |
65 | import com.akiban.server.types3.Types3Switch; |
66 | import com.akiban.util.GrowableByteBuffer; |
67 | import com.akiban.util.ShareHolder; |
68 | @@ -78,12 +81,12 @@ |
69 | // the current row across these two invocations. |
70 | boolean wasHeld = false; |
71 | boolean wroteToPayload = false; |
72 | - PersistitGroupRow row; |
73 | + AbstractRow row; |
74 | if (currentRow.isEmpty()) { |
75 | - row = (PersistitGroupRow) cursor.next(); |
76 | + row = (AbstractRow) cursor.next(); |
77 | } else { |
78 | wasHeld = true; |
79 | - row = (PersistitGroupRow) currentRow.get(); |
80 | + row = (AbstractRow) currentRow.get(); |
81 | currentRow.release(); |
82 | } |
83 | if (row == null) { |
84 | @@ -117,7 +120,7 @@ |
85 | public RowData collectNextRow() |
86 | { |
87 | RowData rowData = null; |
88 | - PersistitGroupRow row = (PersistitGroupRow) cursor.next(); |
89 | + AbstractRow row = (AbstractRow) cursor.next(); |
90 | if (row == null) { |
91 | close(); |
92 | } else { |
93 | @@ -196,9 +199,8 @@ |
94 | |
95 | // OperatorBasedRowCollector interface |
96 | |
97 | - public static OperatorBasedRowCollector newCollector(ConfigurationService config, |
98 | - Session session, |
99 | - PersistitStore store, |
100 | + public static OperatorBasedRowCollector newCollector(Session session, |
101 | + Store store, |
102 | int scanFlags, |
103 | RowDef rowDef, |
104 | int indexId, |
105 | @@ -217,8 +219,7 @@ |
106 | throw new IllegalArgumentException("Must scan a UserTable: " + rowDef); |
107 | } |
108 | OperatorBasedRowCollector rowCollector = |
109 | - new OneTableRowCollector(config, |
110 | - session, |
111 | + new OneTableRowCollector(session, |
112 | store, |
113 | rowDef, |
114 | indexId, |
115 | @@ -234,12 +235,10 @@ |
116 | return rowCollector; |
117 | } |
118 | |
119 | - protected OperatorBasedRowCollector(PersistitStore store, Session session, ConfigurationService config) |
120 | + protected OperatorBasedRowCollector(Store store, Session session) |
121 | { |
122 | this.schema = SchemaCache.globalSchema(store.getAIS(session)); |
123 | - // Passing null to PersistitAdapter's TreeService argument. TreeService is only needed for sorting, |
124 | - // which OBRC doesn't use. |
125 | - this.adapter = new PersistitAdapter(schema, store, null, session, config); |
126 | + this.adapter = store.createAdapter(session, schema); |
127 | this.rowCollectorId = idCounter.getAndIncrement(); |
128 | } |
129 | |
130 | @@ -397,7 +396,7 @@ |
131 | |
132 | private long rowCollectorId; |
133 | protected final Schema schema; |
134 | - protected PersistitAdapter adapter; |
135 | + protected StoreAdapter adapter; |
136 | protected UserTable queryRootTable; |
137 | protected UserTableRowType queryRootType; |
138 | protected TableIndex predicateIndex; |
139 | |
140 | === modified file 'src/main/java/com/akiban/qp/persistitadapter/OperatorStore.java' |
141 | --- src/main/java/com/akiban/qp/persistitadapter/OperatorStore.java 2013-04-30 22:35:43 +0000 |
142 | +++ src/main/java/com/akiban/qp/persistitadapter/OperatorStore.java 2013-05-20 14:47:34 +0000 |
143 | @@ -48,7 +48,6 @@ |
144 | import com.akiban.server.store.SchemaManager; |
145 | import com.akiban.server.types.ToObjectValueTarget; |
146 | import com.akiban.server.types.ValueSource; |
147 | -import com.akiban.server.types3.Types3Switch; |
148 | import com.akiban.sql.optimizer.rule.PlanGenerator; |
149 | import com.akiban.util.tap.InOutTap; |
150 | import com.akiban.util.tap.PointTap; |
151 | @@ -86,7 +85,6 @@ |
152 | |
153 | @Override |
154 | public void updateRow(Session session, RowData oldRowData, RowData newRowData, ColumnSelector columnSelector, Index[] indexes) |
155 | - throws PersistitException |
156 | { |
157 | if(indexes != null) { |
158 | throw new IllegalStateException("Unexpected indexes: " + Arrays.toString(indexes)); |
159 | @@ -169,7 +167,7 @@ |
160 | } |
161 | |
162 | @Override |
163 | - public void writeRow(Session session, RowData rowData) throws PersistitException { |
164 | + public void writeRow(Session session, RowData rowData) { |
165 | INSERT_TOTAL.in(); |
166 | INSERT_MAINTENANCE.in(); |
167 | try { |
168 | @@ -194,7 +192,7 @@ |
169 | } |
170 | |
171 | @Override |
172 | - public void deleteRow(Session session, RowData rowData, boolean deleteIndexes, boolean cascadeDelete) throws PersistitException { |
173 | + public void deleteRow(Session session, RowData rowData, boolean deleteIndexes, boolean cascadeDelete) { |
174 | DELETE_TOTAL.in(); |
175 | DELETE_MAINTENANCE.in(); |
176 | try { |
177 | @@ -288,14 +286,14 @@ |
178 | BitSet columnDifferences, |
179 | OperatorStoreGIHandler handler, |
180 | OperatorStoreGIHandler.Action action) |
181 | - throws PersistitException |
182 | { |
183 | UserTable userTable = ais.getUserTable(rowData.getRowDefId()); |
184 | if(canSkipMaintenance(userTable)) { |
185 | return; |
186 | } |
187 | - Exchange hEx = adapter.takeExchange(userTable.getGroup()); |
188 | + Exchange hEx = null; |
189 | try { |
190 | + hEx = adapter.takeExchange(userTable.getGroup()); |
191 | // the "false" at the end of constructHKey toggles whether the RowData should be modified to increment |
192 | // the hidden PK field, if there is one. For PK-less rows, this field have already been incremented by now, |
193 | // so we don't want to increment it again |
194 | @@ -316,8 +314,12 @@ |
195 | SKIP_MAINTENANCE.hit(); |
196 | } |
197 | } |
198 | + } catch(PersistitException e) { |
199 | + throw PersistitAdapter.wrapPersistitException(session, e); |
200 | } finally { |
201 | - adapter.returnExchange(hEx); |
202 | + if(hEx != null) { |
203 | + adapter.returnExchange(hEx); |
204 | + } |
205 | } |
206 | } |
207 | |
208 | @@ -357,7 +359,6 @@ |
209 | AkibanInformationSchema ais, |
210 | PersistitAdapter adapter, |
211 | RowData rowData) |
212 | - throws PersistitException |
213 | { |
214 | UserTable uTable = ais.getUserTable(rowData.getRowDefId()); |
215 | |
216 | |
217 | === modified file 'src/main/java/com/akiban/qp/persistitadapter/PersistitAdapter.java' |
218 | --- src/main/java/com/akiban/qp/persistitadapter/PersistitAdapter.java 2013-04-11 05:51:16 +0000 |
219 | +++ src/main/java/com/akiban/qp/persistitadapter/PersistitAdapter.java 2013-05-20 14:47:34 +0000 |
220 | @@ -129,10 +129,6 @@ |
221 | } catch (InvalidOperationException e) { |
222 | rollbackIfNeeded(e); |
223 | throw e; |
224 | - } catch (PersistitException e) { |
225 | - rollbackIfNeeded(e); |
226 | - handlePersistitException(e); |
227 | - assert false; |
228 | } |
229 | finally { |
230 | leaveUpdateStep(oldStep); |
231 | @@ -149,10 +145,6 @@ |
232 | } catch (InvalidOperationException e) { |
233 | rollbackIfNeeded(e); |
234 | throw e; |
235 | - } catch (PersistitException e) { |
236 | - rollbackIfNeeded(e); |
237 | - handlePersistitException(e); |
238 | - assert false; |
239 | } |
240 | finally { |
241 | leaveUpdateStep(oldStep); |
242 | @@ -170,10 +162,6 @@ |
243 | } catch (InvalidOperationException e) { |
244 | rollbackIfNeeded(e); |
245 | throw e; |
246 | - } catch (PersistitException e) { |
247 | - rollbackIfNeeded(e); |
248 | - handlePersistitException(e); |
249 | - assert false; |
250 | } |
251 | finally { |
252 | leaveUpdateStep(oldStep); |
253 | @@ -203,10 +191,6 @@ |
254 | } catch (InvalidOperationException e) { |
255 | rollbackIfNeeded(e); |
256 | throw e; |
257 | - } catch (PersistitException e) { |
258 | - rollbackIfNeeded(e); |
259 | - handlePersistitException(e); |
260 | - assert false; |
261 | } |
262 | finally { |
263 | leaveUpdateStep(oldStep); |
264 | @@ -216,11 +200,7 @@ |
265 | @Override |
266 | public long rowCount(RowType tableType) { |
267 | RowDef rowDef = tableType.userTable().rowDef(); |
268 | - try { |
269 | - return rowDef.getTableStatus().getRowCount(); |
270 | - } catch(PersistitInterruptedException e) { |
271 | - throw new QueryCanceledException(getSession()); |
272 | - } |
273 | + return rowDef.getTableStatus().getRowCount(); |
274 | } |
275 | |
276 | @Override |
277 | @@ -235,7 +215,7 @@ |
278 | key = persistitKeyValueSource.key(); |
279 | depth = persistitKeyValueSource.depth(); |
280 | } else { |
281 | - key = persistit.getKey(); |
282 | + key = persistit.createKey(); |
283 | collator.append(key, valueSource.getString()); |
284 | depth = 0; |
285 | } |
286 | @@ -325,7 +305,10 @@ |
287 | public static boolean isFromInterruption(Exception e) { |
288 | Throwable cause = e.getCause(); |
289 | return (e instanceof PersistitInterruptedException) || |
290 | - ((cause != null) && (cause instanceof InterruptedIOException || cause instanceof InterruptedException)); |
291 | + ((cause != null) && |
292 | + (cause instanceof PersistitInterruptedException || |
293 | + cause instanceof InterruptedIOException || |
294 | + cause instanceof InterruptedException)); |
295 | } |
296 | |
297 | public static RuntimeException wrapPersistitException(Session session, PersistitException e) |
298 | @@ -418,7 +401,10 @@ |
299 | |
300 | // For use by this class |
301 | private void rollbackIfNeeded(Exception e) { |
302 | - if((e instanceof DuplicateKeyException) || (e instanceof PersistitException) || isFromInterruption(e)) { |
303 | + if((e instanceof DuplicateKeyException) || |
304 | + (e instanceof PersistitException) || |
305 | + (e instanceof PersistitAdapterException) || |
306 | + isFromInterruption(e)) { |
307 | Transaction txn = transaction(); |
308 | if(txn.isActive()) { |
309 | txn.rollback(); |
310 | |
311 | === modified file 'src/main/java/com/akiban/qp/persistitadapter/PersistitGroupRow.java' |
312 | --- src/main/java/com/akiban/qp/persistitadapter/PersistitGroupRow.java 2013-03-22 20:05:57 +0000 |
313 | +++ src/main/java/com/akiban/qp/persistitadapter/PersistitGroupRow.java 2013-05-20 14:47:34 +0000 |
314 | @@ -159,6 +159,7 @@ |
315 | } while (exception != null); |
316 | } |
317 | |
318 | + @Override |
319 | public RowData rowData() |
320 | { |
321 | return rowData; |
322 | |
323 | === modified file 'src/main/java/com/akiban/qp/persistitadapter/indexrow/PersistitIndexRow.java' |
324 | --- src/main/java/com/akiban/qp/persistitadapter/indexrow/PersistitIndexRow.java 2013-03-22 20:05:57 +0000 |
325 | +++ src/main/java/com/akiban/qp/persistitadapter/indexrow/PersistitIndexRow.java 2013-05-20 14:47:34 +0000 |
326 | @@ -128,7 +128,7 @@ |
327 | protected PersistitIndexRow(PersistitAdapter adapter, IndexRowType indexRowType) |
328 | { |
329 | super(adapter); |
330 | - this.keyState = adapter.persistit().getKey(); |
331 | + this.keyState = adapter.persistit().createKey(); |
332 | resetForWrite(indexRowType.index(), keyState); |
333 | this.indexRowType = indexRowType; |
334 | this.leafmostTable = (UserTable) index.leafMostTable(); |
335 | |
336 | === modified file 'src/main/java/com/akiban/qp/row/AbstractRow.java' |
337 | --- src/main/java/com/akiban/qp/row/AbstractRow.java 2013-03-22 20:05:57 +0000 |
338 | +++ src/main/java/com/akiban/qp/row/AbstractRow.java 2013-05-20 14:47:34 +0000 |
339 | @@ -22,6 +22,7 @@ |
340 | import com.akiban.qp.rowtype.IndexRowType; |
341 | import com.akiban.qp.rowtype.RowType; |
342 | import com.akiban.server.Quote; |
343 | +import com.akiban.server.rowdata.RowData; |
344 | import com.akiban.server.types.ValueSource; |
345 | import com.akiban.server.types.util.ValueSources; |
346 | import com.akiban.server.types3.TClass; |
347 | @@ -166,6 +167,10 @@ |
348 | return builder.toString(); |
349 | } |
350 | |
351 | + public RowData rowData() { |
352 | + throw new UnsupportedOperationException(); |
353 | + } |
354 | + |
355 | // for use by subclasses |
356 | protected void afterRelease() {} |
357 | protected void beforeAcquire() {} |
358 | |
359 | === modified file 'src/main/java/com/akiban/server/PersistitAccumulatorTableStatusCache.java' |
360 | --- src/main/java/com/akiban/server/PersistitAccumulatorTableStatusCache.java 2013-04-11 06:15:45 +0000 |
361 | +++ src/main/java/com/akiban/server/PersistitAccumulatorTableStatusCache.java 2013-05-20 14:47:34 +0000 |
362 | @@ -18,6 +18,7 @@ |
363 | package com.akiban.server; |
364 | |
365 | import com.akiban.qp.memoryadapter.MemoryTableFactory; |
366 | +import com.akiban.qp.persistitadapter.PersistitAdapter; |
367 | import com.akiban.server.error.PersistitAdapterException; |
368 | import com.akiban.server.rowdata.IndexDef; |
369 | import com.akiban.server.rowdata.RowDef; |
370 | @@ -97,18 +98,30 @@ |
371 | } |
372 | |
373 | @Override |
374 | - public long getAutoIncrement() throws PersistitInterruptedException { |
375 | - return autoIncrement.getSnapshot(); |
376 | - } |
377 | - |
378 | - @Override |
379 | - public int getOrdinal() throws PersistitInterruptedException { |
380 | - return (int) ordinal.getSnapshot(); |
381 | - } |
382 | - |
383 | - @Override |
384 | - public long getRowCount() throws PersistitInterruptedException { |
385 | - return rowCount.getSnapshot(); |
386 | + public long getAutoIncrement() { |
387 | + try { |
388 | + return autoIncrement.getSnapshot(); |
389 | + } catch(PersistitInterruptedException e) { |
390 | + throw PersistitAdapter.wrapPersistitException(null, e); |
391 | + } |
392 | + } |
393 | + |
394 | + @Override |
395 | + public int getOrdinal() { |
396 | + try { |
397 | + return (int) ordinal.getSnapshot(); |
398 | + } catch(PersistitInterruptedException e) { |
399 | + throw PersistitAdapter.wrapPersistitException(null, e); |
400 | + } |
401 | + } |
402 | + |
403 | + @Override |
404 | + public long getRowCount() { |
405 | + try { |
406 | + return rowCount.getSnapshot(); |
407 | + } catch(PersistitInterruptedException e) { |
408 | + throw PersistitAdapter.wrapPersistitException(null, e); |
409 | + } |
410 | } |
411 | |
412 | @Override |
413 | @@ -127,8 +140,12 @@ |
414 | } |
415 | |
416 | @Override |
417 | - public long getUniqueID() throws PersistitInterruptedException { |
418 | - return uniqueID.getSnapshot(); |
419 | + public long getUniqueID() { |
420 | + try { |
421 | + return uniqueID.getSnapshot(); |
422 | + } catch(PersistitInterruptedException e) { |
423 | + throw PersistitAdapter.wrapPersistitException(null, e); |
424 | + } |
425 | } |
426 | |
427 | @Override |
428 | @@ -151,23 +168,31 @@ |
429 | rowCount.sumAdd(count); |
430 | } |
431 | |
432 | - public void setOrdinal(int ordinal) throws PersistitInterruptedException { |
433 | - this.ordinal.set(ordinal); |
434 | + public void setOrdinal(int ordinal) { |
435 | + try { |
436 | + this.ordinal.set(ordinal); |
437 | + } catch(PersistitInterruptedException e) { |
438 | + throw PersistitAdapter.wrapPersistitException(null, e); |
439 | + } |
440 | } |
441 | |
442 | @Override |
443 | - public long createNewUniqueID() throws PersistitInterruptedException { |
444 | + public long createNewUniqueID() { |
445 | return uniqueID.seqAllocate(); |
446 | } |
447 | |
448 | @Override |
449 | - public void truncate() throws PersistitInterruptedException { |
450 | - internalSetRowCount(0); |
451 | - internalSetAutoIncrement(0, true); |
452 | + public void truncate() { |
453 | + try { |
454 | + internalSetRowCount(0); |
455 | + internalSetAutoIncrement(0, true); |
456 | + } catch(PersistitInterruptedException e) { |
457 | + throw PersistitAdapter.wrapPersistitException(null, e); |
458 | + } |
459 | } |
460 | |
461 | @Override |
462 | - public void setAutoIncrement(long value) throws PersistitInterruptedException { |
463 | + public void setAutoIncrement(long value) { |
464 | internalSetAutoIncrement(value, false); |
465 | } |
466 | |
467 | @@ -189,8 +214,12 @@ |
468 | rowCount.set(rowCountValue); |
469 | } |
470 | |
471 | - private void internalSetAutoIncrement(long autoIncrementValue, boolean evenIfLess) throws PersistitInterruptedException { |
472 | - autoIncrement.set(autoIncrementValue, evenIfLess); |
473 | + private void internalSetAutoIncrement(long autoIncrementValue, boolean evenIfLess) { |
474 | + try { |
475 | + autoIncrement.set(autoIncrementValue, evenIfLess); |
476 | + } catch(PersistitInterruptedException e) { |
477 | + throw PersistitAdapter.wrapPersistitException(null, e); |
478 | + } |
479 | } |
480 | } |
481 | |
482 | |
483 | === modified file 'src/main/java/com/akiban/server/TableStatus.java' |
484 | --- src/main/java/com/akiban/server/TableStatus.java 2013-04-11 06:15:45 +0000 |
485 | +++ src/main/java/com/akiban/server/TableStatus.java 2013-05-20 14:47:34 +0000 |
486 | @@ -34,34 +34,34 @@ |
487 | void rowsWritten(long count); |
488 | |
489 | /** Reset, but do not remove, the state of a table. */ |
490 | - void truncate() throws PersistitInterruptedException; |
491 | + void truncate(); |
492 | |
493 | /** Set the auto-increment value of a given table. */ |
494 | - void setAutoIncrement(long value) throws PersistitInterruptedException; |
495 | + void setAutoIncrement(long value); |
496 | |
497 | /** Set the RowDef of a given table.*/ |
498 | void setRowDef(RowDef rowDef); |
499 | |
500 | /** Create a brand new, unique ID for the given table. */ |
501 | - long createNewUniqueID() throws PersistitInterruptedException; |
502 | + long createNewUniqueID(); |
503 | |
504 | /** Set the ordinal value of a given table. */ |
505 | - void setOrdinal(int value) throws PersistitInterruptedException; |
506 | + void setOrdinal(int value); |
507 | |
508 | /** |
509 | * @return Current auto-increment value of the assocated table. |
510 | */ |
511 | - long getAutoIncrement() throws PersistitInterruptedException; |
512 | + long getAutoIncrement(); |
513 | |
514 | /** |
515 | * @return Ordinal of the associated table. |
516 | */ |
517 | - int getOrdinal() throws PersistitInterruptedException; |
518 | + int getOrdinal(); |
519 | |
520 | /** |
521 | * @return Current number of rows in the associated table. |
522 | */ |
523 | - long getRowCount() throws PersistitInterruptedException; |
524 | + long getRowCount(); |
525 | |
526 | /** |
527 | * @return Approximate number of rows in the associated table. |
528 | @@ -71,7 +71,7 @@ |
529 | /** |
530 | * @return The <b>last</b> unique value used for the associated table. |
531 | */ |
532 | - long getUniqueID() throws PersistitInterruptedException; |
533 | + long getUniqueID(); |
534 | |
535 | /** @return The table ID this status is for */ |
536 | int getTableID(); |
537 | |
538 | === modified file 'src/main/java/com/akiban/server/manage/ManageMXBean.java' |
539 | --- src/main/java/com/akiban/server/manage/ManageMXBean.java 2013-03-22 20:05:57 +0000 |
540 | +++ src/main/java/com/akiban/server/manage/ManageMXBean.java 2013-05-20 14:47:34 +0000 |
541 | @@ -25,15 +25,9 @@ |
542 | |
543 | int getJmxPort(); |
544 | |
545 | - boolean isDeferIndexesEnabled(); |
546 | - |
547 | - void setDeferIndexes(final boolean defer); |
548 | - |
549 | void buildIndexes(final String arg, final boolean deferIndexes); |
550 | |
551 | void deleteIndexes(final String arg); |
552 | |
553 | - void flushIndexes(); |
554 | - |
555 | String getVersionString(); |
556 | } |
557 | |
558 | === modified file 'src/main/java/com/akiban/server/manage/ManageMXBeanImpl.java' |
559 | --- src/main/java/com/akiban/server/manage/ManageMXBeanImpl.java 2013-03-22 20:05:57 +0000 |
560 | +++ src/main/java/com/akiban/server/manage/ManageMXBeanImpl.java 2013-05-20 14:47:34 +0000 |
561 | @@ -52,16 +52,6 @@ |
562 | } |
563 | |
564 | @Override |
565 | - public boolean isDeferIndexesEnabled() { |
566 | - return getStore().isDeferIndexes(); |
567 | - } |
568 | - |
569 | - @Override |
570 | - public void setDeferIndexes(final boolean defer) { |
571 | - getStore().setDeferIndexes(defer); |
572 | - } |
573 | - |
574 | - @Override |
575 | public void buildIndexes(final String arg, final boolean deferIndexes) { |
576 | Session session = createSession(); |
577 | try { |
578 | @@ -88,18 +78,6 @@ |
579 | } |
580 | |
581 | @Override |
582 | - public void flushIndexes() { |
583 | - Session session = createSession(); |
584 | - try { |
585 | - getStore().flushIndexes(session); |
586 | - } catch(Exception t) { |
587 | - throw new RuntimeException(t); |
588 | - } finally { |
589 | - session.close(); |
590 | - } |
591 | - } |
592 | - |
593 | - @Override |
594 | public String getVersionString() { |
595 | return AkServer.VERSION_STRING; |
596 | } |
597 | |
598 | === modified file 'src/main/java/com/akiban/server/service/dxl/BasicDDLFunctions.java' |
599 | --- src/main/java/com/akiban/server/service/dxl/BasicDDLFunctions.java 2013-04-22 02:00:55 +0000 |
600 | +++ src/main/java/com/akiban/server/service/dxl/BasicDDLFunctions.java 2013-05-20 14:47:34 +0000 |
601 | @@ -1161,7 +1161,7 @@ |
602 | if (expected != actual) { |
603 | PersistitStore pStore = this.store().getPersistitStore(); |
604 | if (index.isTableIndex()) { |
605 | - pStore.getTableStatus(((TableIndex) index).getTable()).setRowCount(actual); |
606 | + index.leafMostTable().rowDef().getTableStatus().setRowCount(actual); |
607 | } |
608 | else { |
609 | final Exchange ex = pStore.getExchange(session, index); |
610 | |
611 | === modified file 'src/main/java/com/akiban/server/service/dxl/BasicDMLFunctions.java' |
612 | --- src/main/java/com/akiban/server/service/dxl/BasicDMLFunctions.java 2013-03-22 20:05:57 +0000 |
613 | +++ src/main/java/com/akiban/server/service/dxl/BasicDMLFunctions.java 2013-05-20 14:47:34 +0000 |
614 | @@ -581,22 +581,14 @@ |
615 | { |
616 | logger.trace("writing a row"); |
617 | final RowData rowData = niceRowToRowData(row); |
618 | - try { |
619 | - store().writeRow(session, rowData); |
620 | - } catch (PersistitException ex) { |
621 | - throw new PersistitAdapterException(ex); |
622 | - } |
623 | + store().writeRow(session, rowData); |
624 | } |
625 | |
626 | @Override |
627 | public void writeRows(Session session, List<RowData> rows) { |
628 | logger.trace("writing {} rows", rows.size()); |
629 | - try { |
630 | - for(RowData rowData : rows) { |
631 | - store().writeRow(session, rowData); |
632 | - } |
633 | - } catch (PersistitException ex) { |
634 | - throw new PersistitAdapterException(ex); |
635 | + for(RowData rowData : rows) { |
636 | + store().writeRow(session, rowData); |
637 | } |
638 | } |
639 | |
640 | @@ -605,11 +597,7 @@ |
641 | { |
642 | logger.trace("deleting a row (cascade: {})", cascadeDelete); |
643 | final RowData rowData = niceRowToRowData(row); |
644 | - try { |
645 | - store().deleteRow(session, rowData, true, cascadeDelete); |
646 | - } catch (PersistitException ex) { |
647 | - throw new PersistitAdapterException(ex); |
648 | - } |
649 | + store().deleteRow(session, rowData, true, cascadeDelete); |
650 | } |
651 | |
652 | private RowData niceRowToRowData(NewRow row) |
653 | @@ -636,12 +624,7 @@ |
654 | tableId |
655 | ); |
656 | |
657 | - try { |
658 | - store().updateRow(session, oldData, newData, columnSelector, null); |
659 | - } catch (PersistitException ex) { |
660 | - throw new PersistitAdapterException(ex); |
661 | - } |
662 | - |
663 | + store().updateRow(session, oldData, newData, columnSelector, null); |
664 | } |
665 | |
666 | private void checkForModifiedCursors( |
667 | @@ -749,12 +732,7 @@ |
668 | final UserTable utable = table.isUserTable() ? (UserTable)table : null; |
669 | |
670 | if(utable == null || canFastTruncate(session, utable)) { |
671 | - try { |
672 | - store().truncateGroup(session, table.getGroup()); |
673 | - } catch (PersistitException ex) { |
674 | - throw new PersistitAdapterException(ex); |
675 | - } |
676 | - |
677 | + store().truncateGroup(session, table.getGroup()); |
678 | return; |
679 | } |
680 | |
681 | @@ -810,11 +788,7 @@ |
682 | thrown = e; |
683 | } |
684 | } |
685 | - try { |
686 | - store().truncateTableStatus(session, tableId); |
687 | - } catch (PersistitException ex) { |
688 | - throw new PersistitAdapterException(ex); |
689 | - } |
690 | + store().truncateTableStatus(session, tableId); |
691 | if (thrown != null) { |
692 | throw thrown; |
693 | } |
694 | |
695 | === added file 'src/main/java/com/akiban/server/store/AbstractStore.java' |
696 | --- src/main/java/com/akiban/server/store/AbstractStore.java 1970-01-01 00:00:00 +0000 |
697 | +++ src/main/java/com/akiban/server/store/AbstractStore.java 2013-05-20 14:47:34 +0000 |
698 | @@ -0,0 +1,487 @@ |
699 | +/** |
700 | + * Copyright (C) 2009-2013 Akiban Technologies, Inc. |
701 | + * |
702 | + * This program is free software: you can redistribute it and/or modify |
703 | + * it under the terms of the GNU Affero General Public License as published by |
704 | + * the Free Software Foundation, either version 3 of the License, or |
705 | + * (at your option) any later version. |
706 | + * |
707 | + * This program is distributed in the hope that it will be useful, |
708 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
709 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
710 | + * GNU Affero General Public License for more details. |
711 | + * |
712 | + * You should have received a copy of the GNU Affero General Public License |
713 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
714 | + */ |
715 | + |
716 | +package com.akiban.server.store; |
717 | + |
718 | +import com.akiban.ais.model.Group; |
719 | +import com.akiban.ais.model.Index; |
720 | +import com.akiban.ais.model.NopVisitor; |
721 | +import com.akiban.ais.model.Table; |
722 | +import com.akiban.ais.model.TableName; |
723 | +import com.akiban.ais.model.UserTable; |
724 | +import com.akiban.qp.persistitadapter.OperatorBasedRowCollector; |
725 | +import com.akiban.server.TableStatistics; |
726 | +import com.akiban.server.TableStatus; |
727 | +import com.akiban.server.api.dml.ColumnSelector; |
728 | +import com.akiban.server.api.dml.scan.ScanLimit; |
729 | +import com.akiban.server.error.CursorCloseBadException; |
730 | +import com.akiban.server.error.CursorIsUnknownException; |
731 | +import com.akiban.server.error.NoSuchTableException; |
732 | +import com.akiban.server.error.RowDefNotFoundException; |
733 | +import com.akiban.server.rowdata.IndexDef; |
734 | +import com.akiban.server.rowdata.RowData; |
735 | +import com.akiban.server.rowdata.RowDef; |
736 | +import com.akiban.server.service.session.Session; |
737 | +import com.akiban.server.service.tree.TreeLink; |
738 | +import com.akiban.server.store.statistics.Histogram; |
739 | +import com.akiban.server.store.statistics.HistogramEntry; |
740 | +import com.akiban.server.store.statistics.IndexStatistics; |
741 | +import com.akiban.server.store.statistics.IndexStatisticsService; |
742 | +import com.akiban.util.tap.InOutTap; |
743 | +import com.akiban.util.tap.Tap; |
744 | +import com.persistit.Key; |
745 | +import org.slf4j.Logger; |
746 | +import org.slf4j.LoggerFactory; |
747 | + |
748 | +import java.util.ArrayList; |
749 | +import java.util.Arrays; |
750 | +import java.util.BitSet; |
751 | +import java.util.Collection; |
752 | +import java.util.Collections; |
753 | +import java.util.List; |
754 | + |
755 | +public abstract class AbstractStore implements Store { |
756 | + private static final Logger LOG = LoggerFactory.getLogger(AbstractStore.class.getName()); |
757 | + private static final InOutTap NEW_COLLECTOR_TAP = Tap.createTimer("read: new_collector"); |
758 | + private static final Session.MapKey<Integer,List<RowCollector>> COLLECTORS = Session.MapKey.mapNamed("collectors"); |
759 | + |
760 | + protected IndexStatisticsService indexStatisticsService; |
761 | + |
762 | + // |
763 | + // AbstractStore |
764 | + // |
765 | + |
766 | + protected RowDef rowDefFromExplicitOrId(Session session, RowData rowData) { |
767 | + RowDef rowDef = rowData.getExplicitRowDef(); |
768 | + if(rowDef == null) { |
769 | + rowDef = getRowDef(session, rowData.getRowDefId()); |
770 | + } |
771 | + return rowDef; |
772 | + } |
773 | + |
774 | + protected boolean hasNullIndexSegments(RowData rowData, Index index) |
775 | + { |
776 | + IndexDef indexDef = index.indexDef(); |
777 | + assert indexDef.getRowDef().getRowDefId() == rowData.getRowDefId(); |
778 | + for (int i : indexDef.getFields()) { |
779 | + if (rowData.isNull(i)) { |
780 | + return true; |
781 | + } |
782 | + } |
783 | + return false; |
784 | + } |
785 | + |
786 | + /** Convert from new-format histogram to old for adapter. */ |
787 | + protected TableStatistics.Histogram indexStatisticsToHistogram(Session session, Index index, Key key) { |
788 | + IndexStatistics stats = indexStatisticsService.getIndexStatistics(session, index); |
789 | + if (stats == null) { |
790 | + return null; |
791 | + } |
792 | + Histogram fromHistogram = stats.getHistogram(0, index.getKeyColumns().size()); |
793 | + if (fromHistogram == null) { |
794 | + return null; |
795 | + } |
796 | + IndexDef indexDef = index.indexDef(); |
797 | + RowDef indexRowDef = indexDef.getRowDef(); |
798 | + TableStatistics.Histogram toHistogram = new TableStatistics.Histogram(index.getIndexId()); |
799 | + RowData indexRowData = new RowData(new byte[4096]); |
800 | + Object[] indexValues = new Object[indexRowDef.getFieldCount()]; |
801 | + long count = 0; |
802 | + for (HistogramEntry entry : fromHistogram.getEntries()) { |
803 | + // Decode the key. |
804 | + int keylen = entry.getKeyBytes().length; |
805 | + System.arraycopy(entry.getKeyBytes(), 0, key.getEncodedBytes(), 0, keylen); |
806 | + key.setEncodedSize(keylen); |
807 | + key.indexTo(0); |
808 | + int depth = key.getDepth(); |
809 | + // Copy key fields to index row. |
810 | + for (int field : indexDef.getFields()) { |
811 | + if (--depth >= 0) { |
812 | + indexValues[field] = key.decode(); |
813 | + } else { |
814 | + indexValues[field] = null; |
815 | + } |
816 | + } |
817 | + indexRowData.createRow(indexRowDef, indexValues); |
818 | + // Partial counts to running total less than key. |
819 | + count += entry.getLessCount(); |
820 | + toHistogram.addSample(new TableStatistics.HistogramSample(indexRowData.copy(), count)); |
821 | + count += entry.getEqualCount(); |
822 | + } |
823 | + // Add final entry with all nulls. |
824 | + Arrays.fill(indexValues, null); |
825 | + indexRowData.createRow(indexRowDef, indexValues); |
826 | + toHistogram.addSample(new TableStatistics.HistogramSample(indexRowData.copy(), count)); |
827 | + return toHistogram; |
828 | + } |
829 | + |
830 | + protected static boolean bytesEqual(byte[] a, int aoffset, int asize, byte[] b, int boffset, int bsize) { |
831 | + if (asize != bsize) { |
832 | + return false; |
833 | + } |
834 | + for (int i = 0; i < asize; i++) { |
835 | + if (a[i + aoffset] != b[i + boffset]) { |
836 | + return false; |
837 | + } |
838 | + } |
839 | + return true; |
840 | + } |
841 | + |
842 | + protected static boolean fieldsEqual(RowDef rowDef, RowData a, RowData b, int[] fieldIndexes) |
843 | + { |
844 | + for (int fieldIndex : fieldIndexes) { |
845 | + long aloc = rowDef.fieldLocation(a, fieldIndex); |
846 | + long bloc = rowDef.fieldLocation(b, fieldIndex); |
847 | + if (!bytesEqual(a.getBytes(), (int) aloc, (int) (aloc >>> 32), |
848 | + b.getBytes(), (int) bloc, (int) (bloc >>> 32))) { |
849 | + return false; |
850 | + } |
851 | + } |
852 | + return true; |
853 | + } |
854 | + |
855 | + protected static boolean fieldEqual(RowDef rowDef, RowData a, RowData b, int fieldPosition) |
856 | + { |
857 | + long aloc = rowDef.fieldLocation(a, fieldPosition); |
858 | + long bloc = rowDef.fieldLocation(b, fieldPosition); |
859 | + return bytesEqual(a.getBytes(), (int) aloc, (int) (aloc >>> 32), |
860 | + b.getBytes(), (int) bloc, (int) (bloc >>> 32)); |
861 | + } |
862 | + |
863 | + protected BitSet analyzeFieldChanges(Session session, RowDef rowDef, RowData oldRow, RowData newRow) |
864 | + { |
865 | + BitSet tablesRequiringHKeyMaintenance; |
866 | + assert oldRow.getRowDefId() == newRow.getRowDefId(); |
867 | + int fields = rowDef.getFieldCount(); |
868 | + // Find the PK and FK fields |
869 | + BitSet keyField = new BitSet(fields); |
870 | + for (int pkFieldPosition : rowDef.getPKIndex().indexDef().getFields()) { |
871 | + keyField.set(pkFieldPosition, true); |
872 | + } |
873 | + for (int fkFieldPosition : rowDef.getParentJoinFields()) { |
874 | + keyField.set(fkFieldPosition, true); |
875 | + } |
876 | + // Find whether and where key fields differ |
877 | + boolean allEqual = true; |
878 | + for (int keyFieldPosition = keyField.nextSetBit(0); |
879 | + allEqual && keyFieldPosition >= 0; |
880 | + keyFieldPosition = keyField.nextSetBit(keyFieldPosition + 1)) { |
881 | + boolean fieldEqual = fieldEqual(rowDef, oldRow, newRow, keyFieldPosition); |
882 | + if (!fieldEqual) { |
883 | + allEqual = false; |
884 | + } |
885 | + } |
886 | + if (allEqual) { |
887 | + tablesRequiringHKeyMaintenance = null; |
888 | + } else { |
889 | + // A PK or FK field has changed, so the update has to be done as delete/insert. To minimize hkey |
890 | + // propagation work, find which tables (descendents of the updated table) are affected by hkey |
891 | + // changes. |
892 | + tablesRequiringHKeyMaintenance = hKeyDependentTableOrdinals(session, oldRow.getRowDefId()); |
893 | + } |
894 | + return tablesRequiringHKeyMaintenance; |
895 | + } |
896 | + |
897 | + private BitSet hKeyDependentTableOrdinals(Session session, int rowDefId) |
898 | + { |
899 | + RowDef rowDef = getRowDef(session, rowDefId); |
900 | + UserTable table = rowDef.userTable(); |
901 | + BitSet ordinals = new BitSet(); |
902 | + for (UserTable hKeyDependentTable : table.hKeyDependentTables()) { |
903 | + int ordinal = hKeyDependentTable.rowDef().getOrdinal(); |
904 | + ordinals.set(ordinal, true); |
905 | + } |
906 | + return ordinals; |
907 | + } |
908 | + |
909 | + |
910 | + // |
911 | + // Store methods |
912 | + // |
913 | + |
914 | + @Override |
915 | + public RowDef getRowDef(Session session, int rowDefID) { |
916 | + Table table = getAIS(session).getUserTable(rowDefID); |
917 | + if(table == null) { |
918 | + throw new RowDefNotFoundException(rowDefID); |
919 | + } |
920 | + return table.rowDef(); |
921 | + } |
922 | + |
923 | + @Override |
924 | + public RowDef getRowDef(Session session, TableName tableName) { |
925 | + Table table = getAIS(session).getTable(tableName); |
926 | + if(table == null) { |
927 | + throw new NoSuchTableException(tableName); |
928 | + } |
929 | + return table.rowDef(); |
930 | + } |
931 | + |
932 | + @Override |
933 | + public RowCollector newRowCollector(Session session, |
934 | + int scanFlags, |
935 | + int rowDefId, |
936 | + int indexId, |
937 | + byte[] columnBitMap, |
938 | + RowData start, |
939 | + ColumnSelector startColumns, |
940 | + RowData end, |
941 | + ColumnSelector endColumns, |
942 | + ScanLimit scanLimit) |
943 | + { |
944 | + NEW_COLLECTOR_TAP.in(); |
945 | + RowCollector rc; |
946 | + try { |
947 | + if(start != null && startColumns == null) { |
948 | + startColumns = createNonNullFieldSelector(start); |
949 | + } |
950 | + if(end != null && endColumns == null) { |
951 | + endColumns = createNonNullFieldSelector(end); |
952 | + } |
953 | + RowDef rowDef = checkRequest(session, rowDefId, start, startColumns, end, endColumns); |
954 | + rc = OperatorBasedRowCollector.newCollector(session, |
955 | + this, |
956 | + scanFlags, |
957 | + rowDef, |
958 | + indexId, |
959 | + columnBitMap, |
960 | + start, |
961 | + startColumns, |
962 | + end, |
963 | + endColumns, |
964 | + scanLimit); |
965 | + } finally { |
966 | + NEW_COLLECTOR_TAP.out(); |
967 | + } |
968 | + return rc; |
969 | + } |
970 | + |
971 | + @Override |
972 | + public void addSavedRowCollector(final Session session, |
973 | + final RowCollector rc) { |
974 | + final Integer tableId = rc.getTableId(); |
975 | + final List<RowCollector> list = collectorsForTableId(session, tableId); |
976 | + if (!list.isEmpty()) { |
977 | + LOG.debug("Note: Nested RowCollector on tableId={} depth={}", tableId, list.size() + 1); |
978 | + assert list.get(list.size() - 1) != rc : "Redundant call"; |
979 | + // |
980 | + // This disallows the patch because we agreed not to fix the |
981 | + // bug. However, these changes fix a memory leak, which is |
982 | + // important for robustness. |
983 | + // |
984 | + // throw new StoreException(122, "Bug 255 workaround is disabled"); |
985 | + } |
986 | + list.add(rc); |
987 | + } |
988 | + |
989 | + @Override |
990 | + public RowCollector getSavedRowCollector(final Session session, |
991 | + final int tableId) throws CursorIsUnknownException { |
992 | + final List<RowCollector> list = collectorsForTableId(session, tableId); |
993 | + if (list.isEmpty()) { |
994 | + LOG.debug("Nested RowCollector on tableId={} depth={}", tableId, (list.size() + 1)); |
995 | + throw new CursorIsUnknownException(tableId); |
996 | + } |
997 | + return list.get(list.size() - 1); |
998 | + } |
999 | + |
1000 | + @Override |
1001 | + public void removeSavedRowCollector(final Session session, |
1002 | + final RowCollector rc) throws CursorIsUnknownException { |
1003 | + final Integer tableId = rc.getTableId(); |
1004 | + final List<RowCollector> list = collectorsForTableId(session, tableId); |
1005 | + if (list.isEmpty()) { |
1006 | + throw new CursorIsUnknownException (tableId); |
1007 | + } |
1008 | + final RowCollector removed = list.remove(list.size() - 1); |
1009 | + if (removed != rc) { |
1010 | + throw new CursorCloseBadException(tableId); |
1011 | + } |
1012 | + } |
1013 | + |
1014 | + // This is to avoid circular dependencies in Guicer. |
1015 | + // TODO: There is still a functional circularity: store needs |
1016 | + // stats to clear them when deleting a group; stats need store to |
1017 | + // persist the stats. It would be better to separate out the |
1018 | + // higher level store functions from what other services require. |
1019 | + @Override |
1020 | + public void setIndexStatistics(IndexStatisticsService indexStatisticsService) { |
1021 | + this.indexStatisticsService = indexStatisticsService; |
1022 | + } |
1023 | + |
1024 | + @Override |
1025 | + public TableStatistics getTableStatistics(final Session session, int tableId) { |
1026 | + final RowDef rowDef = getRowDef(session, tableId); |
1027 | + final TableStatistics ts = new TableStatistics(tableId); |
1028 | + final TableStatus status = rowDef.getTableStatus(); |
1029 | + ts.setAutoIncrementValue(status.getAutoIncrement()); |
1030 | + ts.setRowCount(status.getRowCount()); |
1031 | + // TODO - get correct values |
1032 | + ts.setMeanRecordLength(100); |
1033 | + ts.setBlockSize(8192); |
1034 | + for(Index index : rowDef.getIndexes()) { |
1035 | + if(index.isSpatial()) { |
1036 | + continue; |
1037 | + } |
1038 | + TableStatistics.Histogram histogram = indexStatisticsToHistogram(session, index, createKey()); |
1039 | + if(histogram != null) { |
1040 | + ts.addHistogram(histogram); |
1041 | + } |
1042 | + } |
1043 | + return ts; |
1044 | + } |
1045 | + |
1046 | + @Override |
1047 | + public long getRowCount(Session session, boolean exact, RowData start, RowData end, byte[] columnBitMap) { |
1048 | + // TODO: Compute a reasonable value. The value 2 is special because it is not 0 or 1 but will |
1049 | + // still induce MySQL to use an index rather than a full table scan. |
1050 | + return 2; |
1051 | + } |
1052 | + |
1053 | + @Override |
1054 | + public void dropGroup(final Session session, Group group) { |
1055 | + group.getRoot().traverseTableAndDescendants(new NopVisitor() { |
1056 | + @Override |
1057 | + public void visitUserTable(UserTable table) { |
1058 | + removeTrees(session, table); |
1059 | + } |
1060 | + }); |
1061 | + } |
1062 | + |
1063 | + @Override |
1064 | + public void truncateGroup(final Session session, final Group group) { |
1065 | + final List<Index> indexes = new ArrayList<>(); |
1066 | + // Collect indexes, truncate table statuses |
1067 | + group.getRoot().traverseTableAndDescendants(new NopVisitor() { |
1068 | + @Override |
1069 | + public void visitUserTable(UserTable table) { |
1070 | + indexes.addAll(table.getIndexesIncludingInternal()); |
1071 | + table.rowDef().getTableStatus().truncate(); |
1072 | + } |
1073 | + }); |
1074 | + |
1075 | + indexes.addAll(group.getIndexes()); |
1076 | + truncateIndexes(session, indexes); |
1077 | + |
1078 | + // Truncate the group tree |
1079 | + truncateTree(session, group); |
1080 | + } |
1081 | + |
1082 | + @Override |
1083 | + public void truncateTableStatus(final Session session, final int rowDefId) { |
1084 | + getRowDef(session, rowDefId).getTableStatus().truncate(); |
1085 | + } |
1086 | + |
1087 | + @Override |
1088 | + public void truncateIndexes(Session session, Collection<? extends Index> indexes) { |
1089 | + for(Index index : indexes) { |
1090 | + truncateTree(session, index.indexDef()); |
1091 | + } |
1092 | + // Delete any statistics associated with index. |
1093 | + indexStatisticsService.deleteIndexStatistics(session, indexes); |
1094 | + } |
1095 | + |
1096 | + @Override |
1097 | + public void deleteIndexes(final Session session, final Collection<? extends Index> indexes) { |
1098 | + for(Index index : indexes) { |
1099 | + final IndexDef indexDef = index.indexDef(); |
1100 | + if(indexDef != null) { |
1101 | + removeTree(session, indexDef); |
1102 | + } |
1103 | + } |
1104 | + indexStatisticsService.deleteIndexStatistics(session, indexes); |
1105 | + } |
1106 | + |
1107 | + @Override |
1108 | + public void removeTrees(Session session, UserTable table) { |
1109 | + // Table indexes |
1110 | + for(Index index : table.getIndexesIncludingInternal()) { |
1111 | + removeTree(session, index.indexDef()); |
1112 | + } |
1113 | + indexStatisticsService.deleteIndexStatistics(session, table.getIndexesIncludingInternal()); |
1114 | + |
1115 | + // Group indexes |
1116 | + for(Index index : table.getGroupIndexes()) { |
1117 | + removeTree(session, index.indexDef()); |
1118 | + } |
1119 | + indexStatisticsService.deleteIndexStatistics(session, table.getGroupIndexes()); |
1120 | + |
1121 | + // Sequence |
1122 | + if(table.getIdentityColumn() != null) { |
1123 | + deleteSequences(session, Collections.singleton(table.getIdentityColumn().getIdentityGenerator())); |
1124 | + } |
1125 | + |
1126 | + // And the group tree |
1127 | + removeTree(session, table.getGroup()); |
1128 | + } |
1129 | + |
1130 | + @Override |
1131 | + public void removeTrees(Session session, Collection<? extends TreeLink> treeLinks) { |
1132 | + for(TreeLink link : treeLinks) { |
1133 | + removeTree(session, link); |
1134 | + } |
1135 | + } |
1136 | + |
1137 | + |
1138 | + // |
1139 | + // Internal |
1140 | + // |
1141 | + |
1142 | + private List<RowCollector> collectorsForTableId(final Session session, final int tableId) { |
1143 | + List<RowCollector> list = session.get(COLLECTORS, tableId); |
1144 | + if (list == null) { |
1145 | + list = new ArrayList<>(); |
1146 | + session.put(COLLECTORS, tableId, list); |
1147 | + } |
1148 | + return list; |
1149 | + } |
1150 | + |
1151 | + private RowDef checkRequest(Session session, int rowDefId, RowData start, ColumnSelector startColumns, |
1152 | + RowData end, ColumnSelector endColumns) throws IllegalArgumentException { |
1153 | + if (start != null) { |
1154 | + if (startColumns == null) { |
1155 | + throw new IllegalArgumentException("non-null start row requires non-null ColumnSelector"); |
1156 | + } |
1157 | + if( start.getRowDefId() != rowDefId) { |
1158 | + throw new IllegalArgumentException("Start and end RowData must specify the same rowDefId"); |
1159 | + } |
1160 | + } |
1161 | + if (end != null) { |
1162 | + if (endColumns == null) { |
1163 | + throw new IllegalArgumentException("non-null end row requires non-null ColumnSelector"); |
1164 | + } |
1165 | + if (end.getRowDefId() != rowDefId) { |
1166 | + throw new IllegalArgumentException("Start and end RowData must specify the same rowDefId"); |
1167 | + } |
1168 | + } |
1169 | + final RowDef rowDef = getRowDef(session, rowDefId); |
1170 | + if (rowDef == null) { |
1171 | + throw new IllegalArgumentException("No RowDef for rowDefId " + rowDefId); |
1172 | + } |
1173 | + return rowDef; |
1174 | + } |
1175 | + |
1176 | + private static ColumnSelector createNonNullFieldSelector(final RowData rowData) { |
1177 | + assert rowData != null; |
1178 | + return new ColumnSelector() { |
1179 | + @Override |
1180 | + public boolean includesColumn(int columnPosition) { |
1181 | + return !rowData.isNull(columnPosition); |
1182 | + } |
1183 | + }; |
1184 | + } |
1185 | +} |
1186 | |
1187 | === modified file 'src/main/java/com/akiban/server/store/DelegatingStore.java' |
1188 | --- src/main/java/com/akiban/server/store/DelegatingStore.java 2013-03-22 20:05:57 +0000 |
1189 | +++ src/main/java/com/akiban/server/store/DelegatingStore.java 2013-05-20 14:47:34 +0000 |
1190 | @@ -17,10 +17,14 @@ |
1191 | |
1192 | package com.akiban.server.store; |
1193 | |
1194 | +import com.akiban.ais.model.AkibanInformationSchema; |
1195 | import com.akiban.ais.model.Group; |
1196 | import com.akiban.ais.model.Index; |
1197 | import com.akiban.ais.model.Sequence; |
1198 | -import com.akiban.ais.model.Table; |
1199 | +import com.akiban.ais.model.TableName; |
1200 | +import com.akiban.ais.model.UserTable; |
1201 | +import com.akiban.qp.operator.StoreAdapter; |
1202 | +import com.akiban.qp.rowtype.Schema; |
1203 | import com.akiban.server.rowdata.RowData; |
1204 | import com.akiban.server.rowdata.RowDef; |
1205 | import com.akiban.server.TableStatistics; |
1206 | @@ -30,7 +34,8 @@ |
1207 | import com.akiban.server.service.Service; |
1208 | import com.akiban.server.service.session.Session; |
1209 | import com.akiban.server.service.tree.TreeLink; |
1210 | -import com.persistit.exception.PersistitException; |
1211 | +import com.akiban.server.store.statistics.IndexStatisticsService; |
1212 | +import com.persistit.Key; |
1213 | |
1214 | import java.util.Collection; |
1215 | |
1216 | @@ -42,7 +47,8 @@ |
1217 | this.delegate = delegate; |
1218 | } |
1219 | |
1220 | - protected S getDelegate() { |
1221 | + // TODO: Ditch DelegatingStore altogether |
1222 | + public S getDelegate() { |
1223 | return delegate; |
1224 | } |
1225 | |
1226 | @@ -62,11 +68,22 @@ |
1227 | delegate.crash(); |
1228 | } |
1229 | |
1230 | + @Override |
1231 | + public AkibanInformationSchema getAIS(Session session) { |
1232 | + return delegate.getAIS(session); |
1233 | + } |
1234 | + |
1235 | + @Override |
1236 | public RowDef getRowDef(Session session, int rowDefID) { |
1237 | return delegate.getRowDef(session, rowDefID); |
1238 | } |
1239 | |
1240 | @Override |
1241 | + public RowDef getRowDef(Session session, TableName tableName) { |
1242 | + return delegate.getRowDef(session, tableName); |
1243 | + } |
1244 | + |
1245 | + @Override |
1246 | public void startBulkLoad(Session session) { |
1247 | delegate.startBulkLoad(session); |
1248 | } |
1249 | @@ -81,15 +98,15 @@ |
1250 | delegate.finishBulkLoad(session); |
1251 | } |
1252 | |
1253 | - public void writeRow(Session session, RowData rowData) throws PersistitException { |
1254 | + public void writeRow(Session session, RowData rowData) { |
1255 | delegate.writeRow(session, rowData); |
1256 | } |
1257 | |
1258 | - public void deleteRow(Session session, RowData rowData, boolean deleteIndexes, boolean cascadeDelete) throws PersistitException { |
1259 | + public void deleteRow(Session session, RowData rowData, boolean deleteIndexes, boolean cascadeDelete) { |
1260 | delegate.deleteRow(session, rowData, deleteIndexes, cascadeDelete); |
1261 | } |
1262 | |
1263 | - public void updateRow(Session session, RowData oldRowData, RowData newRowData, ColumnSelector columnSelector, Index[] indexes) throws PersistitException { |
1264 | + public void updateRow(Session session, RowData oldRowData, RowData newRowData, ColumnSelector columnSelector, Index[] indexes) { |
1265 | delegate.updateRow(session, oldRowData, newRowData, columnSelector, indexes); |
1266 | } |
1267 | |
1268 | @@ -97,11 +114,11 @@ |
1269 | delegate.dropGroup(session, group); |
1270 | } |
1271 | |
1272 | - public void truncateGroup(Session session, Group group) throws PersistitException { |
1273 | + public void truncateGroup(Session session, Group group) { |
1274 | delegate.truncateGroup(session, group); |
1275 | } |
1276 | |
1277 | - public void truncateTableStatus(Session session, int rowDefId) throws PersistitException { |
1278 | + public void truncateTableStatus(Session session, int rowDefId) { |
1279 | delegate.truncateTableStatus(session, rowDefId); |
1280 | } |
1281 | |
1282 | @@ -117,11 +134,6 @@ |
1283 | delegate.removeSavedRowCollector(session, rc); |
1284 | } |
1285 | |
1286 | - @SuppressWarnings("deprecation") |
1287 | - public RowCollector newRowCollector(Session session, int rowDefId, int indexId, int scanFlags, RowData start, RowData end, byte[] columnBitMap, ScanLimit scanLimit) { |
1288 | - return delegate.newRowCollector(session, rowDefId, indexId, scanFlags, start, end, columnBitMap, scanLimit); |
1289 | - } |
1290 | - |
1291 | public RowCollector newRowCollector(Session session, int scanFlags, int rowDefId, int indexId, byte[] columnBitMap, RowData start, ColumnSelector startColumns, RowData end, ColumnSelector endColumns, ScanLimit scanLimit) { |
1292 | return delegate.newRowCollector(session, scanFlags, rowDefId, indexId, columnBitMap, start, startColumns, end, endColumns, scanLimit); |
1293 | } |
1294 | @@ -134,10 +146,6 @@ |
1295 | return delegate.getTableStatistics(session, tableId); |
1296 | } |
1297 | |
1298 | - public void flushIndexes(Session session) { |
1299 | - delegate.flushIndexes(session); |
1300 | - } |
1301 | - |
1302 | public void buildIndexes(Session session, Collection<? extends Index> indexes, boolean defer) { |
1303 | delegate.buildIndexes(session, indexes, defer); |
1304 | } |
1305 | @@ -146,22 +154,11 @@ |
1306 | delegate.deleteIndexes(session, indexes); |
1307 | } |
1308 | |
1309 | - public void deleteSequences (Session session, Collection<? extends Sequence> sequences) { |
1310 | - delegate.deleteSequences(session, sequences); |
1311 | - } |
1312 | - |
1313 | - public void removeTrees(Session session, Table table) { |
1314 | + @Override |
1315 | + public void removeTrees(Session session, UserTable table) { |
1316 | delegate.removeTrees(session, table); |
1317 | } |
1318 | |
1319 | - public boolean isDeferIndexes() { |
1320 | - return delegate.isDeferIndexes(); |
1321 | - } |
1322 | - |
1323 | - public void setDeferIndexes(boolean defer) { |
1324 | - delegate.setDeferIndexes(defer); |
1325 | - } |
1326 | - |
1327 | @Override |
1328 | public void truncateIndexes(Session session, Collection<? extends Index> indexes) { |
1329 | delegate.truncateIndexes(session, indexes); |
1330 | @@ -171,4 +168,34 @@ |
1331 | public void removeTrees(Session session, Collection<? extends TreeLink> treeLinks) { |
1332 | delegate.removeTrees(session, treeLinks); |
1333 | } |
1334 | + |
1335 | + @Override |
1336 | + public StoreAdapter createAdapter(Session session, Schema schema) { |
1337 | + return delegate.createAdapter(session, schema); |
1338 | + } |
1339 | + |
1340 | + @Override |
1341 | + public void setIndexStatistics(IndexStatisticsService indexStatistics) { |
1342 | + delegate.setIndexStatistics(indexStatistics); |
1343 | + } |
1344 | + |
1345 | + @Override |
1346 | + public void truncateTree(Session session, TreeLink treeLink) { |
1347 | + delegate.truncateTree(session, treeLink); |
1348 | + } |
1349 | + |
1350 | + @Override |
1351 | + public Key createKey() { |
1352 | + return delegate.createKey(); |
1353 | + } |
1354 | + |
1355 | + @Override |
1356 | + public void deleteSequences(Session session, Collection<? extends Sequence> sequences) { |
1357 | + delegate.deleteSequences(session, sequences); |
1358 | + } |
1359 | + |
1360 | + @Override |
1361 | + public void removeTree(Session session, TreeLink treeLink) { |
1362 | + delegate.removeTree(session, treeLink); |
1363 | + } |
1364 | } |
1365 | |
1366 | === modified file 'src/main/java/com/akiban/server/store/PersistitStore.java' |
1367 | --- src/main/java/com/akiban/server/store/PersistitStore.java 2013-05-03 00:59:49 +0000 |
1368 | +++ src/main/java/com/akiban/server/store/PersistitStore.java 2013-05-20 14:47:34 +0000 |
1369 | @@ -20,19 +20,18 @@ |
1370 | import com.akiban.ais.model.*; |
1371 | import com.akiban.ais.model.Index.IndexType; |
1372 | import com.akiban.qp.operator.StoreAdapter; |
1373 | -import com.akiban.qp.persistitadapter.OperatorBasedRowCollector; |
1374 | import com.akiban.qp.persistitadapter.PersistitAdapter; |
1375 | import com.akiban.qp.persistitadapter.PersistitHKey; |
1376 | import com.akiban.qp.persistitadapter.indexrow.PersistitIndexRow; |
1377 | import com.akiban.qp.persistitadapter.indexrow.PersistitIndexRowBuffer; |
1378 | import com.akiban.qp.rowtype.IndexRowType; |
1379 | +import com.akiban.qp.rowtype.Schema; |
1380 | import com.akiban.qp.util.SchemaCache; |
1381 | import com.akiban.server.*; |
1382 | import com.akiban.server.api.dml.ColumnSelector; |
1383 | import com.akiban.server.api.dml.scan.LegacyRowWrapper; |
1384 | import com.akiban.server.api.dml.scan.NewRow; |
1385 | import com.akiban.server.api.dml.scan.NiceRow; |
1386 | -import com.akiban.server.api.dml.scan.ScanLimit; |
1387 | import com.akiban.server.collation.CString; |
1388 | import com.akiban.server.collation.CStringKeyCoder; |
1389 | import com.akiban.server.error.*; |
1390 | @@ -46,10 +45,6 @@ |
1391 | import com.akiban.server.service.transaction.TransactionService; |
1392 | import com.akiban.server.service.tree.TreeLink; |
1393 | import com.akiban.server.service.tree.TreeService; |
1394 | -import com.akiban.server.store.statistics.Histogram; |
1395 | -import com.akiban.server.store.statistics.HistogramEntry; |
1396 | -import com.akiban.server.store.statistics.IndexStatistics; |
1397 | -import com.akiban.server.store.statistics.IndexStatisticsService; |
1398 | import com.akiban.util.tap.InOutTap; |
1399 | import com.akiban.util.tap.PointTap; |
1400 | import com.akiban.util.tap.Tap; |
1401 | @@ -69,9 +64,8 @@ |
1402 | import java.util.concurrent.atomic.AtomicLong; |
1403 | import java.util.concurrent.atomic.AtomicReference; |
1404 | |
1405 | -public class PersistitStore implements Store, Service { |
1406 | - |
1407 | - private static final Session.MapKey<Integer, List<RowCollector>> COLLECTORS = Session.MapKey.mapNamed("collectors"); |
1408 | +public class PersistitStore extends AbstractStore implements Service |
1409 | +{ |
1410 | private static final AtomicReference<Bulkload> activeBulkload = new AtomicReference<>(); |
1411 | |
1412 | private static final Logger LOG = LoggerFactory |
1413 | @@ -85,8 +79,6 @@ |
1414 | |
1415 | private static final InOutTap TABLE_INDEX_MAINTENANCE_TAP = Tap.createTimer("index: maintain_table"); |
1416 | |
1417 | - private static final InOutTap NEW_COLLECTOR_TAP = Tap.createTimer("read: new_collector"); |
1418 | - |
1419 | // an InOutTap would be nice, but pre-propagateDownGroup optimization, propagateDownGroup was called recursively |
1420 | // (via writeRow). PointTap handles this correctly, InOutTap does not, currently. |
1421 | private static final PointTap PROPAGATE_HKEY_CHANGE_TAP = Tap.createCount("write: propagate_hkey_change"); |
1422 | @@ -102,10 +94,6 @@ |
1423 | |
1424 | private final static int MAX_ROW_SIZE = 5000000; |
1425 | |
1426 | - private final static int MAX_INDEX_TRANCHE_SIZE = 10 * 1024 * 1024; |
1427 | - |
1428 | - private final static int KEY_STATE_SIZE_OVERHEAD = 50; |
1429 | - |
1430 | private final static byte[] EMPTY_BYTE_ARRAY = new byte[0]; |
1431 | |
1432 | private boolean writeLockEnabled; |
1433 | @@ -126,12 +114,6 @@ |
1434 | |
1435 | private DisplayFilter originalDisplayFilter; |
1436 | |
1437 | - private volatile IndexStatisticsService indexStatistics; |
1438 | - |
1439 | - private final Map<Tree, SortedSet<KeyState>> deferredIndexKeys = new HashMap<>(); |
1440 | - |
1441 | - private int deferredIndexKeyLimit = MAX_INDEX_TRANCHE_SIZE; |
1442 | - |
1443 | private FullTextIndexService fullTextService; |
1444 | |
1445 | private RowDataValueCoder valueCoder; |
1446 | @@ -161,6 +143,12 @@ |
1447 | this.transactionService = transactionService; |
1448 | } |
1449 | |
1450 | + |
1451 | + // |
1452 | + // FullText change tracking |
1453 | + // TODO: Move out of PersistitStore |
1454 | + // |
1455 | + |
1456 | public void setFullTextService(FullTextIndexService service) |
1457 | { |
1458 | fullTextService = service; |
1459 | @@ -579,14 +567,15 @@ |
1460 | } |
1461 | |
1462 | @Override |
1463 | + public Key createKey() { |
1464 | + return treeService.createKey(); |
1465 | + } |
1466 | + |
1467 | + @Override |
1468 | public PersistitStore getPersistitStore() { |
1469 | return this; |
1470 | } |
1471 | |
1472 | - public TreeService treeService() { |
1473 | - return treeService; |
1474 | - } |
1475 | - |
1476 | public Persistit getDb() { |
1477 | return treeService.getDb(); |
1478 | } |
1479 | @@ -603,11 +592,6 @@ |
1480 | return treeService.getExchange(session, index.indexDef()); |
1481 | } |
1482 | |
1483 | - public Key getKey() |
1484 | - { |
1485 | - return treeService.getKey(); |
1486 | - } |
1487 | - |
1488 | public void releaseExchange(final Session session, final Exchange exchange) { |
1489 | treeService.releaseExchange(session, exchange); |
1490 | } |
1491 | @@ -744,6 +728,7 @@ |
1492 | |
1493 | // --------------------- Implement Store interface -------------------- |
1494 | |
1495 | + @Override |
1496 | public AkibanInformationSchema getAIS(Session session) { |
1497 | Bulkload bulkload = activeBulkload.get(); |
1498 | if (bulkload != null) |
1499 | @@ -751,32 +736,18 @@ |
1500 | return schemaManager.getAis(session); |
1501 | } |
1502 | |
1503 | - public RowDef getRowDef(Session session, TableName tableName) { |
1504 | - Table table = getAIS(session).getTable(tableName); |
1505 | - if(table == null) { |
1506 | - throw new NoSuchTableException(tableName); |
1507 | - } |
1508 | - return table.rowDef(); |
1509 | - } |
1510 | - |
1511 | - @Override |
1512 | - public RowDef getRowDef(Session session, int rowDefID) { |
1513 | - Table table = getAIS(session).getUserTable(rowDefID); |
1514 | - if(table == null) { |
1515 | - throw new RowDefNotFoundException(rowDefID); |
1516 | - } |
1517 | - return table.rowDef(); |
1518 | - } |
1519 | - |
1520 | @Override |
1521 | public void writeRow(Session session, RowData rowData) |
1522 | - throws PersistitException |
1523 | { |
1524 | Bulkload bulkload = activeBulkload.get(); |
1525 | - if (bulkload != null) |
1526 | - writeRowBulk(session, rowData, bulkload); |
1527 | - else |
1528 | - writeRowStandard(session, rowData, null, true); |
1529 | + try { |
1530 | + if (bulkload != null) |
1531 | + writeRowBulk(session, rowData, bulkload); |
1532 | + else |
1533 | + writeRowStandard(session, rowData, null, true); |
1534 | + } catch(PersistitException e) { |
1535 | + throw PersistitAdapter.wrapPersistitException(session, e); |
1536 | + } |
1537 | } |
1538 | |
1539 | private void writeRowStandard(Session session, |
1540 | @@ -804,7 +775,7 @@ |
1541 | // in a good position to report a meaningful uniqueness violation, e.g. on the PK, since we don't have |
1542 | // the PK value handy. Instead, rely on PK validation when indexes are maintained. |
1543 | |
1544 | - packRowData(hEx, rowDef, rowData); |
1545 | + packRowData(hEx, rowData); |
1546 | // Store the h-row |
1547 | hEx.store(); |
1548 | if (rowDef.isAutoIncrement()) { |
1549 | @@ -824,7 +795,7 @@ |
1550 | // bug1112940: Bump row count *after* uniqueness checks in insertIntoIndex |
1551 | rowDef.getTableStatus().rowsWritten(1); |
1552 | |
1553 | - if (propagateHKeyChanges && hasChildren(rowDef.userTable())) { |
1554 | + if (propagateHKeyChanges && rowDef.userTable().hasChildren()) { |
1555 | // The row being inserted might be the parent of orphan rows |
1556 | // already present. The hkeys of these |
1557 | // orphan rows need to be maintained. The hkeys of interest |
1558 | @@ -860,17 +831,13 @@ |
1559 | } |
1560 | propagateDownGroup(session, hEx, tablesRequiringHKeyMaintenance, indexRow, true, false); |
1561 | } |
1562 | - |
1563 | - if (deferredIndexKeyLimit <= 0) { |
1564 | - putAllDeferredIndexKeys(session); |
1565 | - } |
1566 | } finally { |
1567 | WRITE_ROW_TAP.out(); |
1568 | releaseExchange(session, hEx); |
1569 | } |
1570 | } |
1571 | |
1572 | - private void writeRowBulk(Session session, RowData rowData, Bulkload bulkload) throws PersistitException { |
1573 | + private void writeRowBulk(Session session, RowData rowData, Bulkload bulkload) { |
1574 | final RowDef rowDef = writeRowCheck(session, rowData, true); |
1575 | if(session.get(StoreAdapter.STORE_ADAPTER_KEY) == null) { |
1576 | // Attaches itself to the session |
1577 | @@ -908,25 +875,27 @@ |
1578 | // Group table |
1579 | Key groupTableKey = bulkload.groupTableKey.get(); |
1580 | Value groupTableValue = bulkload.groupTableValue.get(); |
1581 | - constructHKey(session, groupTableKey, rowDef, rowData, true, hiddenPk); // invokes key.clear() |
1582 | - groupTableValue.clear(); |
1583 | - packRowData(groupTableValue, rowDef, rowData); |
1584 | try { |
1585 | + constructHKey(session, groupTableKey, rowDef, rowData, true, hiddenPk); // invokes key.clear() |
1586 | + groupTableValue.clear(); |
1587 | + packRowData(groupTableValue, rowData); |
1588 | Tree tree = treeService.populateTreeCache(rowDef.getGroup()).getTree(); |
1589 | bulkload.groupBuilder.treeBuilder.store(tree, groupTableKey, groupTableValue); |
1590 | + |
1591 | + PersistitIndexRowBuffer indexRow = new PersistitIndexRowBuffer(adapter(session)); |
1592 | + for (Index index : rowDef.getIndexes()) { |
1593 | + StorageAction action = index.isPrimaryKey() ? bulkload.pkStorage : bulkload.groupBuilder; |
1594 | + insertIntoIndex(session, index, rowData, groupTableKey, indexRow, deferIndexes, action); |
1595 | + } |
1596 | } catch (InvalidOperationException e) { |
1597 | throw e; |
1598 | + } catch (PersistitException e) { |
1599 | + throw PersistitAdapter.wrapPersistitException(session, e); |
1600 | } catch (Exception e) { |
1601 | LOG.error("while merging PKs", e); |
1602 | throw new BulkloadException("unknown exception (see log): " + e.getMessage()); |
1603 | } |
1604 | |
1605 | - PersistitIndexRowBuffer indexRow = new PersistitIndexRowBuffer(adapter(session)); |
1606 | - for (Index index : rowDef.getIndexes()) { |
1607 | - StorageAction action = index.isPrimaryKey() ? bulkload.pkStorage : bulkload.groupBuilder; |
1608 | - insertIntoIndex(session, index, rowData, groupTableKey, indexRow, deferIndexes, action); |
1609 | - } |
1610 | - |
1611 | insertedRowsCount.incrementAndGet(); |
1612 | } |
1613 | |
1614 | @@ -1030,18 +999,17 @@ |
1615 | } |
1616 | |
1617 | @Override |
1618 | - public void deleteRow(Session session, RowData rowData, boolean deleteIndexes, boolean cascadeDelete) throws PersistitException |
1619 | + public void deleteRow(Session session, RowData rowData, boolean deleteIndexes, boolean cascadeDelete) |
1620 | { |
1621 | deleteRow(session, rowData, deleteIndexes, cascadeDelete, null, true); |
1622 | } |
1623 | - |
1624 | - private void deleteRow(Session session, RowData rowData, boolean deleteIndexes, boolean cascadeDelete, |
1625 | + |
1626 | + private void deleteRow(Session session, RowData rowData, boolean deleteIndexes, boolean cascadeDelete, |
1627 | BitSet tablesRequiringHKeyMaintenance, boolean propagateHKeyChanges) |
1628 | - throws PersistitException |
1629 | { |
1630 | RowDef rowDef = writeCheck(session, rowData, false); |
1631 | Exchange hEx = null; |
1632 | - |
1633 | + |
1634 | DELETE_ROW_TAP.in(); |
1635 | try { |
1636 | hEx = getExchange(session, rowDef); |
1637 | @@ -1075,9 +1043,11 @@ |
1638 | // The row being deleted might be the parent of rows that |
1639 | // now become orphans. The hkeys |
1640 | // of these rows need to be maintained. |
1641 | - if(propagateHKeyChanges && hasChildren(rowDef.userTable())) { |
1642 | + if(propagateHKeyChanges && rowDef.userTable().hasChildren()) { |
1643 | propagateDownGroup(session, hEx, tablesRequiringHKeyMaintenance, indexRow, deleteIndexes, cascadeDelete); |
1644 | } |
1645 | + } catch(PersistitException e) { |
1646 | + throw PersistitAdapter.wrapPersistitException(session, e); |
1647 | } finally { |
1648 | DELETE_ROW_TAP.out(); |
1649 | releaseExchange(session, hEx); |
1650 | @@ -1090,7 +1060,6 @@ |
1651 | RowData newRowData, |
1652 | ColumnSelector columnSelector, |
1653 | Index[] indexes) |
1654 | - throws PersistitException |
1655 | { |
1656 | updateRow(session, oldRowData, newRowData, columnSelector, indexes, (indexes != null), true); |
1657 | } |
1658 | @@ -1102,7 +1071,6 @@ |
1659 | Index[] indexesToMaintain, |
1660 | boolean indexesAsInsert, |
1661 | boolean propagateHKeyChanges) |
1662 | - throws PersistitException |
1663 | { |
1664 | int rowDefId = oldRowData.getRowDefId(); |
1665 | if (newRowData.getRowDefId() != rowDefId) { |
1666 | @@ -1147,7 +1115,7 @@ |
1667 | : null; |
1668 | if (tablesRequiringHKeyMaintenance == null) { |
1669 | // No PK or FK fields have changed. Just update the row. |
1670 | - packRowData(hEx, newRowDef, mergedRowData); |
1671 | + packRowData(hEx, mergedRowData); |
1672 | // Store the h-row |
1673 | hEx.store(); |
1674 | // Update the indexes (new row) |
1675 | @@ -1169,58 +1137,14 @@ |
1676 | deleteRow(session, oldRowData, true, false, tablesRequiringHKeyMaintenance, true); |
1677 | writeRowStandard(session, mergedRowData, tablesRequiringHKeyMaintenance, true); // May throw DuplicateKeyException |
1678 | } |
1679 | + } catch(PersistitException e) { |
1680 | + throw PersistitAdapter.wrapPersistitException(session, e); |
1681 | } finally { |
1682 | UPDATE_ROW_TAP.out(); |
1683 | releaseExchange(session, hEx); |
1684 | } |
1685 | } |
1686 | |
1687 | - private BitSet analyzeFieldChanges(Session session, RowDef rowDef, RowData oldRow, RowData newRow) |
1688 | - { |
1689 | - BitSet tablesRequiringHKeyMaintenance; |
1690 | - assert oldRow.getRowDefId() == newRow.getRowDefId(); |
1691 | - int fields = rowDef.getFieldCount(); |
1692 | - // Find the PK and FK fields |
1693 | - BitSet keyField = new BitSet(fields); |
1694 | - for (int pkFieldPosition : rowDef.getPKIndex().indexDef().getFields()) { |
1695 | - keyField.set(pkFieldPosition, true); |
1696 | - } |
1697 | - for (int fkFieldPosition : rowDef.getParentJoinFields()) { |
1698 | - keyField.set(fkFieldPosition, true); |
1699 | - } |
1700 | - // Find whether and where key fields differ |
1701 | - boolean allEqual = true; |
1702 | - for (int keyFieldPosition = keyField.nextSetBit(0); |
1703 | - allEqual && keyFieldPosition >= 0; |
1704 | - keyFieldPosition = keyField.nextSetBit(keyFieldPosition + 1)) { |
1705 | - boolean fieldEqual = fieldEqual(rowDef, oldRow, newRow, keyFieldPosition); |
1706 | - if (!fieldEqual) { |
1707 | - allEqual = false; |
1708 | - } |
1709 | - } |
1710 | - if (allEqual) { |
1711 | - tablesRequiringHKeyMaintenance = null; |
1712 | - } else { |
1713 | - // A PK or FK field has changed, so the update has to be done as delete/insert. To minimize hkey |
1714 | - // propagation work, find which tables (descendents of the updated table) are affected by hkey |
1715 | - // changes. |
1716 | - tablesRequiringHKeyMaintenance = hKeyDependentTableOrdinals(session, oldRow.getRowDefId()); |
1717 | - } |
1718 | - return tablesRequiringHKeyMaintenance; |
1719 | - } |
1720 | - |
1721 | - private BitSet hKeyDependentTableOrdinals(Session session, int rowDefId) |
1722 | - { |
1723 | - RowDef rowDef = getRowDef(session, rowDefId); |
1724 | - UserTable table = rowDef.userTable(); |
1725 | - BitSet ordinals = new BitSet(); |
1726 | - for (UserTable hKeyDependentTable : table.hKeyDependentTables()) { |
1727 | - int ordinal = hKeyDependentTable.rowDef().getOrdinal(); |
1728 | - ordinals.set(ordinal, true); |
1729 | - } |
1730 | - return ordinals; |
1731 | - } |
1732 | - |
1733 | private void checkNoGroupIndexes(Table table) { |
1734 | if (updateGroupIndexes && !table.getGroupIndexes().isEmpty()) { |
1735 | throw new UnsupportedOperationException("PersistitStore can't update group indexes; found on " + table); |
1736 | @@ -1278,308 +1202,42 @@ |
1737 | } |
1738 | |
1739 | @Override |
1740 | - public void dropGroup(Session session, Group group) { |
1741 | - for(Table table : group.getRoot().getAIS().getUserTables().values()) { |
1742 | - if(table.getGroup() == group) { |
1743 | - removeTrees(session, table); |
1744 | - } |
1745 | - } |
1746 | - // tableStatusCache entries updated elsewhere |
1747 | - } |
1748 | - |
1749 | - @Override |
1750 | - public void truncateGroup(final Session session, final Group group) throws PersistitException { |
1751 | + public void truncateGroup(final Session session, final Group group) { |
1752 | List<Index> indexes = new ArrayList<>(); |
1753 | - // Collect indexes, truncate table statuses |
1754 | - for(UserTable table : group.getRoot().getAIS().getUserTables().values()) { |
1755 | - if(table.getGroup() == group) { |
1756 | - indexes.addAll(table.getIndexesIncludingInternal()); |
1757 | - table.rowDef().getTableStatus().truncate(); |
1758 | - } |
1759 | - } |
1760 | - indexes.addAll(group.getIndexes()); |
1761 | - truncateIndexes(session, indexes); |
1762 | - |
1763 | // Truncate the group tree |
1764 | final Exchange hEx = getExchange(session, group); |
1765 | - hEx.removeAll(); |
1766 | - releaseExchange(session, hEx); |
1767 | - } |
1768 | + try { |
1769 | + // Collect indexes, truncate table statuses |
1770 | + for(UserTable table : group.getRoot().getAIS().getUserTables().values()) { |
1771 | + if(table.getGroup() == group) { |
1772 | + indexes.addAll(table.getIndexesIncludingInternal()); |
1773 | + table.rowDef().getTableStatus().truncate(); |
1774 | + } |
1775 | + } |
1776 | + indexes.addAll(group.getIndexes()); |
1777 | + truncateIndexes(session, indexes); |
1778 | |
1779 | - // This is to avoid circular dependencies in Guicer. |
1780 | - // TODO: There is still a functional circularity: store needs |
1781 | - // stats to clear them when deleting a group; stats need store to |
1782 | - // persist the stats. It would be better to separate out the |
1783 | - // higher level store functions from what other services require. |
1784 | - public void setIndexStatistics(IndexStatisticsService indexStatistics) { |
1785 | - this.indexStatistics = indexStatistics; |
1786 | + hEx.removeAll(); |
1787 | + } catch(PersistitException e) { |
1788 | + throw PersistitAdapter.wrapPersistitException(session, e); |
1789 | + } finally { |
1790 | + releaseExchange(session, hEx); |
1791 | + } |
1792 | } |
1793 | |
1794 | @Override |
1795 | public void truncateIndexes(Session session, Collection<? extends Index> indexes) { |
1796 | + super.truncateIndexes(session, indexes); |
1797 | for(Index index : indexes) { |
1798 | - Exchange iEx = getExchange(session, index); |
1799 | - try { |
1800 | - iEx.removeAll(); |
1801 | - if (index.isGroupIndex()) { |
1802 | - new AccumulatorAdapter(AccumulatorAdapter.AccumInfo.ROW_COUNT, iEx.getTree()).set(0); |
1803 | - } |
1804 | - } catch (PersistitException e) { |
1805 | - throw new PersistitAdapterException(e); |
1806 | - } |
1807 | - releaseExchange(session, iEx); |
1808 | - } |
1809 | - // Delete any statistics associated with index. |
1810 | - indexStatistics.deleteIndexStatistics(session, indexes); |
1811 | - } |
1812 | - |
1813 | - @Override |
1814 | - public void truncateTableStatus(final Session session, final int rowDefId) throws PersistitException { |
1815 | - getRowDef(session, rowDefId).getTableStatus().truncate(); |
1816 | - } |
1817 | - |
1818 | - @Override |
1819 | - public RowCollector getSavedRowCollector(final Session session, |
1820 | - final int tableId) throws CursorIsUnknownException { |
1821 | - final List<RowCollector> list = collectorsForTableId(session, tableId); |
1822 | - if (list.isEmpty()) { |
1823 | - LOG.debug("Nested RowCollector on tableId={} depth={}", tableId, (list.size() + 1)); |
1824 | - throw new CursorIsUnknownException(tableId); |
1825 | - } |
1826 | - return list.get(list.size() - 1); |
1827 | - } |
1828 | - |
1829 | - @Override |
1830 | - public void addSavedRowCollector(final Session session, |
1831 | - final RowCollector rc) { |
1832 | - final Integer tableId = rc.getTableId(); |
1833 | - final List<RowCollector> list = collectorsForTableId(session, tableId); |
1834 | - if (!list.isEmpty()) { |
1835 | - LOG.debug("Note: Nested RowCollector on tableId={} depth={}", tableId, list.size() + 1); |
1836 | - assert list.get(list.size() - 1) != rc : "Redundant call"; |
1837 | - // |
1838 | - // This disallows the patch because we agreed not to fix the |
1839 | - // bug. However, these changes fix a memory leak, which is |
1840 | - // important for robustness. |
1841 | - // |
1842 | - // throw new StoreException(122, "Bug 255 workaround is disabled"); |
1843 | - } |
1844 | - list.add(rc); |
1845 | - } |
1846 | - |
1847 | - @Override |
1848 | - public void removeSavedRowCollector(final Session session, |
1849 | - final RowCollector rc) throws CursorIsUnknownException { |
1850 | - final Integer tableId = rc.getTableId(); |
1851 | - final List<RowCollector> list = collectorsForTableId(session, tableId); |
1852 | - if (list.isEmpty()) { |
1853 | - throw new CursorIsUnknownException (tableId); |
1854 | - } |
1855 | - final RowCollector removed = list.remove(list.size() - 1); |
1856 | - if (removed != rc) { |
1857 | - throw new CursorCloseBadException (tableId); |
1858 | - } |
1859 | - } |
1860 | - |
1861 | - private List<RowCollector> collectorsForTableId(final Session session, |
1862 | - final int tableId) { |
1863 | - List<RowCollector> list = session.get(COLLECTORS, tableId); |
1864 | - if (list == null) { |
1865 | - list = new ArrayList<>(); |
1866 | - session.put(COLLECTORS, tableId, list); |
1867 | - } |
1868 | - return list; |
1869 | - } |
1870 | - |
1871 | - private RowDef checkRequest(Session session, int rowDefId, RowData start, ColumnSelector startColumns, |
1872 | - RowData end, ColumnSelector endColumns) throws IllegalArgumentException { |
1873 | - if (start != null) { |
1874 | - if (startColumns == null) { |
1875 | - throw new IllegalArgumentException("non-null start row requires non-null ColumnSelector"); |
1876 | - } |
1877 | - if( start.getRowDefId() != rowDefId) { |
1878 | - throw new IllegalArgumentException("Start and end RowData must specify the same rowDefId"); |
1879 | - } |
1880 | - } |
1881 | - if (end != null) { |
1882 | - if (endColumns == null) { |
1883 | - throw new IllegalArgumentException("non-null end row requires non-null ColumnSelector"); |
1884 | - } |
1885 | - if (end.getRowDefId() != rowDefId) { |
1886 | - throw new IllegalArgumentException("Start and end RowData must specify the same rowDefId"); |
1887 | - } |
1888 | - } |
1889 | - final RowDef rowDef = getRowDef(session, rowDefId); |
1890 | - if (rowDef == null) { |
1891 | - throw new IllegalArgumentException("No RowDef for rowDefId " + rowDefId); |
1892 | - } |
1893 | - return rowDef; |
1894 | - } |
1895 | - |
1896 | - private static ColumnSelector createNonNullFieldSelector(final RowData rowData) { |
1897 | - assert rowData != null; |
1898 | - return new ColumnSelector() { |
1899 | - @Override |
1900 | - public boolean includesColumn(int columnPosition) { |
1901 | - return !rowData.isNull(columnPosition); |
1902 | - } |
1903 | - }; |
1904 | - } |
1905 | - |
1906 | - @Override |
1907 | - public RowCollector newRowCollector(Session session, |
1908 | - int rowDefId, |
1909 | - int indexId, |
1910 | - int scanFlags, |
1911 | - RowData start, |
1912 | - RowData end, |
1913 | - byte[] columnBitMap, |
1914 | - ScanLimit scanLimit) |
1915 | - { |
1916 | - return newRowCollector(session, scanFlags, rowDefId, indexId, columnBitMap, start, null, end, null, scanLimit); |
1917 | - } |
1918 | - |
1919 | - @Override |
1920 | - public RowCollector newRowCollector(Session session, |
1921 | - int scanFlags, |
1922 | - int rowDefId, |
1923 | - int indexId, |
1924 | - byte[] columnBitMap, |
1925 | - RowData start, |
1926 | - ColumnSelector startColumns, |
1927 | - RowData end, |
1928 | - ColumnSelector endColumns, |
1929 | - ScanLimit scanLimit) |
1930 | - { |
1931 | - NEW_COLLECTOR_TAP.in(); |
1932 | - RowCollector rc; |
1933 | - try { |
1934 | - if(start != null && startColumns == null) { |
1935 | - startColumns = createNonNullFieldSelector(start); |
1936 | - } |
1937 | - if(end != null && endColumns == null) { |
1938 | - endColumns = createNonNullFieldSelector(end); |
1939 | - } |
1940 | - RowDef rowDef = checkRequest(session, rowDefId, start, startColumns, end, endColumns); |
1941 | - rc = OperatorBasedRowCollector.newCollector(config, |
1942 | - session, |
1943 | - this, |
1944 | - scanFlags, |
1945 | - rowDef, |
1946 | - indexId, |
1947 | - columnBitMap, |
1948 | - start, |
1949 | - startColumns, |
1950 | - end, |
1951 | - endColumns, |
1952 | - scanLimit); |
1953 | - } finally { |
1954 | - NEW_COLLECTOR_TAP.out(); |
1955 | - } |
1956 | - return rc; |
1957 | - } |
1958 | - |
1959 | - public final static long HACKED_ROW_COUNT = 2; |
1960 | - |
1961 | - @Override |
1962 | - public long getRowCount(final Session session, final boolean exact, |
1963 | - final RowData start, final RowData end, final byte[] columnBitMap) { |
1964 | - // |
1965 | - // TODO: Compute a reasonable value. The value "2" is a hack - |
1966 | - // special because it's not 0 or 1, but small enough to induce |
1967 | - // MySQL to use an index rather than full table scan. |
1968 | - // |
1969 | - return HACKED_ROW_COUNT; // TODO: delete the HACKED_ROW_COUNT field when |
1970 | - // this gets fixed |
1971 | - // final int tableId = start.getRowDefId(); |
1972 | - // final TableStatus status = tableManager.getTableStatus(tableId); |
1973 | - // return status.getRowCount(); |
1974 | - } |
1975 | - |
1976 | - @Override |
1977 | - public TableStatistics getTableStatistics(final Session session, int tableId) { |
1978 | - final RowDef rowDef = getRowDef(session, tableId); |
1979 | - final TableStatistics ts = new TableStatistics(tableId); |
1980 | - final TableStatus status = rowDef.getTableStatus(); |
1981 | - try { |
1982 | - ts.setAutoIncrementValue(status.getAutoIncrement()); |
1983 | - ts.setRowCount(status.getRowCount()); |
1984 | - // TODO - get correct values |
1985 | - ts.setMeanRecordLength(100); |
1986 | - ts.setBlockSize(8192); |
1987 | - } catch (PersistitException e) { |
1988 | - throw new PersistitAdapterException(e); |
1989 | - } |
1990 | - for (Index index : rowDef.getIndexes()) { |
1991 | - if (index.isSpatial()) |
1992 | - continue; |
1993 | - TableStatistics.Histogram histogram = indexStatisticsToHistogram(session, |
1994 | - index); |
1995 | - if (histogram != null) { |
1996 | - ts.addHistogram(histogram); |
1997 | - } |
1998 | - } |
1999 | - return ts; |
2000 | - } |
2001 | - |
2002 | - /** Convert from new-format histogram to old for adapter. */ |
2003 | - protected TableStatistics.Histogram indexStatisticsToHistogram(Session session, |
2004 | - Index index) { |
2005 | - IndexStatistics stats = indexStatistics.getIndexStatistics(session, index); |
2006 | - if (stats == null) { |
2007 | - return null; |
2008 | - } |
2009 | - Histogram fromHistogram = stats.getHistogram(0, index.getKeyColumns().size()); |
2010 | - if (fromHistogram == null) { |
2011 | - return null; |
2012 | - } |
2013 | - IndexDef indexDef = index.indexDef(); |
2014 | - RowDef indexRowDef = indexDef.getRowDef(); |
2015 | - TableStatistics.Histogram toHistogram = new TableStatistics.Histogram(index.getIndexId()); |
2016 | - Key key = treeService.createKey(); |
2017 | - RowData indexRowData = new RowData(new byte[4096]); |
2018 | - Object[] indexValues = new Object[indexRowDef.getFieldCount()]; |
2019 | - long count = 0; |
2020 | - for (HistogramEntry entry : fromHistogram.getEntries()) { |
2021 | - // Decode the key. |
2022 | - int keylen = entry.getKeyBytes().length; |
2023 | - System.arraycopy(entry.getKeyBytes(), 0, key.getEncodedBytes(), 0, keylen); |
2024 | - key.setEncodedSize(keylen); |
2025 | - key.indexTo(0); |
2026 | - int depth = key.getDepth(); |
2027 | - // Copy key fields to index row. |
2028 | - for (int field : indexDef.getFields()) { |
2029 | - if (--depth >= 0) { |
2030 | - indexValues[field] = key.decode(); |
2031 | - } else { |
2032 | - indexValues[field] = null; |
2033 | - } |
2034 | - } |
2035 | - indexRowData.createRow(indexRowDef, indexValues); |
2036 | - // Partial counts to running total less than key. |
2037 | - count += entry.getLessCount(); |
2038 | - toHistogram.addSample(new TableStatistics.HistogramSample(indexRowData.copy(), |
2039 | - count)); |
2040 | - count += entry.getEqualCount(); |
2041 | - } |
2042 | - // Add final entry with all nulls. |
2043 | - Arrays.fill(indexValues, null); |
2044 | - indexRowData.createRow(indexRowDef, indexValues); |
2045 | - toHistogram.addSample(new TableStatistics.HistogramSample(indexRowData.copy(), |
2046 | - count)); |
2047 | - return toHistogram; |
2048 | - } |
2049 | - |
2050 | - boolean hasNullIndexSegments(RowData rowData, Index index) |
2051 | - { |
2052 | - IndexDef indexDef = index.indexDef(); |
2053 | - assert indexDef.getRowDef().getRowDefId() == rowData.getRowDefId(); |
2054 | - for (int i : indexDef.getFields()) { |
2055 | - if (rowData.isNull(i)) { |
2056 | - return true; |
2057 | - } |
2058 | - } |
2059 | - return false; |
2060 | + if(index.isGroupIndex()) { |
2061 | + try { |
2062 | + Tree tree = index.indexDef().getTreeCache().getTree(); |
2063 | + new AccumulatorAdapter(AccumulatorAdapter.AccumInfo.ROW_COUNT, tree).set(0); |
2064 | + } catch(PersistitInterruptedException e) { |
2065 | + throw PersistitAdapter.wrapPersistitException(session, e); |
2066 | + } |
2067 | + } |
2068 | + } |
2069 | } |
2070 | |
2071 | private void checkNotGroupIndex(Index index) { |
2072 | @@ -1607,24 +1265,13 @@ |
2073 | { |
2074 | checkNotGroupIndex(index); |
2075 | Exchange iEx = getExchange(session, index); |
2076 | - constructIndexRow(iEx, rowData, index, hkey, indexRow, true); |
2077 | - checkUniqueness(index, rowData, iEx); |
2078 | - if (deferIndexes) { |
2079 | - // TODO: bug767737, deferred indexing does not handle uniqueness |
2080 | - synchronized (deferredIndexKeys) { |
2081 | - SortedSet<KeyState> keySet = deferredIndexKeys.get(iEx.getTree()); |
2082 | - if (keySet == null) { |
2083 | - keySet = new TreeSet<>(); |
2084 | - deferredIndexKeys.put(iEx.getTree(), keySet); |
2085 | - } |
2086 | - KeyState ks = new KeyState(iEx.getKey()); |
2087 | - keySet.add(ks); |
2088 | - deferredIndexKeyLimit -= (ks.getBytes().length + KEY_STATE_SIZE_OVERHEAD); |
2089 | - } |
2090 | - } else { |
2091 | + try { |
2092 | + constructIndexRow(iEx, rowData, index, hkey, indexRow, true); |
2093 | + checkUniqueness(index, rowData, iEx); |
2094 | storageAction.store(iEx); |
2095 | + } finally { |
2096 | + releaseExchange(session, iEx); |
2097 | } |
2098 | - releaseExchange(session, iEx); |
2099 | } |
2100 | |
2101 | private void checkUniqueness(Index index, RowData rowData, Exchange iEx) throws PersistitException |
2102 | @@ -1661,22 +1308,6 @@ |
2103 | return keyExistsInIndex; |
2104 | } |
2105 | |
2106 | - private void putAllDeferredIndexKeys(final Session session) { |
2107 | - synchronized (deferredIndexKeys) { |
2108 | - for (final Map.Entry<Tree, SortedSet<KeyState>> entry : deferredIndexKeys |
2109 | - .entrySet()) { |
2110 | - final Exchange iEx = treeService.getExchange(session, entry.getKey()); |
2111 | - try { |
2112 | - buildIndexAddKeys(entry.getValue(), iEx); |
2113 | - entry.getValue().clear(); |
2114 | - } finally { |
2115 | - treeService.releaseExchange(session, iEx); |
2116 | - } |
2117 | - } |
2118 | - deferredIndexKeyLimit = MAX_INDEX_TRANCHE_SIZE; |
2119 | - } |
2120 | - } |
2121 | - |
2122 | private void updateIndex(Session session, |
2123 | Index index, |
2124 | RowDef rowDef, |
2125 | @@ -1761,47 +1392,11 @@ |
2126 | releaseExchange(session, iEx); |
2127 | } |
2128 | |
2129 | - static boolean bytesEqual(byte[] a, int aoffset, int asize, |
2130 | - byte[] b, int boffset, int bsize) { |
2131 | - if (asize != bsize) { |
2132 | - return false; |
2133 | - } |
2134 | - for (int i = 0; i < asize; i++) { |
2135 | - if (a[i + aoffset] != b[i + boffset]) { |
2136 | - return false; |
2137 | - } |
2138 | - } |
2139 | - return true; |
2140 | - } |
2141 | - |
2142 | - public static boolean fieldsEqual(RowDef rowDef, RowData a, RowData b, int[] fieldIndexes) |
2143 | - { |
2144 | - for (int fieldIndex : fieldIndexes) { |
2145 | - long aloc = rowDef.fieldLocation(a, fieldIndex); |
2146 | - long bloc = rowDef.fieldLocation(b, fieldIndex); |
2147 | - if (!bytesEqual(a.getBytes(), (int) aloc, (int) (aloc >>> 32), |
2148 | - b.getBytes(), (int) bloc, (int) (bloc >>> 32))) { |
2149 | - return false; |
2150 | - } |
2151 | - } |
2152 | - return true; |
2153 | - } |
2154 | - |
2155 | - public static boolean fieldEqual(RowDef rowDef, RowData a, RowData b, int fieldPosition) |
2156 | - { |
2157 | - long aloc = rowDef.fieldLocation(a, fieldPosition); |
2158 | - long bloc = rowDef.fieldLocation(b, fieldPosition); |
2159 | - return bytesEqual(a.getBytes(), (int) aloc, (int) (aloc >>> 32), |
2160 | - b.getBytes(), (int) bloc, (int) (bloc >>> 32)); |
2161 | - } |
2162 | - |
2163 | - public void packRowData(final Exchange hEx, final RowDef rowDef, |
2164 | - final RowData rowData) { |
2165 | - packRowData(hEx.getValue(), rowDef, rowData); |
2166 | - } |
2167 | - |
2168 | - public void packRowData(final Value value, final RowDef rowDef, |
2169 | - final RowData rowData) { |
2170 | + public void packRowData(final Exchange hEx,final RowData rowData) { |
2171 | + packRowData(hEx.getValue(), rowData); |
2172 | + } |
2173 | + |
2174 | + public void packRowData(final Value value, final RowData rowData) { |
2175 | value.directPut(valueCoder, rowData, null); |
2176 | } |
2177 | |
2178 | @@ -1818,8 +1413,8 @@ |
2179 | // rowData.prepareRow(0); |
2180 | } |
2181 | |
2182 | + @Override |
2183 | public void buildIndexes(Session session, Collection<? extends Index> indexes, boolean defer) { |
2184 | - flushIndexes(session); |
2185 | Set<Group> groups = new HashSet<>(); |
2186 | Map<Integer,RowDef> userRowDefs = new HashMap<>(); |
2187 | Set<Index> indexesToBuild = new HashSet<>(); |
2188 | @@ -1852,103 +1447,37 @@ |
2189 | indexKeyCount++; |
2190 | } |
2191 | } |
2192 | - if (deferredIndexKeyLimit <= 0) { |
2193 | - putAllDeferredIndexKeys(session); |
2194 | - } |
2195 | } |
2196 | } |
2197 | } catch (PersistitException e) { |
2198 | throw new PersistitAdapterException(e); |
2199 | } |
2200 | - flushIndexes(session); |
2201 | LOG.debug("Inserted {} index keys into group {}", indexKeyCount, group.getName()); |
2202 | } |
2203 | } |
2204 | |
2205 | @Override |
2206 | - public void removeTrees(Session session, Collection<? extends TreeLink> treeLinks) { |
2207 | - try { |
2208 | - for(TreeLink link : treeLinks) { |
2209 | - if(!schemaManager.treeRemovalIsDelayed()) { |
2210 | - Exchange ex = treeService.getExchange(session, link); |
2211 | - ex.removeTree(); |
2212 | - // Do not releaseExchange, causes caching and leak for now unused tree |
2213 | - } |
2214 | - schemaManager.treeWasRemoved(session, link.getSchemaName(), link.getTreeName()); |
2215 | - } |
2216 | - } catch (PersistitException e) { |
2217 | - LOG.debug("Exception removing tree from Persistit", e); |
2218 | - throw new PersistitAdapterException(e); |
2219 | + public void removeTrees(Session session, UserTable table) { |
2220 | + super.removeTrees(session, table); |
2221 | + |
2222 | + // TODO: Generalize. Knowing about FullTextService is wrong. |
2223 | + for(FullTextIndex idx : table.getOwnFullTextIndexes()) { |
2224 | + fullTextService.dropIndex(session, idx); |
2225 | } |
2226 | } |
2227 | |
2228 | @Override |
2229 | - public void removeTrees(Session session, Table table) { |
2230 | - Collection<TreeLink> treeLinks = new ArrayList<>(); |
2231 | - |
2232 | - // delete all fulltext indexes |
2233 | - if (table.isUserTable()) |
2234 | - { |
2235 | - for (FullTextIndex idx : ((UserTable)table).getOwnFullTextIndexes()) |
2236 | - fullTextService.dropIndex(session, idx); |
2237 | - } |
2238 | - |
2239 | - // Add all index trees |
2240 | - final Collection<TableIndex> tableIndexes = table.isUserTable() ? ((UserTable)table).getIndexesIncludingInternal() : table.getIndexes(); |
2241 | - final Collection<GroupIndex> groupIndexes = table.getGroupIndexes(); |
2242 | - for(Index index : tableIndexes) { |
2243 | - treeLinks.add(index.indexDef()); |
2244 | - } |
2245 | - for(Index index : groupIndexes) { |
2246 | - treeLinks.add(index.indexDef()); |
2247 | - } |
2248 | - // Drop the sequence trees too. |
2249 | - if (table.isUserTable() && ((UserTable)table).getIdentityColumn() != null) { |
2250 | - treeLinks.add(((UserTable)table).getIdentityColumn().getIdentityGenerator()); |
2251 | - } else if (table.isGroupTable()) { |
2252 | - for (UserTable userTable : table.getAIS().getUserTables().values()) { |
2253 | - if (userTable.getGroup() == table.getGroup() && |
2254 | - userTable.getIdentityColumn() != null) { |
2255 | - treeLinks.add(userTable.getIdentityColumn().getIdentityGenerator()); |
2256 | - } |
2257 | - } |
2258 | - } |
2259 | - |
2260 | - // And the group tree |
2261 | - treeLinks.add(table.getGroup()); |
2262 | - // And drop them all |
2263 | - removeTrees(session, treeLinks); |
2264 | - indexStatistics.deleteIndexStatistics(session, tableIndexes); |
2265 | - indexStatistics.deleteIndexStatistics(session, groupIndexes); |
2266 | - } |
2267 | - |
2268 | - public void flushIndexes(final Session session) { |
2269 | - try { |
2270 | - putAllDeferredIndexKeys(session); |
2271 | - } catch (PersistitAdapterException e) { |
2272 | - LOG.debug("Exception while trying to flush deferred index keys", e); |
2273 | - throw e; |
2274 | - } |
2275 | - } |
2276 | - |
2277 | public void deleteIndexes(final Session session, final Collection<? extends Index> indexes) { |
2278 | - List<TreeLink> links = new ArrayList<>(indexes.size()); |
2279 | + super.deleteIndexes(session, indexes); |
2280 | + // TODO: Generalize. Knowing about FullTextService is wrong. |
2281 | for(Index index : indexes) { |
2282 | // no trees to drop |
2283 | if (index.getIndexType() == IndexType.FULL_TEXT) |
2284 | { |
2285 | fullTextService.dropIndex(session, (FullTextIndex)index); |
2286 | indexes.remove(index); |
2287 | - continue; |
2288 | - } |
2289 | - final IndexDef indexDef = index.indexDef(); |
2290 | - if(indexDef == null) { |
2291 | - throw new IllegalStateException("indexDef is null for index: " + index); |
2292 | - } |
2293 | - links.add(indexDef); |
2294 | + } |
2295 | } |
2296 | - removeTrees(session, links); |
2297 | - indexStatistics.deleteIndexStatistics(session, indexes); |
2298 | } |
2299 | |
2300 | @Override |
2301 | @@ -1956,28 +1485,6 @@ |
2302 | removeTrees(session, sequences); |
2303 | } |
2304 | |
2305 | - private void buildIndexAddKeys(final SortedSet<KeyState> keys, |
2306 | - final Exchange iEx) { |
2307 | - final long start = System.nanoTime(); |
2308 | - try { |
2309 | - for (final KeyState keyState : keys) { |
2310 | - keyState.copyTo(iEx.getKey()); |
2311 | - iEx.store(); |
2312 | - } |
2313 | - } catch (PersistitException e) { |
2314 | - LOG.error(e.getMessage()); |
2315 | - throw new PersistitAdapterException(e); |
2316 | - } |
2317 | - final long elapsed = System.nanoTime() - start; |
2318 | - if (LOG.isInfoEnabled()) { |
2319 | - LOG.debug("Index builder inserted {} keys into index tree {} in {} seconds", new Object[]{ |
2320 | - keys.size(), |
2321 | - iEx.getTree().getName(), |
2322 | - elapsed / 1000000000 |
2323 | - }); |
2324 | - } |
2325 | - } |
2326 | - |
2327 | private RowData mergeRows(RowDef rowDef, RowData currentRow, RowData newRowData, ColumnSelector columnSelector) { |
2328 | NewRow mergedRow = NiceRow.fromRowData(currentRow, rowDef); |
2329 | NewRow newRow = new LegacyRowWrapper(rowDef, newRowData); |
2330 | @@ -1990,24 +1497,6 @@ |
2331 | return mergedRow.toRowData(); |
2332 | } |
2333 | |
2334 | - private RowDef rowDefFromExplicitOrId(Session session, RowData rowData) { |
2335 | - RowDef rowDef = rowData.getExplicitRowDef(); |
2336 | - if(rowDef == null) { |
2337 | - rowDef = getRowDef(session, rowData.getRowDefId()); |
2338 | - } |
2339 | - return rowDef; |
2340 | - } |
2341 | - |
2342 | - @Override |
2343 | - public boolean isDeferIndexes() { |
2344 | - return deferIndexes; |
2345 | - } |
2346 | - |
2347 | - @Override |
2348 | - public void setDeferIndexes(final boolean defer) { |
2349 | - deferIndexes = defer; |
2350 | - } |
2351 | - |
2352 | private void lockAndCheckVersion(Session session, RowDef rowDef) { |
2353 | final LockService.Mode mode = LockService.Mode.SHARED; |
2354 | final int tableID = rowDef.getRowDefId(); |
2355 | @@ -2070,24 +1559,11 @@ |
2356 | return visitor; |
2357 | } |
2358 | |
2359 | - public TableStatus getTableStatus(Table table) { |
2360 | - TableStatus ts = null; |
2361 | - if(table.rowDef() != null) { |
2362 | - ts = table.rowDef().getTableStatus(); |
2363 | - } |
2364 | - return ts; |
2365 | - } |
2366 | - |
2367 | private static PersistitAdapter adapter(Session session) |
2368 | { |
2369 | return (PersistitAdapter) session.get(StoreAdapter.STORE_ADAPTER_KEY); |
2370 | } |
2371 | |
2372 | - private static boolean hasChildren(UserTable table) { |
2373 | - // At runtime, getCandidateChildJoins() = getChildJoins() and doesn't involve building a temp list |
2374 | - return !table.getCandidateChildJoins().isEmpty(); |
2375 | - } |
2376 | - |
2377 | private TreeBuilder createTreeBuilder(String name, float bufferBoolFraction) { |
2378 | TreeBuilder tb = new TreeBuilder(getDb(), name, -1, bufferBoolFraction) |
2379 | // TODO: throw an Akiban dup-key exception once we can handle them |
2380 | @@ -2153,6 +1629,38 @@ |
2381 | lockKeyAppender.clear(); |
2382 | } |
2383 | |
2384 | + @Override |
2385 | + public StoreAdapter createAdapter(Session session, Schema schema) { |
2386 | + return new PersistitAdapter(schema, this, treeService, session, config); |
2387 | + } |
2388 | + |
2389 | + @Override |
2390 | + public void truncateTree(Session session, TreeLink treeLink) { |
2391 | + Exchange iEx = treeService.getExchange(session, treeLink); |
2392 | + try { |
2393 | + iEx.removeAll(); |
2394 | + } catch (PersistitException e) { |
2395 | + throw PersistitAdapter.wrapPersistitException(session, e); |
2396 | + } finally { |
2397 | + releaseExchange(session, iEx); |
2398 | + } |
2399 | + } |
2400 | + |
2401 | + @Override |
2402 | + public void removeTree(Session session, TreeLink treeLink) { |
2403 | + try { |
2404 | + if(!schemaManager.treeRemovalIsDelayed()) { |
2405 | + Exchange ex = treeService.getExchange(session, treeLink); |
2406 | + ex.removeTree(); |
2407 | + // Do not releaseExchange, causes caching and leak for now unused tree |
2408 | + } |
2409 | + schemaManager.treeWasRemoved(session, treeLink.getSchemaName(), treeLink.getTreeName()); |
2410 | + } catch (PersistitException e) { |
2411 | + LOG.debug("Exception removing tree from Persistit", e); |
2412 | + throw PersistitAdapter.wrapPersistitException(session, e); |
2413 | + } |
2414 | + } |
2415 | + |
2416 | private class Bulkload { |
2417 | |
2418 | Bulkload(final Persistit persistit, AkibanInformationSchema ais) { |
2419 | |
2420 | === modified file 'src/main/java/com/akiban/server/store/PersistitStoreSchemaManager.java' |
2421 | --- src/main/java/com/akiban/server/store/PersistitStoreSchemaManager.java 2013-04-11 18:35:20 +0000 |
2422 | +++ src/main/java/com/akiban/server/store/PersistitStoreSchemaManager.java 2013-05-20 14:47:34 +0000 |
2423 | @@ -474,11 +474,7 @@ |
2424 | for(ChangedTableDescription desc : alteredTables) { |
2425 | if(desc.isNewGroup()) { |
2426 | UserTable oldTable = oldAIS.getUserTable(desc.getOldName()); |
2427 | - try { |
2428 | - oldTable.rowDef().getTableStatus().setOrdinal(0); |
2429 | - } catch(PersistitException e) { |
2430 | - throw wrapPersistitException(session, e); |
2431 | - } |
2432 | + oldTable.rowDef().getTableStatus().setOrdinal(0); |
2433 | } |
2434 | } |
2435 | |
2436 | |
2437 | === modified file 'src/main/java/com/akiban/server/store/Store.java' |
2438 | --- src/main/java/com/akiban/server/store/Store.java 2013-04-14 00:26:23 +0000 |
2439 | +++ src/main/java/com/akiban/server/store/Store.java 2013-05-20 14:47:34 +0000 |
2440 | @@ -17,57 +17,40 @@ |
2441 | |
2442 | package com.akiban.server.store; |
2443 | |
2444 | +import com.akiban.ais.model.AkibanInformationSchema; |
2445 | import com.akiban.ais.model.Group; |
2446 | import com.akiban.ais.model.Index; |
2447 | import com.akiban.ais.model.Sequence; |
2448 | -import com.akiban.ais.model.Table; |
2449 | +import com.akiban.ais.model.TableName; |
2450 | +import com.akiban.ais.model.UserTable; |
2451 | +import com.akiban.qp.operator.StoreAdapter; |
2452 | +import com.akiban.qp.rowtype.Schema; |
2453 | import com.akiban.server.TableStatistics; |
2454 | import com.akiban.server.api.dml.ColumnSelector; |
2455 | import com.akiban.server.api.dml.scan.ScanLimit; |
2456 | import com.akiban.server.rowdata.RowData; |
2457 | import com.akiban.server.rowdata.RowDef; |
2458 | import com.akiban.server.service.session.Session; |
2459 | +import com.akiban.server.service.tree.KeyCreator; |
2460 | import com.akiban.server.service.tree.TreeLink; |
2461 | -import com.persistit.exception.PersistitException; |
2462 | -import com.persistit.exception.RollbackException; |
2463 | +import com.akiban.server.store.statistics.IndexStatisticsService; |
2464 | |
2465 | import java.util.Collection; |
2466 | |
2467 | -/** |
2468 | - * An abstraction for a layer that stores and retrieves data |
2469 | - * |
2470 | - * @author peter |
2471 | - * |
2472 | - */ |
2473 | -public interface Store { |
2474 | +public interface Store extends KeyCreator { |
2475 | |
2476 | /** Get the RowDef for the given ID. Note, a transaction should be active before calling this. */ |
2477 | RowDef getRowDef(Session session, int rowDefID); |
2478 | - |
2479 | - void writeRow(Session session, RowData rowData) throws PersistitException; |
2480 | - |
2481 | - void deleteRow(Session session, RowData rowData, boolean deleteIndexes, boolean cascadeDelete) throws PersistitException; |
2482 | + RowDef getRowDef(Session session, TableName tableName); |
2483 | + AkibanInformationSchema getAIS(Session session); |
2484 | + |
2485 | + void writeRow(Session session, RowData rowData); |
2486 | + |
2487 | + void deleteRow(Session session, RowData rowData, boolean deleteIndexes, boolean cascadeDelete); |
2488 | |
2489 | void updateRow(Session session, RowData oldRowData, |
2490 | RowData newRowData, |
2491 | - ColumnSelector columnSelector, Index[] indexes) throws PersistitException; |
2492 | - |
2493 | - /** |
2494 | - * See {@link #newRowCollector(Session, int, int, int, byte[], RowData, ColumnSelector, RowData, ColumnSelector, ScanLimit)} |
2495 | - * for parameter descriptions. |
2496 | - * @throws Exception |
2497 | - * |
2498 | - * @deprecated This constructor is ambiguous and may not return the expected rows. Fields from <code>start</code> |
2499 | - * and <code>end</code> that are <code>NULL</code> are considered to be <b>unset</b>. |
2500 | - */ |
2501 | - RowCollector newRowCollector(Session session, |
2502 | - int rowDefId, |
2503 | - int indexId, |
2504 | - int scanFlags, |
2505 | - RowData start, |
2506 | - RowData end, |
2507 | - byte[] columnBitMap, |
2508 | - ScanLimit scanLimit); |
2509 | + ColumnSelector columnSelector, Index[] indexes); |
2510 | |
2511 | /** |
2512 | * Create a new RowCollector. |
2513 | @@ -134,13 +117,10 @@ |
2514 | * Truncate the given group. This includes indexes from all tables, group |
2515 | * indexes, the group itself, and all table statuses. |
2516 | */ |
2517 | - void truncateGroup(Session session, Group group) throws PersistitException; |
2518 | - |
2519 | - void truncateTableStatus(Session session, int rowDefId) throws RollbackException, PersistitException; |
2520 | - |
2521 | - boolean isDeferIndexes(); |
2522 | - void setDeferIndexes(boolean b); |
2523 | - void flushIndexes(Session session); |
2524 | + void truncateGroup(Session session, Group group); |
2525 | + |
2526 | + void truncateTableStatus(Session session, int rowDefId); |
2527 | + |
2528 | void deleteIndexes(Session session, Collection<? extends Index> indexes); |
2529 | void buildIndexes(Session session, Collection<? extends Index> indexes, boolean deferIndexes); |
2530 | |
2531 | @@ -149,10 +129,11 @@ |
2532 | * Remove all trees, and their contents, associated with the given table. |
2533 | * @param session Session |
2534 | * @param table Table |
2535 | - * @throws PersistitException |
2536 | - * @throws Exception |
2537 | + * @throws Exception |
2538 | */ |
2539 | - void removeTrees(Session session, Table table); |
2540 | + void removeTrees(Session session, UserTable table); |
2541 | + void removeTree(Session session, TreeLink treeLink); |
2542 | + void truncateTree(Session session, TreeLink treeLink); |
2543 | |
2544 | /** |
2545 | * Low level operation. Removes the given trees and <i>only</i> the given trees. |
2546 | @@ -171,4 +152,8 @@ |
2547 | void finishBulkLoad(Session session); |
2548 | |
2549 | boolean isBulkloading(); |
2550 | + |
2551 | + void setIndexStatistics(IndexStatisticsService indexStatistics); |
2552 | + |
2553 | + StoreAdapter createAdapter(Session session, Schema schema); |
2554 | } |
2555 | |
2556 | === modified file 'src/main/java/com/akiban/server/store/statistics/IndexStatisticsServiceImpl.java' |
2557 | --- src/main/java/com/akiban/server/store/statistics/IndexStatisticsServiceImpl.java 2013-04-11 05:51:16 +0000 |
2558 | +++ src/main/java/com/akiban/server/store/statistics/IndexStatisticsServiceImpl.java 2013-05-20 14:47:34 +0000 |
2559 | @@ -146,7 +146,7 @@ |
2560 | if (table.hasMemoryTableFactory()) { |
2561 | return table.getMemoryTableFactory().rowCount(); |
2562 | } else { |
2563 | - return store.getTableStatus(table).getRowCount(); |
2564 | + return table.rowDef().getTableStatus().getRowCount(); |
2565 | } |
2566 | } |
2567 | final Exchange ex = store.getExchange(session, index); |
2568 | @@ -161,7 +161,7 @@ |
2569 | @Override |
2570 | public long countEntriesApproximate(Session session, Index index) { |
2571 | if (index.isTableIndex()) { |
2572 | - return store.getTableStatus(((TableIndex)index).getTable()).getApproximateRowCount(); |
2573 | + return index.leafMostTable().rowDef().getTableStatus().getApproximateRowCount(); |
2574 | } |
2575 | final Exchange ex = store.getExchange(session, index); |
2576 | try { |
2577 | |
2578 | === modified file 'src/main/java/com/akiban/server/store/statistics/PersistitStoreIndexStatistics.java' |
2579 | --- src/main/java/com/akiban/server/store/statistics/PersistitStoreIndexStatistics.java 2013-03-22 20:05:57 +0000 |
2580 | +++ src/main/java/com/akiban/server/store/statistics/PersistitStoreIndexStatistics.java 2013-05-20 14:47:34 +0000 |
2581 | @@ -284,6 +284,9 @@ |
2582 | RowData rowData = new RowData(new byte[INITIAL_ROW_SIZE]); |
2583 | RowDef indexStatisticsRowDef = getIndexStatsRowDef(session); |
2584 | RowDef indexStatisticsEntryRowDef = getIndexStatsEntryRowDef(session); |
2585 | + if(index.indexDef() == null) { |
2586 | + return; |
2587 | + } |
2588 | int tableId = index.indexDef().getRowDef().getRowDefId(); |
2589 | int indexId = index.getIndexId(); |
2590 | // Delete index_statistics_entry rows. |
2591 | |
2592 | === modified file 'src/test/java/com/akiban/server/test/it/keyupdate/FixCountStarIT.java' |
2593 | --- src/test/java/com/akiban/server/test/it/keyupdate/FixCountStarIT.java 2013-04-11 05:51:16 +0000 |
2594 | +++ src/test/java/com/akiban/server/test/it/keyupdate/FixCountStarIT.java 2013-05-20 14:47:34 +0000 |
2595 | @@ -95,7 +95,7 @@ |
2596 | public void run() { |
2597 | if (index.isTableIndex()) { |
2598 | TableIndex tIndex = (TableIndex) index; |
2599 | - store().getPersistitStore().getTableStatus(tIndex.getTable()).setRowCount(newVal); |
2600 | + tIndex.leafMostTable().rowDef().getTableStatus().setRowCount(newVal); |
2601 | } |
2602 | else { |
2603 | PersistitStore store = store().getPersistitStore(); |
2604 | |
2605 | === modified file 'src/test/java/com/akiban/server/test/it/rowtests/ObjectToKeyIT.java' |
2606 | --- src/test/java/com/akiban/server/test/it/rowtests/ObjectToKeyIT.java 2013-03-22 20:05:57 +0000 |
2607 | +++ src/test/java/com/akiban/server/test/it/rowtests/ObjectToKeyIT.java 2013-05-20 14:47:34 +0000 |
2608 | @@ -38,7 +38,7 @@ |
2609 | } |
2610 | |
2611 | private void testObjectToKey(FieldDef field, Object... testValues) throws PersistitException { |
2612 | - Key key = persistitStore().getKey(); |
2613 | + Key key = persistitStore().createKey(); |
2614 | PersistitKeyAppender appender = PersistitKeyAppender.create(key); |
2615 | for(Object inObj : testValues) { |
2616 | key.clear(); |
2617 | |
2618 | === modified file 'src/test/java/com/akiban/server/test/it/store/AbstractScanBase.java' |
2619 | --- src/test/java/com/akiban/server/test/it/store/AbstractScanBase.java 2013-03-27 04:42:10 +0000 |
2620 | +++ src/test/java/com/akiban/server/test/it/store/AbstractScanBase.java 2013-05-20 14:47:34 +0000 |
2621 | @@ -139,8 +139,8 @@ |
2622 | final byte[] columnBitMap, final int indexId) throws Exception { |
2623 | int scanCount = 0; |
2624 | result.clear(); |
2625 | - final RowCollector rc = store().newRowCollector(session(), rowDefId, indexId, |
2626 | - scanFlags, start, end, columnBitMap, null); |
2627 | + final RowCollector rc = store().newRowCollector(session(), scanFlags, rowDefId, indexId, columnBitMap, |
2628 | + start, null, end, null, null); |
2629 | if (VERBOSE) { |
2630 | System.out.println("Test " + test); |
2631 | } |
Looks as described.