Require update lock level for checking entry checksum

This commit is contained in:
leventov
2016-02-17 17:50:30 +07:00
parent 4b58d21953
commit a3c83e1c4a
2 changed files with 18 additions and 0 deletions
@@ -32,6 +32,13 @@ public interface ChecksumEntry {
* only when value bytes was updated directly, for example though flyweight implementation of
* a <a href="https://github.com/OpenHFT/Chronicle-Values#value-interface-specification">value
* interface</a>.
*
* @throws UnsupportedOperationException if checksums are not stored in the containing Chronicle
* Hash
* @throws RuntimeException if the context of this entry is locked improperly, e. g. on the
* {@linkplain HashQueryContext#readLock() read} level, that is not upgradable to the
* {@linkplain HashQueryContext#updateLock() update} level. Calling {@code updateChecksum()}
* method is enabled when at least update lock is held.
*/
void updateChecksum();
@@ -39,6 +46,12 @@ public interface ChecksumEntry {
* Computes checksum from the entry bytes and checks whether it is equal to the stored checksum.
*
* @return {@code true} if stored checksum equals to checksum computed from the entry bytes
* @throws UnsupportedOperationException if checksums are not stored in the containing Chronicle
* Hash
* @throws RuntimeException if the context of this entry is locked improperly, e. g. on the
* {@linkplain HashQueryContext#readLock() read} level, that is not upgradable to the
* {@linkplain HashQueryContext#updateLock() update} level. Calling {@code checkSum()} method is
* enabled when at least update lock is held.
*/
boolean checkSum();
}
@@ -164,6 +164,7 @@ public abstract class HashEntryStages<K> implements HashEntry<K>, ChecksumEntry
throw new UnsupportedOperationException(
"Checksum is not stored in this Chronicle Hash");
}
s.innerUpdateLock.lock();
initDelayedUpdateChecksum(true);
}
@@ -174,6 +175,10 @@ public abstract class HashEntryStages<K> implements HashEntry<K>, ChecksumEntry
throw new UnsupportedOperationException(
"Checksum is not stored in this Chronicle Hash");
}
// This is needed, because a concurrent update lock holder might perform an entry update,
// but not yet written a checksum (because checksum write is delayed to the update unlock).
// So checkSum() on read lock level might result to false negative results.
s.innerUpdateLock.lock();
return delayedUpdateChecksumInit() || checksumStrategy.innerCheckSum();
}