* adjust.
*/
int adjust = (delta > cacheSize) ? delta : cacheSize;
/* Perform an auto-commit transaction to update the sequence. */
Locker locker = null;
Cursor cursor = null;
OperationStatus status = OperationStatus.NOTFOUND;
try {
locker = LockerFactory.getWritableLocker
(db.getEnvironment(),
txn,
db.getDatabaseImpl().isInternalDb(),
db.isTransactional(),
db.getDatabaseImpl().isReplicated(),
// autoTxnIsReplicated
autoCommitConfig);
cursor = new Cursor(db, locker, null);
/* Get the existing record. */
readDataRequired(cursor, LockMode.RMW);
/* If we would have wrapped when not allowed, overflow. */
if (overflow) {
throw new SequenceOverflowException
("Sequence overflow " + storedValue);
}
/*
* Handle wrapping. The range size can be larger than a long
* can hold, so to avoid arithmetic overflow we use BigInteger
* arithmetic. Since we are going to write, the BigInteger
* overhead is acceptable.
*/
BigInteger availBig;
if (increment) {
/* Available amount: rangeMax - storedValue */
availBig = BigInteger.valueOf(rangeMax).
subtract(BigInteger.valueOf(storedValue));
} else {
/* Available amount: storedValue - rangeMin */
availBig = BigInteger.valueOf(storedValue).
subtract(BigInteger.valueOf(rangeMin));
}
if (availBig.compareTo(BigInteger.valueOf(adjust)) < 0) {
/* If availBig < adjust then availBig fits in an int. */
int availInt = (int) availBig.longValue();
if (availInt < delta) {
if (wrapAllowed) {
/* Wrap to the opposite range end point. */
storedValue = increment ? rangeMin : rangeMax;
wrapped = true;
} else {
/* Signal an overflow next time. */
overflow = true;
adjust = 0;
}
} else {
/*
* If the delta fits in the cache available, don't wrap
* just to allocate the full cacheSize; instead,
* allocate as much as is available.
*/
adjust = availInt;
}
}
/* Negate the adjustment for decrementing. */
if (!increment) {
adjust = -adjust;
}
/* Set the stored value one past the cached amount. */
storedValue += adjust;
/* Write the new stored value. */
cursor.put(key, makeData());
status = OperationStatus.SUCCESS;
} finally {
if (cursor != null) {
cursor.close();
}
if (locker != null) {
locker.operationEnd(status);
}
}
/* The cache now contains the range: [cacheValue, storedValue) */
cacheValue = storedValue - adjust;