2
* Copyright © 2005-2012 Akiban Technologies, Inc. All rights reserved.
4
* This program and the accompanying materials are made available
5
* under the terms of the Eclipse Public License v1.0 which
6
* accompanies this distribution, and is available at
7
* http://www.eclipse.org/legal/epl-v10.html
9
* This program may also be available under different license terms.
10
* For more information, see www.akiban.com or contact licensing@akiban.com.
13
* Akiban Technologies, Inc.
16
package com.persistit.stress.unit;
18
import java.rmi.RemoteException;
19
import java.util.Random;
21
import javax.management.ObjectName;
23
import com.persistit.Accumulator;
24
import com.persistit.Configuration;
25
import com.persistit.Exchange;
26
import com.persistit.Persistit;
27
import com.persistit.Transaction;
28
import com.persistit.exception.PersistitException;
29
import com.persistit.mxbeans.CheckpointManagerMXBean;
30
import com.persistit.util.ArgParser;
31
import com.persistit.util.Util;
34
* Tests Accumulator values after restart. This test modifies accumulators and
35
* then restarts Persistit, both gracefully and after failure, to verify that
36
* the recovered Accumulator values are always correct. The test specifically
37
* attempts to test the juxtaposition of a Checkpoint and the final Accumulator
38
* update to look for bugs similar to 1064565.
43
public class AccumulatorRestart extends StressBase {
44
final static Random RANDOM = new Random();
46
private final static String[] ARGS_TEMPLATE = { "repeat|int:1:0:1000000000|Repetitions" };
48
public final static long CHECKPOINT_INTERVAL = 30;
50
long _checkpointTimestamp = 0;
51
long _checkpointTime = 0;
53
public AccumulatorRestart(final String argsString) {
58
public void setUp() throws Exception {
60
_ap = new ArgParser("com.persistit.Stress1", _args, ARGS_TEMPLATE).strict();
61
_repeatTotal = _ap.getIntValue("repeat");
65
public void executeTest() {
67
* Local copies, managed by this thread for comparison
74
for (_count = 1;; _count++) {
76
System.out.println(_threadName + " starting cycle " + _count);
77
_ex = getPersistit().getExchange("persistit", _rootName + _threadIndex, true);
78
final Accumulator sum = _ex.getTree().getAccumulator(Accumulator.Type.SUM, 17);
79
final Accumulator max = _ex.getTree().getAccumulator(Accumulator.Type.MAX, 22);
80
final Accumulator min = _ex.getTree().getAccumulator(Accumulator.Type.MIN, 23);
81
final Accumulator seq = _ex.getTree().getAccumulator(Accumulator.Type.SEQ, 47);
82
final Transaction txn = _ex.getTransaction();
87
final long minv = min.getSnapshotValue(txn);
88
final long maxv = max.getSnapshotValue(txn);
89
final long seqv = seq.getSnapshotValue(txn);
90
final long sumv = sum.getSnapshotValue(txn);
91
if (minv != minValue || maxv != maxValue || seqv != seqValue || sumv != sumValue) {
92
fail(String.format("Values don't match: (min/max/seq/sum) "
93
+ "expected=(%,d/%,d/%,d/%,d) actual=(%,d/%,d/%,d/%,d)", minValue, maxValue,
94
seqValue, sumValue, minv, maxv, seqv, sumv));
101
int seqValueHold = 0;
102
final boolean a = RANDOM.nextInt(50) == 0;
105
final long timeOffset = RANDOM.nextInt(1000) - 500;
106
while (!isTriggered(timeOffset)) {
107
final long r = RANDOM.nextInt(1000) - 500;
108
min.update(bsum(minValue, r), txn);
109
max.update(bsum(maxValue, r), txn);
112
long minWas = getLong(_ex.to("min"), Long.MAX_VALUE);
113
_ex.getValue().put(Math.min(bsum(minValue, r), minWas));
115
long maxWas = getLong(_ex.to("max"), Long.MIN_VALUE);
116
_ex.getValue().put(Math.max(bsum(maxValue, r), maxWas));
118
long seqWas = getLong(_ex.to("seq"), 0);
119
_ex.getValue().put(Math.max(seqValue + 1, seqWas));
121
long sumWas = getLong(_ex.to("sum"), 0);
122
_ex.getValue().put(Math.min(sumValue + r, sumWas));
126
minValue = Math.min(bsum(minValue, r), minValue);
127
maxValue = Math.max(bsum(maxValue, r), maxValue);
128
seqValue = seqValue + seqValueHold;
129
sumValue = sumValue + r;
142
if ((_count % 3) == 0) {
143
Persistit db = getPersistit();
146
if (isStopped() || _count >= _repeatTotal) {
150
final Configuration config = db.getConfiguration();
151
db = new Persistit();
152
db.initialize(config);
155
} catch (final Exception ex) {
161
private boolean isTriggered(final long timeOffset) {
162
final long cp = getPersistit().getCurrentCheckpoint().getTimestamp();
163
final long now = System.nanoTime();
165
if (_checkpointTime == 0) {
166
if (cp > _checkpointTimestamp) {
167
_checkpointTime = now;
168
_checkpointTimestamp = cp;
171
if (_checkpointTime != 0) {
172
if (timeOffset > 0 && now > _checkpointTime + timeOffset) {
175
} else if (timeOffset < 0 && now > _checkpointTime + timeOffset + CHECKPOINT_INTERVAL * Util.MS_PER_S) {
183
private long bsum(final long a, final long b) {
185
return a + b > 0 ? a : a + b;
187
return a + b < 0 ? a : a + b;
191
private long getLong(final Exchange ex, final long dflt) throws PersistitException {
192
if (ex.getValue().isDefined()) {
193
return ex.getValue().getLong();