mirror of
https://github.com/OpenHFT/Chronicle-Map.git
synced 2021-09-13 01:26:12 +00:00
Enhanced thread safety tests with the latest lang release
This commit is contained in:
+13
-1
@@ -21,6 +21,7 @@ package net.openhft.chronicle.common.serialization.impl;
|
||||
import net.openhft.chronicle.common.serialization.AgileBytesMarshaller;
|
||||
import net.openhft.chronicle.common.serialization.Hasher;
|
||||
import net.openhft.lang.io.Bytes;
|
||||
import net.openhft.lang.io.MultiStoreBytes;
|
||||
import net.openhft.lang.io.NativeBytes;
|
||||
import net.openhft.lang.io.serialization.*;
|
||||
import net.openhft.lang.io.serialization.impl.AllocateInstanceObjectFactory;
|
||||
@@ -117,7 +118,7 @@ public class ByteableMarshaller<E extends Byteable> implements AgileBytesMarshal
|
||||
try {
|
||||
if (e == null)
|
||||
e = getInstance();
|
||||
e.bytes(bytes, bytes.position());
|
||||
setBytesAndOffset(e, bytes);
|
||||
bytes.skip(size);
|
||||
return e;
|
||||
} catch (Exception ex) {
|
||||
@@ -125,6 +126,17 @@ public class ByteableMarshaller<E extends Byteable> implements AgileBytesMarshal
|
||||
}
|
||||
}
|
||||
|
||||
public static void setBytesAndOffset(Byteable e, Bytes bytes) {
|
||||
// use the unshifting underlying Bytes (the position never changes)
|
||||
// if you use a Bytes where the position changes, you risk concurrency issues.
|
||||
if (bytes instanceof MultiStoreBytes) {
|
||||
MultiStoreBytes msb = (MultiStoreBytes) bytes;
|
||||
e.bytes(msb.underlyingBytes(), msb.underlyingOffset() + msb.position());
|
||||
} else {
|
||||
e.bytes(bytes, bytes.position());
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@NotNull
|
||||
E getInstance() throws Exception {
|
||||
|
||||
@@ -259,9 +259,9 @@ public class NodeDiscovery {
|
||||
* bitwise OR's the two bit sets or put another way, merges the source bitset into the
|
||||
* destination bitset and returns the destination
|
||||
*
|
||||
* @param source
|
||||
* @param destination
|
||||
* @return
|
||||
* @param source to or
|
||||
* @param destination to or
|
||||
* @return result.
|
||||
*/
|
||||
private DirectBitSet orBitSets(@NotNull final DirectBitSet source,
|
||||
@NotNull final DirectBitSet destination) {
|
||||
|
||||
@@ -621,7 +621,7 @@ class ReplicatedChronicleMap<K, KI, MKI extends MetaBytesInterop<K, KI>,
|
||||
readLock();
|
||||
try {
|
||||
long keySize = metaKeyWriter.size(keyWriter, key);
|
||||
MultiStoreBytes entry = tmpBytes;
|
||||
MultiStoreBytes entry = acquireTmpBytes();
|
||||
long offset = searchKey(keyWriter, metaKeyWriter, key, keySize, hash2, entry,
|
||||
hashLookupLiveOnly);
|
||||
if (offset >= 0) {
|
||||
@@ -816,7 +816,7 @@ class ReplicatedChronicleMap<K, KI, MKI extends MetaBytesInterop<K, KI>,
|
||||
hashLookup.startSearch(hash2);
|
||||
for (long pos; (pos = hashLookup.nextPos()) >= 0L; ) {
|
||||
long offset = offsetFromPos(pos);
|
||||
NativeBytes entry = entry(offset);
|
||||
MultiStoreBytes entry = entry(offset);
|
||||
if (!keyEquals(keyWriter, metaKeyWriter, key, keySize, entry))
|
||||
continue;
|
||||
// key is found
|
||||
@@ -982,7 +982,7 @@ class ReplicatedChronicleMap<K, KI, MKI extends MetaBytesInterop<K, KI>,
|
||||
multiMap.startSearch(hash2);
|
||||
for (long pos; (pos = multiMap.nextPos()) >= 0L; ) {
|
||||
long offset = offsetFromPos(pos);
|
||||
NativeBytes entry = entry(offset);
|
||||
MultiStoreBytes entry = entry(offset);
|
||||
if (!keyEquals(keyWriter, metaKeyWriter, key, keySize, entry))
|
||||
continue;
|
||||
// key is found
|
||||
@@ -1049,7 +1049,7 @@ class ReplicatedChronicleMap<K, KI, MKI extends MetaBytesInterop<K, KI>,
|
||||
hashLookupLiveOnly.startSearch(hash2);
|
||||
for (long pos; (pos = hashLookupLiveOnly.nextPos()) >= 0L; ) {
|
||||
long offset = offsetFromPos(pos);
|
||||
NativeBytes entry = entry(offset);
|
||||
MultiStoreBytes entry = entry(offset);
|
||||
if (!keyEquals(keyWriter, metaKeyWriter, key, keySize, entry))
|
||||
continue;
|
||||
// key is found
|
||||
@@ -1109,19 +1109,21 @@ class ReplicatedChronicleMap<K, KI, MKI extends MetaBytesInterop<K, KI>,
|
||||
|
||||
@Override
|
||||
public Entry<K, V> getEntry(long pos) {
|
||||
bytes.position(offsetFromPos(pos) + metaDataBytes);
|
||||
MultiStoreBytes entry = acquireTmpBytes();
|
||||
long offset = offsetFromPos(pos) + metaDataBytes;
|
||||
entry.setBytesOffset(bytes, offset);
|
||||
|
||||
long keySize = keySizeMarshaller.readSize(bytes);
|
||||
long keySize = keySizeMarshaller.readSize(entry);
|
||||
ThreadLocalCopies copies = keyReaderProvider.getCopies(null);
|
||||
K key = keyReaderProvider.get(copies, originalKeyReader).read(bytes, keySize);
|
||||
K key = keyReaderProvider.get(copies, originalKeyReader).read(entry, keySize);
|
||||
|
||||
long timestamp = bytes.readLong();
|
||||
bytes.skip(2L); // identifier and isDeleted flag
|
||||
long timestamp = entry.readLong();
|
||||
entry.skip(2L); // identifier and isDeleted flag
|
||||
|
||||
long valueSize = valueSizeMarshaller.readSize(bytes);
|
||||
alignment.alignPositionAddr(bytes);
|
||||
long valueSize = valueSizeMarshaller.readSize(entry);
|
||||
alignment.alignPositionAddr(entry);
|
||||
copies = valueReaderProvider.getCopies(copies);
|
||||
V value = valueReaderProvider.get(copies, originalValueReader).read(bytes, valueSize);
|
||||
V value = valueReaderProvider.get(copies, originalValueReader).read(entry, valueSize);
|
||||
|
||||
return new TimestampTrackingEntry(key, value, timestamp);
|
||||
}
|
||||
|
||||
@@ -790,7 +790,7 @@ class StatelessChronicleMap<K, V> implements ChronicleMap<K, V>, Closeable {
|
||||
|
||||
private void writeSizeAt(long locationOfSize) {
|
||||
long size = bytes.position() - locationOfSize;
|
||||
LOG.info("writing size = " + size);
|
||||
// LOG.info("writing size = " + size);
|
||||
bytes.writeInt(locationOfSize, (int) size - SIZE_OF_SIZE);
|
||||
}
|
||||
|
||||
|
||||
@@ -1270,14 +1270,14 @@ class StatelessServerConnector<K, V> {
|
||||
@NotNull final ByteBufferBytes reader) {
|
||||
|
||||
|
||||
LOG.info("processStatelessEvent - writer position=" + reader.position() +
|
||||
/* LOG.info("processStatelessEvent - writer position=" + reader.position() +
|
||||
", " +
|
||||
"limit=" + reader.limit() + ",capacity=" + reader.capacity());
|
||||
|
||||
|
||||
LOG.info("StatelessServerConnector- reader position=" + writer.position() +
|
||||
", " +
|
||||
"limit=" + writer.limit() + ",capacity=" + writer.capacity());
|
||||
"limit=" + writer.limit() + ",capacity=" + writer.capacity());*/
|
||||
|
||||
|
||||
final StatelessChronicleMap.EventId event = StatelessChronicleMap.EventId.values()[eventId];
|
||||
|
||||
@@ -523,6 +523,14 @@ class VanillaChronicleMap<K, KI, MKI extends MetaBytesInterop<K, KI>,
|
||||
return valueSize;
|
||||
}
|
||||
|
||||
static final ThreadLocal<MultiStoreBytes> tmpBytes = new ThreadLocal<>();
|
||||
protected MultiStoreBytes acquireTmpBytes() {
|
||||
MultiStoreBytes b = tmpBytes.get();
|
||||
if (b == null)
|
||||
tmpBytes.set(b = new MultiStoreBytes());
|
||||
return b;
|
||||
}
|
||||
|
||||
// these methods should be package local, not public or private.
|
||||
class Segment implements SharedSegment {
|
||||
/*
|
||||
@@ -537,7 +545,6 @@ class VanillaChronicleMap<K, KI, MKI extends MetaBytesInterop<K, KI>,
|
||||
static final long SIZE_OFFSET = LOCK_OFFSET + 8L; // 32-bit
|
||||
|
||||
final NativeBytes bytes;
|
||||
final MultiStoreBytes tmpBytes = new MultiStoreBytes();
|
||||
final long entriesOffset;
|
||||
private final int index;
|
||||
private final SingleThreadedDirectBitSet freeList;
|
||||
@@ -555,7 +562,7 @@ class VanillaChronicleMap<K, KI, MKI extends MetaBytesInterop<K, KI>,
|
||||
long start = bytes.startAddr() + SEGMENT_HEADER;
|
||||
createHashLookups(start);
|
||||
start += align64(sizeOfMultiMap() + sizeOfMultiMapBitSet()) * multiMapsPerSegment();
|
||||
final NativeBytes bsBytes = new NativeBytes(tmpBytes.objectSerializer(),
|
||||
final NativeBytes bsBytes = new NativeBytes(ms.objectSerializer(),
|
||||
start, start + align8(align8(entriesPerSegment) / 8L), null);
|
||||
freeList = new SingleThreadedDirectBitSet(bsBytes);
|
||||
start += numberOfBitSets() * sizeOfBitSets();
|
||||
@@ -624,7 +631,7 @@ class VanillaChronicleMap<K, KI, MKI extends MetaBytesInterop<K, KI>,
|
||||
|
||||
public void readLock() throws IllegalStateException {
|
||||
while (true) {
|
||||
final boolean success = bytes.tryLockNanosLong(LOCK_OFFSET, lockTimeOutNS);
|
||||
final boolean success = bytes.tryRWReadLock(LOCK_OFFSET, lockTimeOutNS);
|
||||
if (success) return;
|
||||
if (currentThread().isInterrupted()) {
|
||||
throw new IllegalStateException(new InterruptedException("Unable to obtain lock, interrupted"));
|
||||
@@ -637,7 +644,7 @@ class VanillaChronicleMap<K, KI, MKI extends MetaBytesInterop<K, KI>,
|
||||
|
||||
public void writeLock() throws IllegalStateException {
|
||||
while (true) {
|
||||
final boolean success = bytes.tryLockNanosLong(LOCK_OFFSET, lockTimeOutNS);
|
||||
final boolean success = bytes.tryRWWriteLock(LOCK_OFFSET, lockTimeOutNS);
|
||||
if (success) return;
|
||||
if (currentThread().isInterrupted()) {
|
||||
throw new IllegalStateException(new InterruptedException("Unable to obtain lock, interrupted"));
|
||||
@@ -650,7 +657,7 @@ class VanillaChronicleMap<K, KI, MKI extends MetaBytesInterop<K, KI>,
|
||||
|
||||
public void readUnlock() {
|
||||
try {
|
||||
bytes.unlockLong(LOCK_OFFSET);
|
||||
bytes.unlockRWReadLock(LOCK_OFFSET);
|
||||
} catch (IllegalMonitorStateException e) {
|
||||
errorListener.errorOnUnlock(e);
|
||||
}
|
||||
@@ -658,7 +665,7 @@ class VanillaChronicleMap<K, KI, MKI extends MetaBytesInterop<K, KI>,
|
||||
|
||||
public void writeUnlock() {
|
||||
try {
|
||||
bytes.unlockLong(LOCK_OFFSET);
|
||||
bytes.unlockRWWriteLock(LOCK_OFFSET);
|
||||
} catch (IllegalMonitorStateException e) {
|
||||
errorListener.errorOnUnlock(e);
|
||||
}
|
||||
@@ -675,15 +682,12 @@ class VanillaChronicleMap<K, KI, MKI extends MetaBytesInterop<K, KI>,
|
||||
|
||||
|
||||
public MultiStoreBytes entry(long offset) {
|
||||
return reuse(tmpBytes, offset);
|
||||
return reuse(acquireTmpBytes(), offset);
|
||||
}
|
||||
|
||||
private MultiStoreBytes reuse(MultiStoreBytes entry, long offset) {
|
||||
offset += metaDataBytes;
|
||||
entry.storePositionAndSize(bytes, offset,
|
||||
// "Infinity". Limit not used when treating entries as
|
||||
// possibly oversized
|
||||
bytes.limit() - offset);
|
||||
entry.setBytesOffset(bytes, offset);
|
||||
return entry;
|
||||
}
|
||||
|
||||
@@ -728,7 +732,7 @@ class VanillaChronicleMap<K, KI, MKI extends MetaBytesInterop<K, KI>,
|
||||
readLock();
|
||||
try {
|
||||
long keySize = metaKeyInterop.size(keyInterop, key);
|
||||
MultiStoreBytes entry = tmpBytes;
|
||||
MultiStoreBytes entry = acquireTmpBytes();
|
||||
long offset = searchKey(keyInterop, metaKeyInterop, key, keySize, hash2, entry,
|
||||
hashLookup);
|
||||
if (offset >= 0L) {
|
||||
@@ -776,7 +780,7 @@ class VanillaChronicleMap<K, KI, MKI extends MetaBytesInterop<K, KI>,
|
||||
}
|
||||
|
||||
V onKeyPresentOnAcquire(ThreadLocalCopies copies, K key, V usingValue, long offset,
|
||||
NativeBytes entry) {
|
||||
MultiStoreBytes entry) {
|
||||
V v = readValue(copies, entry, usingValue);
|
||||
notifyGet(offset, key, v);
|
||||
return v;
|
||||
@@ -817,7 +821,7 @@ class VanillaChronicleMap<K, KI, MKI extends MetaBytesInterop<K, KI>,
|
||||
hashLookup.startSearch(hash2);
|
||||
for (long pos; (pos = hashLookup.nextPos()) >= 0L; ) {
|
||||
long offset = offsetFromPos(pos);
|
||||
NativeBytes entry = entry(offset);
|
||||
MultiStoreBytes entry = entry(offset);
|
||||
if (!keyEquals(keyInterop, metaKeyInterop, key, keySize, entry))
|
||||
continue;
|
||||
// key is found
|
||||
@@ -840,7 +844,7 @@ class VanillaChronicleMap<K, KI, MKI extends MetaBytesInterop<K, KI>,
|
||||
}
|
||||
}
|
||||
|
||||
V replaceValueOnPut(ThreadLocalCopies copies, K key, V value, NativeBytes entry, long pos,
|
||||
V replaceValueOnPut(ThreadLocalCopies copies, K key, V value, MultiStoreBytes entry, long pos,
|
||||
long offset, boolean readPrevValue, MultiMap searchedHashLookup) {
|
||||
long valueSizePos = entry.position();
|
||||
long valueSize = readValueSize(entry);
|
||||
@@ -978,15 +982,14 @@ class VanillaChronicleMap<K, KI, MKI extends MetaBytesInterop<K, KI>,
|
||||
nextPosToSearchFrom = fromPos;
|
||||
}
|
||||
|
||||
V readValue(ThreadLocalCopies copies, NativeBytes entry, V value) {
|
||||
V readValue(ThreadLocalCopies copies, MultiStoreBytes entry, V value) {
|
||||
return readValue(copies, entry, value, readValueSize(entry));
|
||||
}
|
||||
|
||||
V readValue(ThreadLocalCopies copies, NativeBytes entry, V value, long valueSize) {
|
||||
V readValue(ThreadLocalCopies copies, MultiStoreBytes entry, V value, long valueSize) {
|
||||
copies = valueReaderProvider.getCopies(copies);
|
||||
BytesReader<V> valueReader = valueReaderProvider.get(copies, originalValueReader);
|
||||
bytes.positionAddr(entry.positionAddr());
|
||||
return valueReader.read(bytes, valueSize, value);
|
||||
return valueReader.read(entry, valueSize, value);
|
||||
}
|
||||
|
||||
boolean keyEquals(KI keyInterop, MKI metaKeyInterop, K key,
|
||||
@@ -1013,7 +1016,7 @@ class VanillaChronicleMap<K, KI, MKI extends MetaBytesInterop<K, KI>,
|
||||
hashLookup.startSearch(hash2);
|
||||
for (long pos; (pos = hashLookup.nextPos()) >= 0L; ) {
|
||||
long offset = offsetFromPos(pos);
|
||||
NativeBytes entry = entry(offset);
|
||||
MultiStoreBytes entry = entry(offset);
|
||||
if (!keyEquals(keyInterop, metaKeyInterop, key, keySize, entry))
|
||||
continue;
|
||||
// key is found
|
||||
@@ -1074,7 +1077,7 @@ class VanillaChronicleMap<K, KI, MKI extends MetaBytesInterop<K, KI>,
|
||||
hashLookup.startSearch(hash2);
|
||||
for (long pos; (pos = hashLookup.nextPos()) >= 0L; ) {
|
||||
long offset = offsetFromPos(pos);
|
||||
NativeBytes entry = entry(offset);
|
||||
MultiStoreBytes entry = entry(offset);
|
||||
if (!keyEquals(keyInterop, metaKeyInterop, key, keySize, entry))
|
||||
continue;
|
||||
// key is found
|
||||
@@ -1090,7 +1093,7 @@ class VanillaChronicleMap<K, KI, MKI extends MetaBytesInterop<K, KI>,
|
||||
}
|
||||
|
||||
V onKeyPresentOnReplace(ThreadLocalCopies copies, K key, V expectedValue, V newValue,
|
||||
long pos, long offset, NativeBytes entry,
|
||||
long pos, long offset, MultiStoreBytes entry,
|
||||
MultiMap searchedHashLookup) {
|
||||
long valueSizePos = entry.position();
|
||||
long valueSize = readValueSize(entry);
|
||||
@@ -1111,24 +1114,27 @@ class VanillaChronicleMap<K, KI, MKI extends MetaBytesInterop<K, KI>,
|
||||
|
||||
void notifyPut(long offset, boolean added, K key, V value, final long pos) {
|
||||
if (eventListener() != MapEventListeners.NOP) {
|
||||
tmpBytes.storePositionAndSize(bytes, offset, entrySize);
|
||||
eventListener().onPut(VanillaChronicleMap.this, tmpBytes, metaDataBytes,
|
||||
MultiStoreBytes b = acquireTmpBytes();
|
||||
b.storePositionAndSize(bytes, offset, entrySize);
|
||||
eventListener().onPut(VanillaChronicleMap.this, b, metaDataBytes,
|
||||
added, key, value, pos, this);
|
||||
}
|
||||
}
|
||||
|
||||
void notifyGet(long offset, K key, V value) {
|
||||
if (eventListener() != MapEventListeners.NOP) {
|
||||
tmpBytes.storePositionAndSize(bytes, offset, entrySize);
|
||||
eventListener().onGetFound(VanillaChronicleMap.this, tmpBytes, metaDataBytes,
|
||||
MultiStoreBytes b = acquireTmpBytes();
|
||||
b.storePositionAndSize(bytes, offset, entrySize);
|
||||
eventListener().onGetFound(VanillaChronicleMap.this, b, metaDataBytes,
|
||||
key, value);
|
||||
}
|
||||
}
|
||||
|
||||
void notifyRemoved(long offset, K key, V value, final long pos) {
|
||||
if (eventListener() != MapEventListeners.NOP) {
|
||||
tmpBytes.storePositionAndSize(bytes, offset, entrySize);
|
||||
eventListener().onRemove(VanillaChronicleMap.this, tmpBytes, metaDataBytes,
|
||||
MultiStoreBytes b = acquireTmpBytes();
|
||||
b.storePositionAndSize(bytes, offset, entrySize);
|
||||
eventListener().onRemove(VanillaChronicleMap.this, b, metaDataBytes,
|
||||
key, value, pos, this);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user