Closed pablojan closed 5 years ago
The exception recorded in the previous message was caused by an unexpected behavior of
DeltaStoreBasedWaveletState.cachedDeltas
: this map must contain all deltas already applied to the the wavelet snapshot DeltaStoreBasedWaveletState.snapshot
, but the exception shows that sometimes, the latest delta is not present in cachedDeltas,
whereas snapshot
already has been updated with it. Both data structures are updated in the method appendDelta()
(see below) but in original code, invocation to cachedDeltas.put()
is done outside the synchronized block.
With debugging code, it's demonstrated that cachedDeltas' map got desynchronized sometimes.
@Override
public void appendDelta(WaveletDeltaRecord deltaRecord)
throws OperationException {
HashedVersion currentVersion = getCurrentVersion();
Preconditions.checkArgument(currentVersion.equals(deltaRecord.getAppliedAtVersion()),
"Applied version %s doesn't match current version %s", deltaRecord.getAppliedAtVersion(),
currentVersion);
if (deltaRecord.getAppliedAtVersion().getVersion() == 0) {
Preconditions.checkState(lastPersistedVersion.get() == null);
snapshot = WaveletDataUtil.buildWaveletFromFirstDelta(getWaveletName(), deltaRecord.getTransformedDelta());
contributions = new WaveletContributions(deltasAccess.getWaveletName());
contributions.apply(deltaRecord.getTransformedDelta());
} else {
// Avoid to update snapshot when it has being persisted
synchronized (persistLock) {
WaveletDataUtil.applyWaveletDelta(deltaRecord.getTransformedDelta(), snapshot);
contributions.apply(deltaRecord.getTransformedDelta());
}
}
// Now that we built the snapshot without any exceptions, we record the delta.
cachedDeltas.put(deltaRecord.getAppliedAtVersion(), deltaRecord); <------- UNSAFE UPDATE
// Increment counter controlling snapshot persistence
deltasCountBeforeSnapshotStore++;
}
During a long automatized test of collaborative writing (3 writers, 1 read-only) one of the writer clients got disconnected and the server shown following exception: