Merge lp:~pbeaman/akiban-persistit/fix-accumulator-javadoc into lp:akiban-persistit

Proposed by Peter Beaman
Status: Merged
Approved by: Peter Beaman
Approved revision: 439
Merged at revision: 429
Proposed branch: lp:~pbeaman/akiban-persistit/fix-accumulator-javadoc
Merge into: lp:akiban-persistit
Diff against target: 1193 lines (+380/-182)
14 files modified
pom.xml (+1/-1)
src/main/java/com/persistit/Accumulator.java (+158/-68)
src/main/java/com/persistit/SessionId.java (+13/-2)
src/main/java/com/persistit/SharedResource.java (+5/-1)
src/main/java/com/persistit/Tree.java (+94/-2)
src/test/java/com/persistit/AccumulatorRecoveryTest.java (+11/-18)
src/test/java/com/persistit/AccumulatorTest.java (+44/-38)
src/test/java/com/persistit/Bug1064565Test.java (+9/-8)
src/test/java/com/persistit/Bug911849Test.java (+3/-7)
src/test/java/com/persistit/Bug920754Test.java (+5/-3)
src/test/java/com/persistit/Bug974589Test.java (+5/-4)
src/test/java/com/persistit/JournalManagerTest.java (+6/-7)
src/test/java/com/persistit/stress/unit/AccumulatorRestart.java (+15/-12)
src/test/java/com/persistit/stress/unit/Stress8txn.java (+11/-11)
To merge this branch: bzr merge lp:~pbeaman/akiban-persistit/fix-accumulator-javadoc
Reviewer Review Type Date Requested Status
Nathan Williams Needs Fixing
Review via email: mp+158163@code.launchpad.net

Description of the change

Improve the Javadoc for com.persistit.Accumulator to provide better information about snapshot and live values, and the semantics of the update method. Also took this opportunity to implement safeguards against numerical overflows.

To post a comment you must log in.
430. By Peter Beaman

Modify Accumulator API

431. By Peter Beaman

Fix various small test failures. Make SessionId constructor public (miscellaneous).

432. By Peter Beaman

Fix another test

433. By Peter Beaman

More Javadoc tweaks

434. By Peter Beaman

Add the update(long) method back in to ease server changes

435. By Peter Beaman

Deprecate Tree#getAccumulator

Revision history for this message
Peter Beaman (pbeaman) wrote :

Per discussion with Mike and Nathan, the Accumulator API has now changed. Therefore in addition to Javadoc changes, this branch contains quite a few code changes and also a new version number.

Specifically, each kind of accumulator now has a custom method for updating it. A SUM, MIN, MAX and SEQ accumulators are modified by their add(long), minimum(long), maximum(long) and allocate() methods, respectively. Only the allocate() method returns a value. The original update method (minus the Transaction argument) is still present to support the AccumulatorAdpater, but is deprecated. Since the application needs to have specify the final class rather than the base class, the final classes are now public, and there are new type-specific helper methods in Tree to get them. So instead of

  Tree#getAccumulator(Accumulator.Type.SUM, int)

you use

  Tree#getSumAccumulator(int)

The original method remains, but is deprecated.

A minor unrelated change is to make the constructor of SessionId public. This is also an API fix, and I wanted to get it in before forgetting about it.

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

SeqAccumulator#allocate() references a method that is not public in the warning (#update).

I'd say rip out the 'deprecated' constructors since there are other breaking changes.

Otherwise looks good and as described.

review: Needs Fixing
436. By Peter Beaman

Format

437. By Peter Beaman

Fix some more Javadoc errors

438. By Peter Beaman

Remove Tree#getAccumulator

Revision history for this message
Peter Beaman (pbeaman) wrote :

Thanks. Javadoc warnings and faulty example code fixed, and Tree#getAccumulator is now package-private.

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

Did you want to remove the deprecated Accumulator#update(long) as well?

Otherwise looks good and feel free to big-A after that.

Revision history for this message
Peter Beaman (pbeaman) wrote :

I'll take care of it. Thanks.

On Thu, Apr 11, 2013 at 11:18 AM, Nathan Williams <email address hidden>wrote:

> Did you want to remove the deprecated Accumulator#update(long) as well?
>
> Otherwise looks good and feel free to big-A after that.
> --
>
> https://code.launchpad.net/~pbeaman/akiban-persistit/fix-accumulator-javadoc/+merge/158163
> You are the owner of lp:~pbeaman/akiban-persistit/fix-accumulator-javadoc.
>

439. By Peter Beaman

Remove Accumulator#update(long)

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'pom.xml'
2--- pom.xml 2013-03-24 17:25:45 +0000
3+++ pom.xml 2013-04-11 15:33:26 +0000
4@@ -4,7 +4,7 @@
5
6 <groupId>com.akiban</groupId>
7 <artifactId>akiban-persistit</artifactId>
8- <version>3.2.8-SNAPSHOT</version>
9+ <version>3.2.9-SNAPSHOT</version>
10 <packaging>jar</packaging>
11
12 <parent>
13
14=== modified file 'src/main/java/com/persistit/Accumulator.java'
15--- src/main/java/com/persistit/Accumulator.java 2013-01-19 17:42:22 +0000
16+++ src/main/java/com/persistit/Accumulator.java 2013-04-11 15:33:26 +0000
17@@ -30,19 +30,20 @@
18 * include <code>SumAccumulator</code>, <code>MinAccumulator</code>,
19 * <code>MaxAccumulator</code> and <code>SeqAccumulator</code> which compute the
20 * sum, minimum and maximum values of contributions by individual transactions.
21- * (See below for semantics of the <code>SeqAccummulator</code>.) Each
22- * contribution is accounted for separately as a <code>Delta</code> instance
23- * until the transaction is either committed or aborted and there are no other
24- * concurrently executing transactions that started before the commit timestamp.
25- * This mechanism is designed to provide a "snapshot" view of the Accumulator
26- * that is consistent with the snapshot view of the database.
27+ * (See <a href="#_SeqAccumulator">below</a> for semantics of the
28+ * <code>SeqAccummulator</code>.) Each contribution is accounted for separately
29+ * as a <code>Delta</code> instance until the transaction is either committed or
30+ * aborted and there are no other concurrently executing transactions that
31+ * started before the commit timestamp. This mechanism is designed to provide a
32+ * "snapshot" view of the Accumulator that is consistent with the snapshot view
33+ * of the database.
34 * </p>
35 * <p>
36- * In more detail: the {@link #update} method of an Accumulator is invoked
37- * within the scope of a transaction T. That update is not visible to any other
38- * transaction until T commits. Moreover, any other concurrently executing
39- * transaction having a start timestamp less than T's commit timestamp does not
40- * see the results of the update. To accomplish this, the state of the
41+ * In more detail: each type of Accumulator has an update method that may only
42+ * be invoked within the scope of a transaction T. That update is not visible to
43+ * any other transaction until T commits. Moreover, any other concurrently
44+ * executing transaction having a start timestamp less than T's commit timestamp
45+ * does not see the results of the update. To accomplish this, the state of the
46 * Accumulator visible within a transaction is computed by determining which
47 * updates are visible and aggregating them on demand.
48 * </p>
49@@ -55,32 +56,49 @@
50 * containing the Tree.
51 * </p>
52 * <p>
53+ * <h3>Types of Accumulators</h3>
54 * The following defines intended use cases for the various types of
55 * accumulators:
56 * <dl>
57- * <dt>SUM</dt>
58+ * <dt>{@link com.persistit.Accumulator.Type#SUM}</dt>
59 * <dd>Row count, total size, sums of various other characteristics</dd>
60- * <dt>MAX</dt>
61+ * <dt>{@link com.persistit.Accumulator.Type#MAX}</dt>
62 * <dd>Maximum value</dd>
63- * <dt>MIN</dt>
64+ * <dt>{@link com.persistit.Accumulator.Type#MIN}</dt>
65 * <dd>Minimum value</dd>
66- * <dt>SEQ</dt>
67+ * <dt>{@link com.persistit.Accumulator.Type#SEQ}</dt>
68 * <dd>Sequence number generation, e.g., auto-increment or internal primary key
69- * assignment
70+ * assignment</dd>
71 * </dl>
72 * </p>
73 * <p>
74+ * <a name="_SnapshotValue" />
75+ * <h3>Snapshot and Live Values</h3>
76+ * Each Accumulator type supplies both a "snapshot" value and a "live" value.
77+ * The snapshot value is computed as described above by selectively applying
78+ * only those updates visible to the transaction. The live value, however, is
79+ * simply the result of applying each update operation atomically to a long
80+ * value maintained by the Accumulator. For example, if ten transactions
81+ * increment a SUM accumulator by one, and then five commit of them and five and
82+ * roll back, the live value is nonetheless increased by ten. Thus the live
83+ * value is only an estimate. Its value is cheap to acquire but not
84+ * transactionally accurate.
85+ * </p>
86+ * <p>
87+ * <a name="_SeqAccumulator" />
88+ * <h3>SeqAccumulator</h3>
89 * The <code>SeqAccumulator</code> is a combination of
90 * <code>SumAccumulator</code> and <code>MaxAccumulator</code>. When the
91- * {@link #update} method is called, the supplied long value is atomically added
92- * to the Accumulator's <code>live</code> value and the result is returned. In
93- * addition, a <code>Delta</code> holding the resulting sum as a proposed
94- * maximum value is added to the transaction. These semantics guarantee that
95- * every value returned by a SeqAccumulator is unique, and that upon recovery
96- * after a crash, the first value returned will be larger than the maximum value
97- * assigned by any transaction that committed successfully before the crash.
98- * Note that a transaction that assigns value and then aborts will leave a gap
99- * in the numerical sequence.
100+ * {@link com.persistit.Accumulator.SeqAccumulator#allocate()} method is called,
101+ * the Accumulator's <code>live</code> value is atomically incremented and the
102+ * resulting value is returned. In addition, a <code>Delta</code> holding the
103+ * resulting sum as a proposed minimum value is added to the transaction. These
104+ * semantics guarantee that every value returned by a SeqAccumulator (within a
105+ * transaction that actually commits) is unique, and that upon recovery after a
106+ * normal shutdown or crash, the first value returned will be larger than the
107+ * maximum value assigned by any transaction that committed successfully before
108+ * the shutdown. Note that a transaction that allocates a value and then aborts
109+ * leaves a gap in the numerical sequence.
110 * </p>
111 *
112 * @author peter
113@@ -114,7 +132,7 @@
114
115 final static int MAX_SERIALIZED_SIZE = Tree.MAX_SERIALIZED_SIZE + 24;
116
117- private final Tree _tree;
118+ protected final Tree _tree;
119 private final int _index;
120 private final TransactionIndex _transactionIndex;
121
122@@ -158,7 +176,7 @@
123 /**
124 * An Accumulator that computes a sum
125 */
126- final static class SumAccumulator extends Accumulator {
127+ public final static class SumAccumulator extends Accumulator {
128
129 private SumAccumulator(final Tree tree, final int index, final long baseValue,
130 final TransactionIndex transactionIndex) {
131@@ -172,6 +190,9 @@
132
133 @Override
134 long updateValue(final long a, final long b) {
135+ if (b > 0 && a + b < a || b < 0 && a + b > a) {
136+ throw new IllegalArgumentException("Accumulator value overflow: (" + a + "+" + b + ")");
137+ }
138 return applyValue(a, b);
139 }
140
141@@ -184,12 +205,31 @@
142 Type getType() {
143 return Type.SUM;
144 }
145+
146+ /**
147+ * <p>
148+ * Add the supplied value to this <code>SumAccumulator</code>. The
149+ * contribution is immediately accumulated into the live value, and it
150+ * is also posted with a <code>Delta</code>instance to the supplied
151+ * {@link Transaction}. This method may be called only within the scope
152+ * of an active <code>Transaction</code>.
153+ * </p>
154+ *
155+ * @param value
156+ * The delta value
157+ */
158+ public void add(final long value) {
159+ final Transaction txn = _tree.getPersistit().getTransaction();
160+ txn.checkActive();
161+ update(value, txn.getTransactionStatus(), txn.getStep());
162+ }
163+
164 }
165
166 /**
167 * An Accumulator that computes a minimum value
168 */
169- final static class MinAccumulator extends Accumulator {
170+ public final static class MinAccumulator extends Accumulator {
171
172 private MinAccumulator(final Tree tree, final int index, final long baseValue,
173 final TransactionIndex transactionIndex) {
174@@ -215,12 +255,31 @@
175 Type getType() {
176 return Type.MIN;
177 }
178+
179+ /**
180+ * <p>
181+ * Modify the Accumulator so that its value is no less than the supplied
182+ * value. The contribution is immediately accumulated into the live
183+ * value, and it is also posted with a <code>Delta</code> instance to
184+ * the supplied {@link Transaction}. This method may be called only
185+ * within the scope of an active <code>Transaction</code>.
186+ * </p>
187+ *
188+ * @param min
189+ * The candidate minimum value
190+ */
191+ public void minimum(final long min) {
192+ final Transaction txn = _tree.getPersistit().getTransaction();
193+ txn.checkActive();
194+ update(min, txn.getTransactionStatus(), txn.getStep());
195+ }
196+
197 }
198
199 /**
200 * An Accumulator that computes a maximum value
201 */
202- final static class MaxAccumulator extends Accumulator {
203+ public final static class MaxAccumulator extends Accumulator {
204
205 private MaxAccumulator(final Tree tree, final int index, final long baseValue,
206 final TransactionIndex transactionIndex) {
207@@ -246,18 +305,37 @@
208 Type getType() {
209 return Type.MAX;
210 }
211+
212+ /**
213+ * <p>
214+ * Modify the Accumulator so that its value is no greater than the
215+ * supplied value. The contribution is immediately accumulated into the
216+ * live value, and it is also posted with a <code>Delta</code> instance
217+ * to the supplied {@link Transaction}. This method may be called only
218+ * within the scope of an active <code>Transaction</code>.
219+ * </p>
220+ *
221+ * @param max
222+ * The candidate maximum value
223+ */
224+ public void maximum(final long max) {
225+ final Transaction txn = _tree.getPersistit().getTransaction();
226+ txn.checkActive();
227+ update(max, txn.getTransactionStatus(), txn.getStep());
228+ }
229+
230 }
231
232 /**
233 * An Accumulator used to generate unique ID values. The
234- * {@link #update(long, Transaction)} method applied to a
235- * <code>SeqAccumulator</code> generates a new, unique long value. The
236- * transaction records this value as a candidate for maximum value of the
237- * Accumulator. On recovery, the highest such value ever allocated by a
238- * committed transaction is recovered, and so after recovery the next
239- * allocated ID value will be larger than any previously consumed.
240+ * {@link com.persistit.Accumulator.SeqAccumulator#allocate()} method
241+ * generates a new, unique long value. The transaction records this value as
242+ * a candidate for maximum value of the Accumulator. On recovery, the
243+ * highest such value ever allocated by a committed transaction is
244+ * recovered, and so after recovery the next allocated ID value will be
245+ * larger than any previously consumed.
246 */
247- final static class SeqAccumulator extends Accumulator {
248+ public final static class SeqAccumulator extends Accumulator {
249
250 private SeqAccumulator(final Tree tree, final int index, final long baseValue,
251 final TransactionIndex transactionIndex) {
252@@ -271,11 +349,13 @@
253
254 @Override
255 long updateValue(final long a, final long b) {
256- if (b > 0) {
257- return a + b;
258- } else {
259+ if (b <= 0) {
260 throw new IllegalArgumentException("Update value must be positive");
261 }
262+ if (a + b < a) {
263+ throw new IllegalArgumentException("Accumulator value overflow: (" + a + "+" + b + ")");
264+ }
265+ return a + b;
266 }
267
268 @Override
269@@ -287,6 +367,32 @@
270 Type getType() {
271 return Type.SEQ;
272 }
273+
274+ /**
275+ * <p>
276+ * Allocate a sequence number. The value returned is guaranteed to be
277+ * unique for the lifetime of the database. Values are usually assigned
278+ * as consecutive integers, but in some cases there may be gaps in the
279+ * sequence.
280+ * </p>
281+ * <p>
282+ * The value returned is equal to the <a href="#_SnapshotValue">live
283+ * value</a> the instant it is updated. However, note that the following
284+ * code is <em>not</em> guaranteed to generate a unique value:
285+ * <code><pre>
286+ * seqAccumulator.allocate();
287+ * long id = seqAccumulator.getLiveValue();
288+ * </pre></code>while the following is: <code><pre>
289+ * long id = seqAccumulator.allocate();
290+ * </p>
291+ *
292+ * @return the updated live value
293+ */
294+ public long allocate() {
295+ final Transaction txn = _tree.getPersistit().getTransaction();
296+ return update(1, txn.getTransactionStatus(), txn.getStep());
297+ }
298+
299 }
300
301 final static class Delta {
302@@ -528,7 +634,8 @@
303
304 /**
305 * Non-transactional view aggregating all updates applied to this
306- * Accumulator, whether committed or not.
307+ * Accumulator, whether committed or not. See <a
308+ * href="#_SnapshotValue">Snapshot and Live Values</a>.
309 *
310 * @return the live value
311 */
312@@ -537,17 +644,18 @@
313 }
314
315 /**
316- * @param txn
317- * The transaction reading the snapshot
318- * @return The value computed by accumulating values contributed by (a) all
319- * transactions having commit timestamps less than or equal to
320- * <code>transaction</code>'s start timestamp, and (b) all
321- * operations performed by the current transaction having step
322- * numbers equal to or less than the <code>transaction</code>'s
323- * current step.
324+ * Compute the value computed by accumulating values contributed by (a) all
325+ * transactions having commit timestamps less than or equal to the specified
326+ * <code>transaction</code>'s start timestamp, and (b) all operations
327+ * performed by the specified transaction having step numbers equal to or
328+ * less than the <code>transaction</code>'s current step. See <a
329+ * href="#_SnapshotValue">Snapshot and Live Values</a>.
330+ *
331+ * @return the computed snapshot value
332 * @throws InterruptedException
333 */
334- public long getSnapshotValue(final Transaction txn) throws PersistitInterruptedException {
335+ public long getSnapshotValue() throws PersistitInterruptedException {
336+ final Transaction txn = _tree.getPersistit().getTransaction();
337 txn.checkActive();
338 return getSnapshotValue(txn.getStartTimestamp(), txn.getStep());
339 }
340@@ -592,25 +700,7 @@
341 /**
342 * Update the Accumulator by contributing a value. The contribution is
343 * immediately accumulated into the live value, and it is also posted with a
344- * <code>Delta</code>instance to the supplied {@link Transaction}. This
345- * method may be called only within the scope of an active
346- * <code>Transaction</code>.
347- *
348- * @param value
349- * The delta value
350- * @param txn
351- * The transaction it applies to
352- */
353- public long update(final long value, final Transaction txn) {
354- txn.checkActive();
355- return update(value, txn.getTransactionStatus(), txn.getStep());
356- }
357-
358- /**
359- * Update the Accumulator by contributing a value. The contribution is
360- * immediately accumulated into the live value, and it is also posted with a
361- *
362- * @{link {@link Delta} instance to the supplied {@link Transaction}.
363+ * {@link Delta} instance to the supplied {@link Transaction}.
364 *
365 * @param value
366 * The delta value
367
368=== modified file 'src/main/java/com/persistit/SessionId.java'
369--- src/main/java/com/persistit/SessionId.java 2012-10-05 14:20:09 +0000
370+++ src/main/java/com/persistit/SessionId.java 2013-04-11 15:33:26 +0000
371@@ -19,12 +19,14 @@
372 import java.util.concurrent.atomic.AtomicReference;
373
374 /**
375+ * <p>
376 * Identity key for a session. Normally there is one session per thread, but
377 * applications that need to maintain session context across multiple network
378 * requests serviced on different threads can access and carefully modify their
379 * session contexts using SessionID. See {@link Persistit#getSessionId()} and
380 * {@link Persistit#setSessionId(SessionId)}.
381- * <p />
382+ * </p>
383+ * <p>
384 * A SessionId instance holds a reference to the <code>Thread</code> currently
385 * associated with it; initially this this the thread that created the
386 * SessionId. The <code>setSessionId</code> method reassigns the thread field.
387@@ -32,6 +34,15 @@
388 * alive. The {@link Persistit#cleanup()} method cleans up all transaction
389 * resources for <code>SessionId</code> instances whose threads are no longer
390 * alive.
391+ * </p>
392+ * <p>
393+ * A session is used to maintain state, including the {@link Transaction}
394+ * context and map of cached {@link Exchange} maintained by
395+ * {@link Persistit#getExchange(String, String, boolean)}. Therefore care must
396+ * be taken to limit the maximum number of <code>SessionId</code> instances
397+ * created during the lifetime of a <code>Persistit</code> instance and to
398+ * manage them appropriately.
399+ * </p>
400 *
401 * @author peter
402 *
403@@ -44,7 +55,7 @@
404
405 private final AtomicReference<Thread> _owner = new AtomicReference<Thread>();
406
407- SessionId() {
408+ public SessionId() {
409 assign();
410 }
411
412
413=== modified file 'src/main/java/com/persistit/SharedResource.java'
414--- src/main/java/com/persistit/SharedResource.java 2013-01-24 18:19:19 +0000
415+++ src/main/java/com/persistit/SharedResource.java 2013-04-11 15:33:26 +0000
416@@ -398,10 +398,14 @@
417 _generation.incrementAndGet();
418 }
419
420- public int getStatus() {
421+ int getStatus() {
422 return _sync.state();
423 }
424
425+ Persistit getPersistit() {
426+ return _persistit;
427+ }
428+
429 /**
430 * Sets bits in the state. This method does not change the bits used by the
431 * synchronizer to maintain lock state.
432
433=== modified file 'src/main/java/com/persistit/Tree.java'
434--- src/main/java/com/persistit/Tree.java 2013-03-13 16:27:04 +0000
435+++ src/main/java/com/persistit/Tree.java 2013-04-11 15:33:26 +0000
436@@ -19,6 +19,10 @@
437 import java.util.concurrent.atomic.AtomicLong;
438 import java.util.concurrent.atomic.AtomicReference;
439
440+import com.persistit.Accumulator.MaxAccumulator;
441+import com.persistit.Accumulator.MinAccumulator;
442+import com.persistit.Accumulator.SeqAccumulator;
443+import com.persistit.Accumulator.SumAccumulator;
444 import com.persistit.exception.CorruptVolumeException;
445 import com.persistit.exception.PersistitException;
446 import com.persistit.util.Debug;
447@@ -285,23 +289,111 @@
448 }
449
450 /**
451+ * Return a <code>SumAccumulator</code> for this <code>Tree</code> and the
452+ * specified index value between 0 and 63, inclusive. If the
453+ * <code>Tree</code> does not yet have an <code>Accumulator</code> with the
454+ * specified index, this method creates one. Otherwise the previously
455+ * created <code>Accumulator</code>, which must be a
456+ * <code>SumAccumulator</code>, is returned.
457+ *
458+ * @param index
459+ * Application-controlled value between 0 and 63, inclusive.
460+ * @return The <code>Accumulator</code>
461+ * @throws IllegalStateException
462+ * if the previously created instance is not a
463+ * <code>SumAccumulator</code>
464+ */
465+ public SumAccumulator getSumAccumulator(final int index) throws PersistitException {
466+ return (SumAccumulator) getAccumulator(Accumulator.Type.SUM, index);
467+ }
468+
469+ /**
470+ * Return a <code>SeqAccumulator</code> for this <code>Tree</code> and the
471+ * specified index value between 0 and 63, inclusive. If the
472+ * <code>Tree</code> does not yet have an <code>Accumulator</code> with the
473+ * specified index, this method creates one. Otherwise the previously
474+ * created <code>Accumulator</code>, which must be a
475+ * <code>SeqAccumulator</code>, is returned.
476+ *
477+ * @param index
478+ * Application-controlled value between 0 and 63, inclusive.
479+ * @return The <code>Accumulator</code>
480+ * @throws IllegalStateException
481+ * if the previously created instance is not a
482+ * <code>SeqAccumulator</code>
483+ */
484+ public SeqAccumulator getSeqAccumulator(final int index) throws PersistitException {
485+ return (SeqAccumulator) getAccumulator(Accumulator.Type.SEQ, index);
486+ }
487+
488+ /**
489+ * Return a <code>MinAccumulator</code> for this <code>Tree</code> and the
490+ * specified index value between 0 and 63, inclusive. If the
491+ * <code>Tree</code> does not yet have an <code>Accumulator</code> with the
492+ * specified index, this method creates one. Otherwise the previously
493+ * created <code>Accumulator</code>, which must be a
494+ * <code>MinAccumulator</code>, is returned.
495+ *
496+ * @param index
497+ * Application-controlled value between 0 and 63, inclusive.
498+ * @return The <code>Accumulator</code>
499+ * @throws IllegalStateException
500+ * if the previously created instance is not a
501+ * <code>MinAccumulator</code>
502+ */
503+ public MinAccumulator getMinAccumulator(final int index) throws PersistitException {
504+ return (MinAccumulator) getAccumulator(Accumulator.Type.MIN, index);
505+ }
506+
507+ /**
508+ * Return a <code>MaxAccumulator</code> for this <code>Tree</code> and the
509+ * specified index value between 0 and 63, inclusive. If the
510+ * <code>Tree</code> does not yet have an <code>Accumulator</code> with the
511+ * specified index, this method creates one. Otherwise the previously
512+ * created <code>Accumulator</code>, which must be a
513+ * <code>MaxAccumulator</code>, is returned.
514+ *
515+ * @param index
516+ * Application-controlled value between 0 and 63, inclusive.
517+ * @return The <code>Accumulator</code>
518+ * @throws IllegalStateException
519+ * if the previously created instance is not a
520+ * <code>MaxAccumulator</code>
521+ */
522+ public MaxAccumulator getMaxAccumulator(final int index) throws PersistitException {
523+ return (MaxAccumulator) getAccumulator(Accumulator.Type.MAX, index);
524+ }
525+
526+ /**
527+ * <p>
528 * Return an <code>Accumulator</code> for this Tree. The caller provides the
529 * type (SUM, MAX, MIN or SEQ) of accumulator, and an index value between 0
530 * and 63, inclusive. If the <code>Tree</code> does not yet have an
531 * <code>Accumulator</code> with the specified index, this method creates
532 * one of the the specified type. Otherwise the specified type must match
533 * the type of the one previously.
534+ * </p>
535+ * <p>
536+ * This method is deprecated. One of the following methods should be used
537+ * instead:
538+ * <ul>
539+ * <li>{@link #getSumAccumulator(int)}</li>
540+ * <li>{@link #getSeqAccumulator(int)}</li>
541+ * <li>{@link #getMinAccumulator(int)}</li>
542+ * <li>{@link #getMaxAccumulator(int)}</li>
543+ * <ul>
544+ * </p>
545 *
546 * @param type
547 * Type of <code>Accumulator</code>
548 * @param index
549 * Application-controlled value between 0 and 63, inclusive.
550+ * @return The <code>Accumulator</code>
551 * @throws IllegalStateException
552 * if the supplied type does not match that of a previously
553 * created <code>Accumulator</code>
554 */
555- public synchronized Accumulator getAccumulator(final Accumulator.Type type, final int index)
556- throws PersistitException {
557+ synchronized Accumulator getAccumulator(final Accumulator.Type type, final int index) throws PersistitException {
558 if (index < 0 || index >= MAX_ACCUMULATOR_COUNT) {
559 throw new IllegalArgumentException("Invalid accumulator index: " + index);
560 }
561
562=== modified file 'src/test/java/com/persistit/AccumulatorRecoveryTest.java'
563--- src/test/java/com/persistit/AccumulatorRecoveryTest.java 2012-11-20 17:45:51 +0000
564+++ src/test/java/com/persistit/AccumulatorRecoveryTest.java 2013-04-11 15:33:26 +0000
565@@ -28,6 +28,7 @@
566
567 import org.junit.Test;
568
569+import com.persistit.Accumulator.SumAccumulator;
570 import com.persistit.TransactionPlayer.TransactionPlayerListener;
571 import com.persistit.exception.PersistitException;
572 import com.persistit.exception.RollbackException;
573@@ -55,7 +56,7 @@
574 public void testRecoverCommittedTransactions() throws Exception {
575 _persistit.getJournalManager().setAppendOnly(true);
576 final Exchange ex = _persistit.getExchange("persistit", "RecoveryTest", true);
577- final Accumulator rowCount = ex.getTree().getAccumulator(Accumulator.Type.SUM, 0);
578+ final SumAccumulator rowCount = ex.getTree().getSumAccumulator(0);
579 for (int j = 0; j++ < 10;) {
580
581 final Transaction txn = ex.getTransaction();
582@@ -65,11 +66,11 @@
583 for (int i = 0; i < 10; i++) {
584 ex.getValue().put("String value #" + i + " for test1");
585 ex.clear().append("test1").append(j).append(i).store();
586- rowCount.update(1, txn);
587+ rowCount.add(1);
588 }
589 for (int i = 3; i < 10; i += 3) {
590 ex.clear().append("test1").append(j).append(i).remove(Key.GTEQ);
591- rowCount.update(-1, txn);
592+ rowCount.add(-1);
593 }
594 txn.commit();
595 } finally {
596@@ -83,7 +84,7 @@
597 try {
598 final boolean removed = ex.clear().append("test1").append(j).remove(Key.GTEQ);
599 if (removed) {
600- rowCount.update(-7, txn);
601+ rowCount.add(-7);
602 }
603 txn.commit();
604 } finally {
605@@ -263,7 +264,6 @@
606 final Exchange exchange = _persistit.getExchange("persistit", "AccumulatorRecoveryTest", true);
607 final Transaction txn = _persistit.getTransaction();
608 int count = 0;
609- Exception exception = null;
610 while (running.get() && count++ < max) {
611 final int key = random.nextInt(1000000);
612 final int op = random.nextInt(100);
613@@ -278,17 +278,17 @@
614 if (!exists) {
615 exchange.getValue().put(RED_FOX);
616 exchange.store();
617- final Accumulator rowCount = exchange.getTree().getAccumulator(Accumulator.Type.SUM,
618+ final SumAccumulator rowCount = exchange.getTree().getSumAccumulator(
619 ROW_COUNT_ACCUMULATOR_INDEX);
620- rowCount.update(1, txn);
621+ rowCount.add(1);
622 update = 1;
623 }
624 } else {
625 if (exists) {
626 exchange.remove();
627- final Accumulator rowCount = exchange.getTree().getAccumulator(Accumulator.Type.SUM,
628+ final SumAccumulator rowCount = exchange.getTree().getSumAccumulator(
629 ROW_COUNT_ACCUMULATOR_INDEX);
630- rowCount.update(-1, txn);
631+ rowCount.add(-1);
632 update = -1;
633 }
634 }
635@@ -299,9 +299,6 @@
636 retryCount++;
637 assertTrue(retryCount < 5);
638 System.out.println("(Acceptable) rollback in " + Thread.currentThread().getName());
639- } catch (final Exception e) {
640- exception = e;
641- throw e;
642 } finally {
643 txn.end();
644 }
645@@ -312,19 +309,18 @@
646 private long verifyRowCount() throws Exception {
647 final Exchange exchange = _persistit.getExchange("persistit", "AccumulatorRecoveryTest", false);
648 final Transaction txn = _persistit.getTransaction();
649- Exception exception = null;
650 txn.begin();
651 try {
652 final Accumulator rowCount = exchange.getTree().getAccumulator(Accumulator.Type.SUM,
653 ROW_COUNT_ACCUMULATOR_INDEX);
654- final long accumulated = rowCount.getSnapshotValue(txn);
655+ final long accumulated = rowCount.getSnapshotValue();
656 long counted = 0;
657 exchange.to(Key.BEFORE);
658 while (exchange.next()) {
659 counted++;
660 assertFalse(exchange.getValue().isAntiValue());
661 }
662- final long accumulated2 = rowCount.getSnapshotValue(txn);
663+ final long accumulated2 = rowCount.getSnapshotValue();
664 if (accumulated != counted || accumulated != accumulated2) {
665 synchronized (this) {
666 System.out.printf("%s accumulated=%,d accumulated2=%,d counted=%,d\n", Thread.currentThread()
667@@ -335,9 +331,6 @@
668 }
669 txn.commit();
670 return counted;
671- } catch (final Exception e) {
672- exception = e;
673- throw e;
674 } finally {
675 txn.end();
676 }
677
678=== modified file 'src/test/java/com/persistit/AccumulatorTest.java'
679--- src/test/java/com/persistit/AccumulatorTest.java 2012-08-30 16:19:35 +0000
680+++ src/test/java/com/persistit/AccumulatorTest.java 2013-04-11 15:33:26 +0000
681@@ -19,7 +19,6 @@
682 import static org.junit.Assert.assertNotNull;
683 import static org.junit.Assert.assertNull;
684 import static org.junit.Assert.assertTrue;
685-import static org.junit.Assert.fail;
686
687 import java.util.ArrayList;
688 import java.util.Arrays;
689@@ -29,8 +28,11 @@
690
691 import org.junit.Test;
692
693+import com.persistit.Accumulator.SeqAccumulator;
694+import com.persistit.Accumulator.SumAccumulator;
695 import com.persistit.Accumulator.Type;
696 import com.persistit.exception.PersistitException;
697+import com.persistit.exception.PersistitInterruptedException;
698 import com.persistit.exception.TimeoutException;
699 import com.persistit.unit.ConcurrentUtil;
700 import com.persistit.unit.UnitTestProperties;
701@@ -110,42 +112,46 @@
702 public void testBasicIsolation() throws Exception {
703 final SessionId s1 = new SessionId();
704 final SessionId s2 = new SessionId();
705- int expectedErrors = 0;
706 _persistit.setSessionId(s1);
707 final Transaction txn1 = _persistit.getTransaction();
708 _persistit.setSessionId(s2);
709 final Transaction txn2 = _persistit.getTransaction();
710 final Tree tree = _persistit.getVolume("persistit").getTree("AccumulatorTest", true);
711- final Accumulator acc = tree.getAccumulator(Accumulator.Type.SUM, 0);
712+ final SumAccumulator acc = tree.getSumAccumulator(0);
713 assertTrue(txn1 != txn2);
714 txn2.begin();
715- try {
716- acc.getSnapshotValue(txn1);
717- fail("Should have thrown an exceptio");
718- } catch (final IllegalStateException e) {
719- expectedErrors++;
720- // expected
721- }
722- assertEquals(1, expectedErrors);
723+
724 txn1.begin();
725- assertEquals(0, acc.getSnapshotValue(txn1));
726- assertEquals(0, acc.getSnapshotValue(txn2));
727- acc.update(1, txn1);
728- assertEquals(0, acc.getSnapshotValue(txn2));
729- acc.update(1, txn2);
730- assertEquals(1, acc.getSnapshotValue(txn1));
731- assertEquals(1, acc.getSnapshotValue(txn2));
732+ assertEquals(0, snapshotValue(acc, s1));
733+ assertEquals(0, snapshotValue(acc, s2));
734+
735+ increment(acc, s1);
736+ assertEquals(0, snapshotValue(acc, s2));
737+ increment(acc, s2);
738+ assertEquals(1, snapshotValue(acc, s1));
739+ assertEquals(1, snapshotValue(acc, s2));
740 txn1.commit();
741 txn1.end();
742- assertEquals(acc.getSnapshotValue(txn2), 1);
743+ assertEquals(1, snapshotValue(acc, s2));
744 txn2.commit();
745 txn2.end();
746 txn1.begin();
747- assertEquals(2, acc.getSnapshotValue(txn1));
748+ assertEquals(2, snapshotValue(acc, s1));
749 txn1.commit();
750 txn1.end();
751 }
752
753+ private void increment(final SumAccumulator acc, final SessionId sessionId) {
754+ _persistit.setSessionId(sessionId);
755+ acc.add(1);
756+ }
757+
758+ private long snapshotValue(final SumAccumulator acc, final SessionId sessionId)
759+ throws PersistitInterruptedException {
760+ _persistit.setSessionId(sessionId);
761+ return acc.getSnapshotValue();
762+ }
763+
764 @Test
765 public void testBasicIsolation2() throws Exception {
766 final Thread[] threads = new Thread[25];
767@@ -156,7 +162,7 @@
768 threads[i] = new Thread(new Runnable() {
769 @Override
770 public void run() {
771- final long end = System.currentTimeMillis() + 60000;
772+ final long end = System.currentTimeMillis() + 30000;
773 int cleanRun = 0;
774 while (System.currentTimeMillis() < end) {
775 try {
776@@ -164,16 +170,16 @@
777 final Transaction txn = ex.getTransaction();
778 txn.begin();
779 try {
780- final Accumulator acc = ex.getTree().getAccumulator(Accumulator.Type.SUM, 0);
781+ final SumAccumulator acc = ex.getTree().getSumAccumulator(0);
782 final long floor1 = ti.getActiveTransactionFloor();
783- final long v1 = acc.getSnapshotValue(txn);
784+ final long v1 = acc.getSnapshotValue();
785 Thread.sleep(random.nextInt(2));
786- final long v2 = acc.getSnapshotValue(txn);
787+ final long v2 = acc.getSnapshotValue();
788 final long floor2 = ti.getActiveTransactionFloor();
789- acc.update(1, txn);
790- final long v3 = acc.getSnapshotValue(txn);
791- final long v4 = acc.getSnapshotValue(txn);
792- final long v5 = acc.getSnapshotValue(txn);
793+ acc.add(1);
794+ final long v3 = acc.getSnapshotValue();
795+ final long v4 = acc.getSnapshotValue();
796+ final long v5 = acc.getSnapshotValue();
797
798 if (v1 != v2 || v2 + 1 != v3 || v3 != v4 || v4 != v5) {
799 System.out.printf("Thread #%d v1=%,10d v2=%,10d v3=%,10d v4=%,10d v5=%,10d "
800@@ -322,16 +328,16 @@
801 final Transaction txn = _persistit.getTransaction();
802 final String treeName = String.format("AccumulatorTest%2d", retry);
803 final Exchange exchange = _persistit.getExchange("persistit", treeName, true);
804- final Accumulator rowCount = exchange.getTree().getAccumulator(Type.SUM, 0);
805- final Accumulator sequence = exchange.getTree().getAccumulator(Type.SEQ, 1);
806+ final SumAccumulator rowCount = exchange.getTree().getSumAccumulator(0);
807+ final SeqAccumulator sequence = exchange.getTree().getSeqAccumulator(1);
808
809 for (int i = 0; i < count; i++) {
810 txn.begin();
811 try {
812- exchange.clear().append(sequence.update(17, txn));
813+ exchange.clear().append(sequence.allocate() * 17);
814 exchange.getValue().put(RED_FOX);
815 exchange.store();
816- rowCount.update(1, txn);
817+ rowCount.add(1);
818 txn.commit();
819 } finally {
820 txn.end();
821@@ -339,7 +345,7 @@
822 }
823
824 assertEquals(count, rowCount.getLiveValue());
825- assertEquals(count * 17, sequence.getLiveValue());
826+ assertEquals(count, sequence.getLiveValue());
827
828 _persistit.checkpoint();
829
830@@ -355,7 +361,7 @@
831 assertEquals(treeName, as.getTreeName());
832 assertEquals(Type.SEQ, as.getType());
833 assertEquals(1, as.getIndex());
834- assertEquals(count * 17, as.getValue());
835+ assertEquals(count, as.getValue());
836 }
837 }
838
839@@ -383,25 +389,25 @@
840 assertNull("Tree should not exist, pass" + pass, vol.getTree(TEST_TREE_NAME, false));
841
842 final Exchange ex = _persistit.getExchange(TEST_VOLUME_NAME, TEST_TREE_NAME, true);
843- final Accumulator accum = ex.getTree().getAccumulator(ACCUM_TYPE, ACCUM_INDEX);
844+ final SumAccumulator accum = ex.getTree().getSumAccumulator(ACCUM_INDEX);
845 final Transaction txn = _persistit.getTransaction();
846
847 txn.begin();
848- assertEquals("Initial accumulator value, pass" + pass, 0, accum.getSnapshotValue(txn));
849+ assertEquals("Initial accumulator value, pass" + pass, 0, accum.getSnapshotValue());
850 txn.commit();
851 txn.end();
852
853 for (int row = 0; row < ROW_COUNT; ++row) {
854 txn.begin();
855 ex.clear().append(row);
856- accum.update(1, txn);
857+ accum.add(1);
858 txn.commit();
859 txn.end();
860 }
861
862 txn.begin();
863 txn.commit();
864- assertEquals("Accumulator after inserts, pass" + pass, ROW_COUNT, accum.getSnapshotValue(txn));
865+ assertEquals("Accumulator after inserts, pass" + pass, ROW_COUNT, accum.getSnapshotValue());
866 txn.end();
867
868 ex.removeTree();
869
870=== modified file 'src/test/java/com/persistit/Bug1064565Test.java'
871--- src/test/java/com/persistit/Bug1064565Test.java 2012-11-20 17:45:51 +0000
872+++ src/test/java/com/persistit/Bug1064565Test.java 2013-04-11 15:33:26 +0000
873@@ -30,6 +30,7 @@
874
875 import org.junit.Test;
876
877+import com.persistit.Accumulator.SumAccumulator;
878 import com.persistit.exception.PersistitException;
879 import com.persistit.util.ThreadSequencer.Condition;
880
881@@ -84,8 +85,8 @@
882 t.start();
883
884 txn.begin();
885- Accumulator acc = exchange.getTree().getAccumulator(Accumulator.Type.SUM, 0);
886- acc.update(42, txn);
887+ SumAccumulator acc = exchange.getTree().getSumAccumulator(0);
888+ acc.add(42);
889 sequence(ACCUMULATOR_CHECKPOINT_B);
890 txn.commit();
891 txn.end();
892@@ -98,8 +99,8 @@
893 exchange = getExchange();
894 txn = exchange.getTransaction();
895 txn.begin();
896- acc = exchange.getTree().getAccumulator(Accumulator.Type.SUM, 0);
897- assertEquals("Accumulator state should have been checkpointed", 42, acc.getSnapshotValue(txn));
898+ acc = exchange.getTree().getSumAccumulator(0);
899+ assertEquals("Accumulator state should have been checkpointed", 42, acc.getSnapshotValue());
900 txn.commit();
901 txn.end();
902
903@@ -118,8 +119,8 @@
904 Exchange exchange = getExchange();
905 Transaction txn = exchange.getTransaction();
906 txn.begin();
907- Accumulator acc = exchange.getTree().getAccumulator(Accumulator.Type.SUM, 0);
908- acc.update(42, txn);
909+ SumAccumulator acc = exchange.getTree().getSumAccumulator(0);
910+ acc.add(42);
911 _persistit.checkpoint();
912 txn.commit();
913 txn.end();
914@@ -131,8 +132,8 @@
915 exchange = getExchange();
916 txn = exchange.getTransaction();
917 txn.begin();
918- acc = exchange.getTree().getAccumulator(Accumulator.Type.SUM, 0);
919- assertEquals("Accumulator state should have been checkpointed", 42, acc.getSnapshotValue(txn));
920+ acc = exchange.getTree().getSumAccumulator(0);
921+ assertEquals("Accumulator state should have been checkpointed", 42, acc.getSnapshotValue());
922 txn.commit();
923 txn.end();
924
925
926=== modified file 'src/test/java/com/persistit/Bug911849Test.java'
927--- src/test/java/com/persistit/Bug911849Test.java 2012-11-25 20:14:58 +0000
928+++ src/test/java/com/persistit/Bug911849Test.java 2013-04-11 15:33:26 +0000
929@@ -23,6 +23,7 @@
930
931 import org.junit.Test;
932
933+import com.persistit.Accumulator.SumAccumulator;
934 import com.persistit.exception.RollbackException;
935
936 /**
937@@ -82,14 +83,12 @@
938 final Exchange exchange = _persistit.getExchange("persistit", "AccumulatorRecoveryTest", true);
939 final Transaction txn = _persistit.getTransaction();
940 int count = 0;
941- Exception exception = null;
942 while (count++ < max) {
943 int retryCount = 0;
944 txn.begin();
945 try {
946- final Accumulator rowCount = exchange.getTree().getAccumulator(Accumulator.Type.SUM,
947- ROW_COUNT_ACCUMULATOR_INDEX);
948- rowCount.update(1, txn);
949+ final SumAccumulator rowCount = exchange.getTree().getSumAccumulator(ROW_COUNT_ACCUMULATOR_INDEX);
950+ rowCount.add(1);
951 txn.commit();
952 counter.incrementAndGet();
953 if ((count % 10) == 0) {
954@@ -99,9 +98,6 @@
955 retryCount++;
956 assertTrue(retryCount < 5);
957 System.out.println("(Acceptable) rollback in " + Thread.currentThread().getName());
958- } catch (final Exception e) {
959- exception = e;
960- throw e;
961 } finally {
962 txn.end();
963 }
964
965=== modified file 'src/test/java/com/persistit/Bug920754Test.java'
966--- src/test/java/com/persistit/Bug920754Test.java 2012-08-24 13:57:19 +0000
967+++ src/test/java/com/persistit/Bug920754Test.java 2013-04-11 15:33:26 +0000
968@@ -19,6 +19,8 @@
969
970 import org.junit.Test;
971
972+import com.persistit.Accumulator.SumAccumulator;
973+
974 public class Bug920754Test extends PersistitUnitTestCase {
975 /*
976 * https://bugs.launchpad.net/akiban-persistit/+bug/920754
977@@ -48,13 +50,13 @@
978 public void testAccumumulatorTreeIsDeleted() throws Exception {
979 final Exchange exchange = _persistit.getExchange("persistit", "Bug920754Test", true);
980 final Transaction txn = _persistit.getTransaction();
981- final Accumulator[] accumulators = new Accumulator[10];
982+ final SumAccumulator[] accumulators = new SumAccumulator[10];
983 for (int i = 0; i < 10; i++) {
984- accumulators[i] = exchange.getTree().getAccumulator(Accumulator.Type.SUM, 1);
985+ accumulators[i] = exchange.getTree().getSumAccumulator(1);
986 }
987 txn.begin();
988 for (int i = 0; i < 10; i++) {
989- accumulators[i].update(1, txn);
990+ accumulators[i].add(1);
991 }
992 txn.commit();
993 txn.end();
994
995=== modified file 'src/test/java/com/persistit/Bug974589Test.java'
996--- src/test/java/com/persistit/Bug974589Test.java 2012-11-20 17:45:51 +0000
997+++ src/test/java/com/persistit/Bug974589Test.java 2013-04-11 15:33:26 +0000
998@@ -19,6 +19,7 @@
999
1000 import org.junit.Test;
1001
1002+import com.persistit.Accumulator.SumAccumulator;
1003 import com.persistit.exception.PersistitException;
1004 import com.persistit.unit.UnitTestProperties;
1005
1006@@ -47,8 +48,8 @@
1007 * Touch an Accumulator, then immediately checkpoint.
1008 */
1009 txn1.begin();
1010- Accumulator acc1 = ex1.getTree().getAccumulator(Accumulator.Type.SUM, 1);
1011- acc1.update(1, txn1);
1012+ SumAccumulator acc1 = ex1.getTree().getSumAccumulator(1);
1013+ acc1.add(1);
1014 txn1.commit();
1015 txn1.end();
1016 ex1 = null;
1017@@ -63,8 +64,8 @@
1018 Exchange ex2 = getExchange(_persistit);
1019 Transaction txn2 = ex2.getTransaction();
1020 txn2.begin();
1021- Accumulator acc2 = ex2.getTree().getAccumulator(Accumulator.Type.SUM, 1);
1022- assertEquals(loop, acc2.getSnapshotValue(txn2));
1023+ SumAccumulator acc2 = ex2.getTree().getSumAccumulator(1);
1024+ assertEquals(loop, acc2.getSnapshotValue());
1025 txn2.commit();
1026 txn2.end();
1027 System.out.printf("Iteration %,d completed\n", loop);
1028
1029=== modified file 'src/test/java/com/persistit/JournalManagerTest.java'
1030--- src/test/java/com/persistit/JournalManagerTest.java 2012-11-25 20:14:58 +0000
1031+++ src/test/java/com/persistit/JournalManagerTest.java 2013-04-11 15:33:26 +0000
1032@@ -41,6 +41,7 @@
1033
1034 import org.junit.Test;
1035
1036+import com.persistit.Accumulator.SumAccumulator;
1037 import com.persistit.CheckpointManager.Checkpoint;
1038 import com.persistit.JournalManager.PageNode;
1039 import com.persistit.TransactionPlayer.TransactionPlayerListener;
1040@@ -375,14 +376,13 @@
1041 public void testTransactionMapSpanningJournalWriteBuffer() throws Exception {
1042 _persistit.getJournalManager().setWriteBufferSize(JournalManager.MINIMUM_BUFFER_SIZE);
1043 final Transaction txn = _persistit.getTransaction();
1044- Accumulator acc = _persistit.getVolume("persistit").getTree("JournalManagerTest", true)
1045- .getAccumulator(Accumulator.Type.SUM, 0);
1046+ SumAccumulator acc = _persistit.getVolume("persistit").getTree("JournalManagerTest", true).getSumAccumulator(0);
1047 /*
1048 * Load up a sizable live transaction map
1049 */
1050 for (int i = 0; i < 25000; i++) {
1051 txn.begin();
1052- acc.update(1, txn);
1053+ acc.add(1);
1054 txn.commit();
1055 txn.end();
1056 }
1057@@ -390,8 +390,7 @@
1058 _persistit.close();
1059 _persistit = new Persistit(_config);
1060
1061- acc = _persistit.getVolume("persistit").getTree("JournalManagerTest", true)
1062- .getAccumulator(Accumulator.Type.SUM, 0);
1063+ acc = _persistit.getVolume("persistit").getTree("JournalManagerTest", true).getSumAccumulator(0);
1064 assertEquals("Accumulator value is incorrect", 25000, acc.getLiveValue());
1065
1066 }
1067@@ -561,13 +560,13 @@
1068 for (long curSize = 0; curSize < JournalManager.ROLLOVER_THRESHOLD;) {
1069 final Exchange ex = _persistit.getExchange(UnitTestProperties.VOLUME_NAME, "JournalManagerTest", true);
1070 final Transaction txn = _persistit.getTransaction();
1071- final Accumulator accum = ex.getTree().getAccumulator(Accumulator.Type.SUM, 0);
1072+ final SumAccumulator accum = ex.getTree().getSumAccumulator(0);
1073 txn.begin();
1074 for (int j = 0; j < BATCH_SIZE; ++j) {
1075 ex.clear().append(total + j);
1076 ex.getValue().put(j);
1077 ex.store();
1078- accum.update(1, txn);
1079+ accum.add(1);
1080 }
1081 txn.commit();
1082 txn.end();
1083
1084=== modified file 'src/test/java/com/persistit/stress/unit/AccumulatorRestart.java'
1085--- src/test/java/com/persistit/stress/unit/AccumulatorRestart.java 2012-11-28 17:15:48 +0000
1086+++ src/test/java/com/persistit/stress/unit/AccumulatorRestart.java 2013-04-11 15:33:26 +0000
1087@@ -17,7 +17,10 @@
1088
1089 import java.util.Random;
1090
1091-import com.persistit.Accumulator;
1092+import com.persistit.Accumulator.MaxAccumulator;
1093+import com.persistit.Accumulator.MinAccumulator;
1094+import com.persistit.Accumulator.SeqAccumulator;
1095+import com.persistit.Accumulator.SumAccumulator;
1096 import com.persistit.Configuration;
1097 import com.persistit.Exchange;
1098 import com.persistit.Persistit;
1099@@ -74,18 +77,18 @@
1100 final boolean a = RANDOM.nextInt(10) == 0;
1101 System.out.println(_threadName + " starting cycle " + _count + " abort=" + a);
1102 _ex = getPersistit().getExchange("persistit", _rootName + _threadIndex, true);
1103- final Accumulator sum = _ex.getTree().getAccumulator(Accumulator.Type.SUM, 17);
1104- final Accumulator max = _ex.getTree().getAccumulator(Accumulator.Type.MAX, 22);
1105- final Accumulator min = _ex.getTree().getAccumulator(Accumulator.Type.MIN, 23);
1106- final Accumulator seq = _ex.getTree().getAccumulator(Accumulator.Type.SEQ, 47);
1107+ final SumAccumulator sum = _ex.getTree().getSumAccumulator(17);
1108+ final MaxAccumulator max = _ex.getTree().getMaxAccumulator(22);
1109+ final MinAccumulator min = _ex.getTree().getMinAccumulator(23);
1110+ final SeqAccumulator seq = _ex.getTree().getSeqAccumulator(47);
1111 final Transaction txn = _ex.getTransaction();
1112 if (_count > 1) {
1113 txn.begin();
1114 try {
1115- final long minv = min.getSnapshotValue(txn);
1116- final long maxv = max.getSnapshotValue(txn);
1117+ final long minv = min.getSnapshotValue();
1118+ final long maxv = max.getSnapshotValue();
1119 final long seqv = seq.getLiveValue();
1120- final long sumv = sum.getSnapshotValue(txn);
1121+ final long sumv = sum.getSnapshotValue();
1122 if (minv != minValue || maxv != maxValue || seqv != seqValue || sumv != sumValue) {
1123 fail(String.format("Values don't match: (min/max/seq/sum) "
1124 + "expected=(%,d/%,d/%,d/%,d) actual=(%,d/%,d/%,d/%,d)", minValue, maxValue,
1125@@ -101,10 +104,10 @@
1126 final long timeOffset = RANDOM.nextInt(1000) - 500;
1127 while (!isTriggered(timeOffset)) {
1128 final long r = RANDOM.nextInt(1000) - 500;
1129- min.update(bsum(minValue, r), txn);
1130- max.update(bsum(maxValue, r), txn);
1131- seq.update(1, txn);
1132- sum.update(r, txn);
1133+ min.minimum(bsum(minValue, r));
1134+ max.maximum(bsum(maxValue, r));
1135+ seq.allocate();
1136+ sum.add(1);
1137 seqValue++;
1138 final long minWas = getLong(_ex.to("min"), Long.MAX_VALUE);
1139 _ex.getValue().put(Math.min(bsum(minValue, r), minWas));
1140
1141=== modified file 'src/test/java/com/persistit/stress/unit/Stress8txn.java'
1142--- src/test/java/com/persistit/stress/unit/Stress8txn.java 2012-11-23 19:40:49 +0000
1143+++ src/test/java/com/persistit/stress/unit/Stress8txn.java 2013-04-11 15:33:26 +0000
1144@@ -15,7 +15,7 @@
1145
1146 package com.persistit.stress.unit;
1147
1148-import com.persistit.Accumulator;
1149+import com.persistit.Accumulator.SumAccumulator;
1150 import com.persistit.Exchange;
1151 import com.persistit.Key;
1152 import com.persistit.Transaction;
1153@@ -199,10 +199,10 @@
1154
1155 }
1156
1157- final Accumulator acc1 = _exs.getTree().getAccumulator(Accumulator.Type.SUM, _c1);
1158- final Accumulator acc2 = _exs.getTree().getAccumulator(Accumulator.Type.SUM, _c2);
1159- acc1.update(delta, _exs.getTransaction());
1160- acc2.update(-delta, _exs.getTransaction());
1161+ final SumAccumulator acc1 = _exs.getTree().getSumAccumulator(_c1);
1162+ final SumAccumulator acc2 = _exs.getTree().getSumAccumulator(_c2);
1163+ acc1.add(delta);
1164+ acc2.add(-delta);
1165 }
1166 }
1167
1168@@ -252,10 +252,10 @@
1169 addWork(1);
1170
1171 }
1172- final Accumulator acc1 = _exs.getTree().getAccumulator(Accumulator.Type.SUM, _c1);
1173- final Accumulator acc2 = _exs.getTree().getAccumulator(Accumulator.Type.SUM, _c2);
1174- acc1.update(delta, _exs.getTransaction());
1175- acc2.update(-delta, _exs.getTransaction());
1176+ final SumAccumulator acc1 = _exs.getTree().getSumAccumulator(_c1);
1177+ final SumAccumulator acc2 = _exs.getTree().getSumAccumulator(_c2);
1178+ acc1.add(delta);
1179+ acc2.add(-delta);
1180 }
1181 }
1182
1183@@ -410,8 +410,8 @@
1184 }
1185 int totalAcc = 0;
1186 for (int i = 0; i < 25; i++) {
1187- final Accumulator acc = _exs.getTree().getAccumulator(Accumulator.Type.SUM, i);
1188- totalAcc += acc.getSnapshotValue(_exs.getTransaction());
1189+ final SumAccumulator acc = _exs.getTree().getSumAccumulator(i);
1190+ totalAcc += acc.getSnapshotValue();
1191 }
1192 if (totalAcc != 0) {
1193 fail("totalAcc=" + totalAcc);

Subscribers

People subscribed via source and target branches