diff --git a/pom.xml b/pom.xml index 1c6a35b3f..4b6065c6b 100755 --- a/pom.xml +++ b/pom.xml @@ -149,6 +149,12 @@ test + + net.openhft + stage-compiler + 1.0 + provided + diff --git a/src/main/java/net/openhft/chronicle/hash/impl/stage/data/bytes/EntryKeyBytesData.java b/src/main/java/net/openhft/chronicle/hash/impl/stage/data/bytes/EntryKeyBytesData.java new file mode 100644 index 000000000..c394919e1 --- /dev/null +++ b/src/main/java/net/openhft/chronicle/hash/impl/stage/data/bytes/EntryKeyBytesData.java @@ -0,0 +1,80 @@ +/* + * Copyright 2015 Higher Frequency Trading + * + * http://www.higherfrequencytrading.com + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package net.openhft.chronicle.hash.impl.stage.data.bytes; + +import net.openhft.chronicle.bytes.RandomDataInput; +import net.openhft.chronicle.hash.AbstractData; +import net.openhft.chronicle.hash.impl.stage.entry.HashEntryStages; +import net.openhft.chronicle.hash.impl.stage.hash.CheckOnEachPublicOperation; +import net.openhft.chronicle.hash.impl.stage.hash.KeyBytesInterop; +import net.openhft.sg.Stage; +import net.openhft.sg.StageRef; +import net.openhft.sg.Staged; + +@Staged +public class EntryKeyBytesData extends AbstractData { + + @StageRef KeyBytesInterop ki; + @StageRef HashEntryStages entry; + @StageRef CheckOnEachPublicOperation checkOnEachPublicOperation; + + + @Stage("CachedEntryKey") private K cachedEntryKey; + @Stage("CachedEntryKey") private boolean cachedEntryKeyRead = false; + + private void initCachedEntryKey() { + cachedEntryKey = innerGetUsing(cachedEntryKey); + cachedEntryKeyRead = true; + } + + @Override + public RandomDataInput bytes() { + checkOnEachPublicOperation.checkOnEachPublicOperation(); + return entry.entryBS; + } + + @Override + public long offset() { + checkOnEachPublicOperation.checkOnEachPublicOperation(); + return entry.keyOffset; + } + + @Override + public long size() { + checkOnEachPublicOperation.checkOnEachPublicOperation(); + return entry.keySize; + } + + @Override + public K get() { + checkOnEachPublicOperation.checkOnEachPublicOperation(); + return cachedEntryKey; + } + + @Override + public K getUsing(K usingKey) { + checkOnEachPublicOperation.checkOnEachPublicOperation(); + return innerGetUsing(usingKey); + } + + private K innerGetUsing(K usingKey) { + entry.entryBytes.position(entry.keyOffset); + return ki.keyReader.read(entry.entryBytes, size(), usingKey); + } +} diff --git a/src/main/java/net/openhft/chronicle/hash/impl/stage/data/bytes/InputKeyBytesData.java b/src/main/java/net/openhft/chronicle/hash/impl/stage/data/bytes/InputKeyBytesData.java new file mode 100644 index 000000000..781db3a19 --- /dev/null +++ b/src/main/java/net/openhft/chronicle/hash/impl/stage/data/bytes/InputKeyBytesData.java @@ -0,0 +1,70 @@ +/* + * Copyright 2015 Higher Frequency Trading + * + * http://www.higherfrequencytrading.com + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package net.openhft.chronicle.hash.impl.stage.data.bytes; + +import net.openhft.chronicle.bytes.RandomDataInput; +import net.openhft.chronicle.hash.AbstractData; +import net.openhft.chronicle.hash.impl.stage.hash.KeyBytesInterop; +import net.openhft.chronicle.hash.impl.stage.input.HashInputBytes; +import net.openhft.lang.io.Bytes; +import net.openhft.sg.Stage; +import net.openhft.sg.StageRef; +import net.openhft.sg.Staged; + + +@Staged +public class InputKeyBytesData extends AbstractData { + @StageRef HashInputBytes in; + @StageRef KeyBytesInterop ki; + + @Stage("CachedBytesInputKey") private K cachedBytesInputKey; + @Stage("CachedBytesInputKey") private boolean cachedBytesInputKeyRead = false; + + private void initCachedBytesInputKey() { + cachedBytesInputKey = getUsing(cachedBytesInputKey); + cachedBytesInputKeyRead = true; + } + + @Override + public RandomDataInput bytes() { + return in.inputStore; + } + + @Override + public long offset() { + return in.inputKeyOffset; + } + + @Override + public long size() { + return in.inputKeySize; + } + + @Override + public K get() { + return cachedBytesInputKey; + } + + @Override + public K getUsing(K usingKey) { + Bytes inputBytes = in.inputBytes; + inputBytes.position(in.inputKeyOffset); + return ki.keyReader.read(inputBytes, size(), usingKey); + } +} diff --git a/src/main/java/net/openhft/chronicle/hash/impl/stage/data/instance/InputKeyInstanceData.java b/src/main/java/net/openhft/chronicle/hash/impl/stage/data/instance/InputKeyInstanceData.java new file mode 100644 index 000000000..8d43e1db2 --- /dev/null +++ b/src/main/java/net/openhft/chronicle/hash/impl/stage/data/instance/InputKeyInstanceData.java @@ -0,0 +1,65 @@ +/* + * Copyright 2015 Higher Frequency Trading + * + * http://www.higherfrequencytrading.com + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package net.openhft.chronicle.hash.impl.stage.data.instance; + +import net.openhft.chronicle.hash.impl.CopyingInstanceData; +import net.openhft.chronicle.hash.impl.stage.hash.KeyBytesInterop; +import net.openhft.chronicle.hash.impl.value.instance.KeyInitableData; +import net.openhft.chronicle.hash.serialization.internal.MetaBytesInterop; +import net.openhft.lang.io.DirectBytes; +import net.openhft.sg.Stage; +import net.openhft.sg.StageRef; +import net.openhft.sg.Staged; + +@Staged +public abstract class InputKeyInstanceData> + extends CopyingInstanceData implements KeyInitableData { + + @StageRef KeyBytesInterop ki; + + private K key = null; + + @Override + public void initKey(K key) { + this.key = key; + } + + @Override + public K instance() { + return key; + } + + @Stage("Buffer") private DirectBytes buffer; + @Stage("Buffer") private boolean marshalled = false; + + private void initBuffer() { + MKI mki = ki.keyMetaInterop(key); + long size = mki.size(ki.keyInterop, key); + buffer = getBuffer(this.buffer, size); + mki.write(ki.keyInterop, buffer, key); + buffer.flip(); + marshalled = true; + } + + @Override + public K getUsing(K usingKey) { + buffer.position(0); + return ki.keyReader.read(buffer, buffer.limit(), usingKey); + } +} diff --git a/src/main/java/net/openhft/chronicle/hash/impl/stage/entry/AllocatedChunks.java b/src/main/java/net/openhft/chronicle/hash/impl/stage/entry/AllocatedChunks.java new file mode 100644 index 000000000..d49981a3c --- /dev/null +++ b/src/main/java/net/openhft/chronicle/hash/impl/stage/entry/AllocatedChunks.java @@ -0,0 +1,47 @@ +/* + * Copyright 2015 Higher Frequency Trading + * + * http://www.higherfrequencytrading.com + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package net.openhft.chronicle.hash.impl.stage.entry; + +import net.openhft.chronicle.hash.impl.VanillaChronicleHashHolder; +import net.openhft.sg.StageRef; +import net.openhft.sg.Staged; + +@Staged +public class AllocatedChunks { + + @StageRef public VanillaChronicleHashHolder hh; + @StageRef public SegmentStages s; + @StageRef public HashEntryStages entry; + + public int allocatedChunks = 0; + + public void initAllocatedChunks(int allocatedChunks) { + this.allocatedChunks = allocatedChunks; + } + + public void incrementSegmentEntriesIfNeeded() { + // don't increment + } + + public void initEntryAndKeyCopying(long entrySize, long bytesToCopy) { + initAllocatedChunks(hh.h().inChunks(entrySize)); + entry.copyExistingEntry(s.alloc(allocatedChunks), bytesToCopy); + incrementSegmentEntriesIfNeeded(); + } +} diff --git a/src/main/java/net/openhft/chronicle/hash/impl/stage/entry/HashEntryStages.java b/src/main/java/net/openhft/chronicle/hash/impl/stage/entry/HashEntryStages.java new file mode 100644 index 000000000..9f1b8b646 --- /dev/null +++ b/src/main/java/net/openhft/chronicle/hash/impl/stage/entry/HashEntryStages.java @@ -0,0 +1,134 @@ +/* + * Copyright 2015 Higher Frequency Trading + * + * http://www.higherfrequencytrading.com + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package net.openhft.chronicle.hash.impl.stage.entry; + +import net.openhft.chronicle.bytes.BytesStore; +import net.openhft.chronicle.bytes.NativeBytesStore; +import net.openhft.chronicle.hash.Data; +import net.openhft.chronicle.hash.HashEntry; +import net.openhft.chronicle.hash.impl.VanillaChronicleHashHolder; +import net.openhft.chronicle.hash.impl.stage.data.bytes.EntryKeyBytesData; +import net.openhft.chronicle.hash.impl.stage.hash.CheckOnEachPublicOperation; +import net.openhft.lang.io.Bytes; +import net.openhft.sg.Stage; +import net.openhft.sg.StageRef; +import net.openhft.sg.Staged; +import org.jetbrains.annotations.NotNull; + + +@Staged +public abstract class HashEntryStages implements HashEntry { + + @StageRef VanillaChronicleHashHolder hh; + @StageRef public SegmentStages s; + @StageRef public CheckOnEachPublicOperation checkOnEachPublicOperation; + @StageRef public HashLookupPos hlp; + + public final Bytes entryBytes = hh.h().ms.bytes(); + public final BytesStore entryBS = + new NativeBytesStore<>(entryBytes.address(), entryBytes.capacity(), null, false); + + public long pos = -1; + + public void initPos(long pos) { + this.pos = pos; + } + + public abstract void closePos(); + + @Stage("EntryOffset") public long keySizeOffset = -1; + + public void initEntryOffset() { + keySizeOffset = s.entrySpaceOffset + pos * hh.h().chunkSize; + entryBytes.limit(entryBytes.capacity()); + } + + public long keySize = -1; + + public void initKeySize(long keySize) { + this.keySize = keySize; + } + + public long keyOffset = -1; + + public void initKeyOffset(long keyOffset) { + this.keyOffset = keyOffset; + } + + public void readExistingEntry(long pos) { + initPos(pos); + entryBytes.position(keySizeOffset); + initKeySize(hh.h().keySizeMarshaller.readSize(entryBytes)); + initKeyOffset(entryBytes.position()); + } + + public void writeNewEntry(long pos, Data key) { + initPos(pos); + initKeySize(key.size()); + entryBytes.position(keySizeOffset); + hh.h().keySizeMarshaller.writeSize(entryBytes, keySize); + initKeyOffset(entryBytes.position()); + key.writeTo(entryBS, keyOffset); + } + + public void copyExistingEntry(long newPos, long bytesToCopy) { + long oldKeySizeOffset = keySizeOffset; + long oldKeyOffset = keyOffset; + initPos(newPos); + initKeyOffset(keySizeOffset + (oldKeyOffset - oldKeySizeOffset)); + entryBS.write(keySizeOffset, entryBS, oldKeySizeOffset, bytesToCopy); + } + + public long keyEnd() { + return keyOffset + keySize; + } + + protected long entryEnd() { + return keyEnd(); + } + + long entrySize() { + return entryEnd() - keySizeOffset; + } + + @StageRef EntryKeyBytesData entryKey; + + @NotNull + @Override + public Data key() { + checkOnEachPublicOperation.checkOnEachPublicOperation(); + return entryKey; + } + + @Stage("TheEntrySizeInChunks") public int entrySizeInChunks = 0; + + void initTheEntrySizeInChunks() { + entrySizeInChunks = hh.h().inChunks(entrySize()); + } + + public void initTheEntrySizeInChunks(int actuallyUsedChunks) { + entrySizeInChunks = actuallyUsedChunks; + } + + public void innerRemoveEntryExceptHashLookupUpdate() { + s.free(pos, entrySizeInChunks); + s.entries(s.entries() - 1L); + s.incrementModCount(); + } +} diff --git a/src/main/java/net/openhft/chronicle/hash/impl/stage/entry/HashLookup.java b/src/main/java/net/openhft/chronicle/hash/impl/stage/entry/HashLookup.java new file mode 100644 index 000000000..f5b8dc769 --- /dev/null +++ b/src/main/java/net/openhft/chronicle/hash/impl/stage/entry/HashLookup.java @@ -0,0 +1,238 @@ +/* + * Copyright 2015 Higher Frequency Trading + * + * http://www.higherfrequencytrading.com + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package net.openhft.chronicle.hash.impl.stage.entry; + +import net.openhft.chronicle.hash.impl.VanillaChronicleHashHolder; +import net.openhft.chronicle.hash.impl.hashlookup.EntryConsumer; +import net.openhft.lang.Maths; +import net.openhft.sg.Stage; +import net.openhft.sg.StageRef; +import net.openhft.sg.Staged; + +import static net.openhft.lang.MemoryUnit.BITS; +import static net.openhft.lang.MemoryUnit.BYTES; +import static net.openhft.lang.io.NativeBytes.UNSAFE; + +@Staged +public class HashLookup { + // to fit 64 bits per slot. + public static final int MAX_SEGMENT_CHUNKS = 1 << 30; + public static final int MAX_SEGMENT_ENTRIES = 1 << 29; + + + public static int valueBits(long actualChunksPerSegment) { + return 64 - Long.numberOfLeadingZeros(actualChunksPerSegment - 1L); + } + + public static int keyBits(long entriesPerSegment, int valueBits) { + // key hash cardinality is between 1.0 and 2.0 of key cardinality + int minKeyBits = 64 - Long.numberOfLeadingZeros(entriesPerSegment - 1L); + // This minimizes probability of hash collision => on search, additional cache line touch + // and key comparison, that is quite high cost. + // between 8.0 and 16.0 + minKeyBits += 3; + int actualEntryBits = (int) BYTES.align((long) (minKeyBits + valueBits), BITS); + // devote the rest bits for key + return actualEntryBits - valueBits; + } + + public static int entrySize(int keyBits, int valueBits) { + return (int) BYTES.alignAndConvert((long) (keyBits + valueBits), BITS); + } + + public static long capacityFor(long entriesPerSegment) { + if (entriesPerSegment < 0L) + throw new IllegalArgumentException("entriesPerSegment should be positive"); + long capacity = Maths.nextPower2(entriesPerSegment, 64L); + if (((double) entriesPerSegment) / (double) capacity > 2./3.) { + // hash lookup shouldn't be too dense + capacity <<= 1L; + } + return capacity; + } + + public static long mask(int bits) { + return (1L << bits) - 1L; + } + + public static final long UNSET_KEY = 0L; + public static final long UNSET_ENTRY = 0L; + + @Stage("SegmentHashLookup") long address = -1; + @Stage("SegmentHashLookup") long capacityMask; + @Stage("SegmentHashLookup") int hashLookupEntrySize; + @Stage("SegmentHashLookup") long capacityMask2; + @Stage("SegmentHashLookup") int keyBits; + @Stage("SegmentHashLookup") long keyMask; + @Stage("SegmentHashLookup") long valueMask; + @Stage("SegmentHashLookup") long entryMask; + + public void initSegmentHashLookup( + long address, long capacity, int entrySize, int keyBits, int valueBits) { + innerInitSegmentHashLookup(address, capacity, entrySize, keyBits, valueBits); + } + + @Stage("SegmentHashLookup") + private void innerInitSegmentHashLookup( + long address, long capacity, int entrySize, int keyBits, int valueBits) { + this.address = address; + + this.capacityMask = capacity - 1L; + + this.hashLookupEntrySize = entrySize; + this.capacityMask2 = capacityMask * entrySize; + + this.keyBits = keyBits; + this.keyMask = mask(keyBits); + this.valueMask = mask(valueBits); + this.entryMask = mask(keyBits + valueBits); + } + + @StageRef VanillaChronicleHashHolder hh; + @StageRef SegmentStages s; + + public void initSegmentHashLookup() { + long hashLookupOffset = hh.h().segmentOffset(s.segmentIndex); + innerInitSegmentHashLookup(hh.h().ms.address() + hashLookupOffset, + hh.h().segmentHashLookupCapacity, hh.h().segmentHashLookupEntrySize, + hh.h().segmentHashLookupKeyBits, hh.h().segmentHashLookupValueBits); + + } + + long indexToPos(long index) { + return index * hashLookupEntrySize; + } + + public long maskUnsetKey(long key) { + return (key &= keyMask) != UNSET_KEY ? key : keyMask; + } + + public void checkValueForPut(long value) { + assert (value & ~valueMask) == 0L : "Value out of range, was " + value; + } + + public boolean empty(long entry) { + return (entry & entryMask) == UNSET_ENTRY; + } + + public long key(long entry) { + return entry & keyMask; + } + + public long value(long entry) { + return (entry >>> keyBits) & valueMask; + } + + long entry(long key, long value) { + return key | (value << keyBits); + } + + public long hlPos(long key) { + return indexToPos(key & capacityMask); + } + + public long step(long pos) { + return (pos += hashLookupEntrySize) <= capacityMask2 ? pos : 0L; + } + + public long stepBack(long pos) { + return (pos -= hashLookupEntrySize) >= 0 ? pos : capacityMask2; + } + + public long readEntry(long pos) { + return UNSAFE.getLong(address + pos); + } + + public void writeEntry(long pos, long prevEntry, long key, long value) { + long entry = (prevEntry & ~entryMask) | entry(key, value); + UNSAFE.putLong(address + pos, entry); + } + + public void writeEntryVolatile(long pos, long prevEntry, long key, long value) { + long entry = (prevEntry & ~entryMask) | entry(key, value); + UNSAFE.putLongVolatile(null, address + pos, entry); + } + + public void putValueVolatile(long pos, long value) { + checkValueForPut(value); + long currentEntry = readEntry(pos); + writeEntryVolatile(pos, currentEntry, key(currentEntry), value); + } + + void writeEntry(long pos, long prevEntry, long anotherEntry) { + long entry = (prevEntry & ~entryMask) | (anotherEntry & entryMask); + UNSAFE.putLong(address + pos, entry); + } + + void clearEntry(long pos, long prevEntry) { + long entry = (prevEntry & ~entryMask); + UNSAFE.putLong(address + pos, entry); + } + + public void clearHashLookup() { + UNSAFE.setMemory(address, capacityMask2 + hashLookupEntrySize, (byte) 0); + } + + /** + * Returns "insert" position in terms of consequent putValue() + */ + public long remove(long posToRemove) { + long entryToRemove = readEntry(posToRemove); + long posToShift = posToRemove; + while (true) { + posToShift = step(posToShift); + long entryToShift = readEntry(posToShift); + if (empty(entryToShift)) + break; + long insertPos = hlPos(key(entryToShift)); + // the following condition essentially means circular permutations + // of three (r = posToRemove, s = posToShift, i = insertPos) + // positions are accepted: + // [...i..r...s.] or + // [...r..s...i.] or + // [...s..i...r.] + boolean cond1 = insertPos <= posToRemove; + boolean cond2 = posToRemove <= posToShift; + if ((cond1 && cond2) || + // chain wrapped around capacity + (posToShift < insertPos && (cond1 || cond2))) { + writeEntry(posToRemove, entryToRemove, entryToShift); + posToRemove = posToShift; + entryToRemove = entryToShift; + } + } + clearEntry(posToRemove, entryToRemove); + return posToRemove; + } + + String hashLookupToString() { + final StringBuilder sb = new StringBuilder("{"); + forEach((key, value) -> sb.append(key).append('=').append(value).append(',')); + sb.append('}'); + return sb.toString(); + } + + void forEach(EntryConsumer action) { + for (long pos = 0L; pos <= capacityMask2; pos += hashLookupEntrySize) { + long entry = readEntry(pos); + if (!empty(entry)) + action.accept(key(entry), value(entry)); + } + } +} diff --git a/src/main/java/net/openhft/chronicle/hash/impl/stage/entry/HashLookupPos.java b/src/main/java/net/openhft/chronicle/hash/impl/stage/entry/HashLookupPos.java new file mode 100644 index 000000000..c1d3ddb68 --- /dev/null +++ b/src/main/java/net/openhft/chronicle/hash/impl/stage/entry/HashLookupPos.java @@ -0,0 +1,23 @@ +package net.openhft.chronicle.hash.impl.stage.entry; + +import net.openhft.sg.Stage; +import net.openhft.sg.Staged; + +@Staged +public abstract class HashLookupPos { + + public long hashLookupPos = -1; + + public abstract boolean hashLookupPosInit(); + + public void initHashLookupPos(long hashLookupPos) { + this.hashLookupPos = hashLookupPos; + } + + @Stage("HashLookupPos") + public void setHashLookupPos(long hashLookupPos) { + this.hashLookupPos = hashLookupPos; + } + + public abstract void closeHashLookupPos(); +} diff --git a/src/main/java/net/openhft/chronicle/hash/impl/stage/entry/ReadLock.java b/src/main/java/net/openhft/chronicle/hash/impl/stage/entry/ReadLock.java new file mode 100644 index 000000000..20bc158e4 --- /dev/null +++ b/src/main/java/net/openhft/chronicle/hash/impl/stage/entry/ReadLock.java @@ -0,0 +1,107 @@ +/* + * Copyright 2015 Higher Frequency Trading + * + * http://www.higherfrequencytrading.com + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package net.openhft.chronicle.hash.impl.stage.entry; + +import net.openhft.sg.StageRef; +import net.openhft.sg.Staged; +import net.openhft.chronicle.hash.locks.InterProcessLock; +import org.jetbrains.annotations.NotNull; + +import java.util.concurrent.TimeUnit; + +import static net.openhft.chronicle.hash.impl.LocalLockState.READ_LOCKED; +import static net.openhft.chronicle.hash.impl.LocalLockState.UNLOCKED; + + +@Staged +public class ReadLock implements InterProcessLock { + + @StageRef SegmentStages s; + @StageRef HashEntryStages entry; + @StageRef HashLookupPos hlp; + + @Override + public boolean isHeldByCurrentThread() { + return s.localLockState.read; + } + + @Override + public void lock() { + if (s.localLockState == UNLOCKED) { + s.segmentHeader.readLock(s.segmentHeaderAddress); + s.setLocalLockState(READ_LOCKED); + } + } + + @Override + public void lockInterruptibly() throws InterruptedException { + if (s.localLockState == UNLOCKED) { + s.segmentHeader.readLockInterruptibly(s.segmentHeaderAddress); + s.setLocalLockState(READ_LOCKED); + } + } + + @Override + public boolean tryLock() { + if (s.localLockState == UNLOCKED) { + if (s.segmentHeader.tryReadLock(s.segmentHeaderAddress)) { + s.setLocalLockState(READ_LOCKED); + return true; + } else { + return false; + } + } else { + return true; + } + } + + @Override + public boolean tryLock(long time, @NotNull TimeUnit unit) throws InterruptedException { + if (s.localLockState == UNLOCKED) { + if (s.segmentHeader.tryReadLock(s.segmentHeaderAddress, time, unit)) { + s.setLocalLockState(READ_LOCKED); + return true; + } else { + return false; + } + } else { + return true; + } + } + + @Override + public void unlock() { + switch (s.localLockState) { + case UNLOCKED: + return; + case READ_LOCKED: + s.segmentHeader.readUnlock(s.segmentHeaderAddress); + break; + case UPDATE_LOCKED: + s.segmentHeader.updateUnlock(s.segmentHeaderAddress); + break; + case WRITE_LOCKED: + s.segmentHeader.writeUnlock(s.segmentHeaderAddress); + } + s.setLocalLockState(UNLOCKED); + // TODO what should close here? + hlp.closeHashLookupPos(); + entry.closePos(); + } +} diff --git a/src/main/java/net/openhft/chronicle/hash/impl/stage/entry/SegmentStages.java b/src/main/java/net/openhft/chronicle/hash/impl/stage/entry/SegmentStages.java new file mode 100644 index 000000000..b984320f5 --- /dev/null +++ b/src/main/java/net/openhft/chronicle/hash/impl/stage/entry/SegmentStages.java @@ -0,0 +1,368 @@ +/* + * Copyright 2015 Higher Frequency Trading + * + * http://www.higherfrequencytrading.com + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package net.openhft.chronicle.hash.impl.stage.entry; + +import net.openhft.chronicle.hash.impl.BigSegmentHeader; +import net.openhft.chronicle.hash.impl.LocalLockState; +import net.openhft.chronicle.hash.impl.SegmentHeader; +import net.openhft.chronicle.hash.impl.VanillaChronicleHash; +import net.openhft.chronicle.hash.impl.stage.hash.Chaining; +import net.openhft.chronicle.hash.impl.stage.hash.CheckOnEachPublicOperation; +import net.openhft.chronicle.hash.impl.VanillaChronicleHashHolder; +import net.openhft.chronicle.hash.locks.InterProcessLock; +import net.openhft.chronicle.hash.locks.InterProcessReadWriteUpdateLock; +import net.openhft.lang.collection.DirectBitSet; +import net.openhft.lang.collection.SingleThreadedDirectBitSet; +import net.openhft.lang.io.MultiStoreBytes; +import net.openhft.sg.Stage; +import net.openhft.sg.Staged; +import net.openhft.sg.StageRef; +import org.jetbrains.annotations.NotNull; + +import static net.openhft.chronicle.hash.impl.LocalLockState.UNLOCKED; + +@Staged +public abstract class SegmentStages implements InterProcessReadWriteUpdateLock { + + @StageRef Chaining chaining; + @StageRef public VanillaChronicleHashHolder hh; + @StageRef public CheckOnEachPublicOperation checkOnEachPublicOperation; + + @Stage("TheSegmentIndex") public int segmentIndex = -1; + + public void initTheSegmentIndex(int segmentIndex) { + this.segmentIndex = segmentIndex; + + } + + @Stage("SegHeader") long segmentHeaderAddress; + @Stage("SegHeader") SegmentHeader segmentHeader = null; + + private void initSegHeader() { + segmentHeaderAddress = hh.h().ms.address() + hh.h().segmentHeaderOffset(segmentIndex); + segmentHeader = BigSegmentHeader.INSTANCE; + } + + public long entries() { + return segmentHeader.size(segmentHeaderAddress); + } + + public void entries(long size) { + segmentHeader.size(segmentHeaderAddress, size); + } + + long nextPosToSearchFrom() { + return segmentHeader.nextPosToSearchFrom(segmentHeaderAddress); + } + + public void nextPosToSearchFrom(long nextPosToSearchFrom) { + segmentHeader.nextPosToSearchFrom(segmentHeaderAddress, nextPosToSearchFrom); + } + + public long deleted() { + return segmentHeader.deleted(segmentHeaderAddress); + } + + public void deleted(long deleted) { + segmentHeader.deleted(segmentHeaderAddress, deleted); + } + + public long size() { + return entries() - deleted(); + } + + + @Stage("Locks") public SegmentStages rootContextOnThisSegment = null; + /** + * See the ChMap Ops spec, considerations of nested same-thread concurrent contexts. + * Once context enters the segment, and observes concurrent same-thread context, + * it sets concurrentSameThreadContexts = true for itself and that concurrent context. + * This flag is not dropped on exit of one of these contexts, because between calls of + * this context, nested one could be initialized, does some changes that break our thread-local + * assumptions _and exit_, that is why on exit concurrent context should remain "dirty". + */ + @Stage("Locks") public boolean concurrentSameThreadContexts; + + @Stage("Locks") public int latestSameThreadSegmentModCount; + @Stage("Locks") public int contextModCount; + + @Stage("Locks") + public void incrementModCount() { + contextModCount = rootContextOnThisSegment.latestSameThreadSegmentModCount = + rootContextOnThisSegment.latestSameThreadSegmentModCount + 1; + } + + // chain + @Stage("Locks") SegmentStages nextNode; + + @Stage("Locks") LocalLockState localLockState; + @Stage("Locks") int totalReadLockCount; + @Stage("Locks") int totalUpdateLockCount; + @Stage("Locks") int totalWriteLockCount; + + public abstract boolean locksInit(); + + void initLocks() { + localLockState = UNLOCKED; + int indexOfThisContext = chaining.indexInContextChain; + for (int i = indexOfThisContext - 1; i >= 0; i--) { + if (tryFindInitLocksOfThisSegment(this, i)) + return; + } + for (int i = indexOfThisContext + 1, size = chaining.contextChain.size(); i < size; i++) { + if (tryFindInitLocksOfThisSegment(this, i)) + return; + } + rootContextOnThisSegment = this; + concurrentSameThreadContexts = false; + latestSameThreadSegmentModCount = 0; + contextModCount = 0; + nextNode = null; + totalReadLockCount = 0; + totalUpdateLockCount = 0; + totalWriteLockCount = 0; + } + + boolean tryFindInitLocksOfThisSegment(Object thisContext, int index) { + SegmentStages c = chaining.contextAtIndexInChain(index); + if (c.segmentHeader != null && c.segmentHeaderAddress == segmentHeaderAddress && + c.rootContextOnThisSegment != null) { + //TODO implement nested contexts. Hardest part - bodies of Read/Update/WriteLock classes + throw new IllegalStateException("Nested context not implemented yet"); + } else { + return false; + } + } + + void closeLocks() { + // TODO should throw ISE on attempt to close root context when children not closed + if (rootContextOnThisSegment == this) { + closeRootLocks(); + } else { + closeNestedLocks(); + } + localLockState = null; + rootContextOnThisSegment = null; + } + + @Stage("Locks") + private void closeNestedLocks() { + unlinkFromSegmentContextsChain(); + + switch (localLockState) { + case UNLOCKED: + break; + case READ_LOCKED: + int newTotalReadLockCount = this.rootContextOnThisSegment.totalReadLockCount -= 1; + if (newTotalReadLockCount == 0) { + if (this.rootContextOnThisSegment.totalUpdateLockCount == 0 && + this.rootContextOnThisSegment.totalWriteLockCount == 0) { + segmentHeader.readUnlock(segmentHeaderAddress); + } + } else if (newTotalReadLockCount < 0) { + throw new IllegalStateException("read underflow"); + } + break; + case UPDATE_LOCKED: + int newTotalUpdateLockCount = + this.rootContextOnThisSegment.totalUpdateLockCount -= 1; + if (newTotalUpdateLockCount == 0) { + if (this.rootContextOnThisSegment.totalWriteLockCount == 0) { + if (this.rootContextOnThisSegment.totalReadLockCount == 0) { + segmentHeader.updateUnlock(segmentHeaderAddress); + } else { + segmentHeader.downgradeUpdateToReadLock(segmentHeaderAddress); + } + } + } else if (newTotalUpdateLockCount < 0) { + throw new IllegalStateException("update underflow"); + } + break; + case WRITE_LOCKED: + int newTotalWriteLockCount = this.rootContextOnThisSegment.totalWriteLockCount -= 1; + if (newTotalWriteLockCount == 0) { + if (this.rootContextOnThisSegment.totalUpdateLockCount > 0) { + segmentHeader.downgradeWriteToUpdateLock(segmentHeaderAddress); + } else { + if (this.rootContextOnThisSegment.totalReadLockCount > 0) { + segmentHeader.downgradeWriteToReadLock(segmentHeaderAddress); + } else { + segmentHeader.writeUnlock(segmentHeaderAddress); + } + } + } + break; + } + } + + @Stage("Locks") + private void unlinkFromSegmentContextsChain() { + SegmentStages prevContext = this.rootContextOnThisSegment; + while (true) { + assert prevContext.nextNode != null; + if (prevContext.nextNode == this) + break; + prevContext = prevContext.nextNode; + } + assert nextNode == null; + prevContext.nextNode = null; + } + + @Stage("Locks") + private void closeRootLocks() { + assert nextNode == null; + + + switch (localLockState) { + case UNLOCKED: + return; + case READ_LOCKED: + segmentHeader.readUnlock(segmentHeaderAddress); + return; + case UPDATE_LOCKED: + segmentHeader.updateUnlock(segmentHeaderAddress); + return; + case WRITE_LOCKED: + segmentHeader.writeUnlock(segmentHeaderAddress); + } + } + + @Stage("Locks") + public void setLocalLockState(LocalLockState newState) { + localLockState = newState; + } + + // TODO their isHeldByCurrentThread should be _context_ local + // i. e. if outer same-thread context hold the lock, isHeld() should be false, but + // lock() op could be shallow + @StageRef public ReadLock innerReadLock; + @StageRef public UpdateLock innerUpdateLock; + @StageRef public WriteLock innerWriteLock; + + + @NotNull + @Override + public InterProcessLock readLock() { + checkOnEachPublicOperation.checkOnEachPublicOperation(); + return innerReadLock; + } + + @NotNull + @Override + public InterProcessLock updateLock() { + checkOnEachPublicOperation.checkOnEachPublicOperation(); + return innerUpdateLock; + } + + @NotNull + @Override + public InterProcessLock writeLock() { + checkOnEachPublicOperation.checkOnEachPublicOperation(); + return innerWriteLock; + } + + + @StageRef public HashLookup hashLookup; + + @Stage("Segment") MultiStoreBytes freeListBytes = new MultiStoreBytes(); + @Stage("Segment") public SingleThreadedDirectBitSet freeList = new SingleThreadedDirectBitSet(); + @Stage("Segment") long entrySpaceOffset = 0; + + boolean segmentInit() { + return entrySpaceOffset > 0; + } + + void initSegment() { + VanillaChronicleHash h = hh.h(); + long hashLookupOffset = h.segmentOffset(segmentIndex); + long freeListOffset = hashLookupOffset + h.segmentHashLookupOuterSize; + freeListBytes.storePositionAndSize(h.ms, freeListOffset, h.segmentFreeListInnerSize); + freeList.reuse(freeListBytes); + entrySpaceOffset = freeListOffset + h.segmentFreeListOuterSize + + h.segmentEntrySpaceInnerOffset; + } + + void closeSegment() { + entrySpaceOffset = 0; + } + + //TODO refactor/optimize + public long alloc(int chunks) { + VanillaChronicleHash h = hh.h(); + if (chunks > h.maxChunksPerEntry) + throw new IllegalArgumentException("Entry is too large: requires " + chunks + + " entry size chucks, " + h.maxChunksPerEntry + " is maximum."); + long ret = freeList.setNextNContinuousClearBits(nextPosToSearchFrom(), chunks); + if (ret == DirectBitSet.NOT_FOUND || ret + chunks > h.actualChunksPerSegment) { + if (ret != DirectBitSet.NOT_FOUND && + ret + chunks > h.actualChunksPerSegment && ret < h.actualChunksPerSegment) + freeList.clear(ret, h.actualChunksPerSegment); + ret = freeList.setNextNContinuousClearBits(0L, chunks); + if (ret == DirectBitSet.NOT_FOUND || ret + chunks > h.actualChunksPerSegment) { + if (ret != DirectBitSet.NOT_FOUND && + ret + chunks > h.actualChunksPerSegment && + ret < h.actualChunksPerSegment) + freeList.clear(ret, h.actualChunksPerSegment); + if (chunks == 1) { + throw new IllegalStateException( + "Segment is full, no free entries found"); + } else { + throw new IllegalStateException( + "Segment is full or has no ranges of " + chunks + + " continuous free chunks" + ); + } + } + updateNextPosToSearchFrom(ret, chunks); + } else { + // if bit at nextPosToSearchFrom is clear, it was skipped because + // more than 1 chunk was requested. Don't move nextPosToSearchFrom + // in this case. chunks == 1 clause is just a fast path. + if (chunks == 1 || freeList.isSet(nextPosToSearchFrom())) { + updateNextPosToSearchFrom(ret, chunks); + } + } + return ret; + } + + public void free(long fromPos, int chunks) { + freeList.clear(fromPos, fromPos + chunks); + if (fromPos < nextPosToSearchFrom()) + nextPosToSearchFrom(fromPos); + } + + public void updateNextPosToSearchFrom(long allocated, int chunks) { + long nextPosToSearchFrom = allocated + chunks; + if (nextPosToSearchFrom >= hh.h().actualChunksPerSegment) + nextPosToSearchFrom = 0L; + nextPosToSearchFrom(nextPosToSearchFrom); + } + + public void clearSegment() { + innerWriteLock.lock(); + hashLookup.clearHashLookup(); + freeList.clear(); + nextPosToSearchFrom(0L); + entries(0L); + } + + public void clear() { + clearSegment(); + } +} diff --git a/src/main/java/net/openhft/chronicle/hash/impl/stage/entry/UpdateLock.java b/src/main/java/net/openhft/chronicle/hash/impl/stage/entry/UpdateLock.java new file mode 100644 index 000000000..67cd5edfd --- /dev/null +++ b/src/main/java/net/openhft/chronicle/hash/impl/stage/entry/UpdateLock.java @@ -0,0 +1,131 @@ +/* + * Copyright 2015 Higher Frequency Trading + * + * http://www.higherfrequencytrading.com + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package net.openhft.chronicle.hash.impl.stage.entry; + +import net.openhft.sg.StageRef; +import net.openhft.sg.Staged; +import net.openhft.chronicle.hash.locks.InterProcessLock; +import org.jetbrains.annotations.NotNull; + +import java.util.concurrent.TimeUnit; + +import static net.openhft.chronicle.hash.impl.LocalLockState.READ_LOCKED; +import static net.openhft.chronicle.hash.impl.LocalLockState.UPDATE_LOCKED; + +@Staged +public class UpdateLock implements InterProcessLock { + + @StageRef SegmentStages s; + + @Override + public boolean isHeldByCurrentThread() { + return s.localLockState.update; + } + + @Override + public void lock() { + switch (s.localLockState) { + case UNLOCKED: + s.segmentHeader.updateLock(s.segmentHeaderAddress); + s.setLocalLockState(UPDATE_LOCKED); + return; + case READ_LOCKED: + throw forbiddenUpgrade(); + case UPDATE_LOCKED: + case WRITE_LOCKED: + // do nothing + } + } + + /** + * Non-static because after compilation it becomes inner class which forbids static methods + */ + @NotNull + private IllegalMonitorStateException forbiddenUpgrade() { + return new IllegalMonitorStateException("Cannot upgrade from read to update lock"); + } + + @Override + public void lockInterruptibly() throws InterruptedException { + switch (s.localLockState) { + case UNLOCKED: + s.segmentHeader.updateLockInterruptibly(s.segmentHeaderAddress); + s.setLocalLockState(UPDATE_LOCKED); + return; + case READ_LOCKED: + throw forbiddenUpgrade(); + case UPDATE_LOCKED: + case WRITE_LOCKED: + // do nothing + } + } + + @Override + public boolean tryLock() { + switch (s.localLockState) { + case UNLOCKED: + if (s.segmentHeader.tryUpdateLock(s.segmentHeaderAddress)) { + s.setLocalLockState(UPDATE_LOCKED); + return true; + } else { + return false; + } + case READ_LOCKED: + throw forbiddenUpgrade(); + case UPDATE_LOCKED: + case WRITE_LOCKED: + return true; + } + throw new AssertionError(); + } + + @Override + public boolean tryLock(long time, @NotNull TimeUnit unit) throws InterruptedException { + switch (s.localLockState) { + case UNLOCKED: + if (s.segmentHeader.tryUpdateLock(s.segmentHeaderAddress, time, unit)) { + s.setLocalLockState(UPDATE_LOCKED); + return true; + } else { + return false; + } + case READ_LOCKED: + throw forbiddenUpgrade(); + case UPDATE_LOCKED: + case WRITE_LOCKED: + return true; + } + throw new AssertionError(); + } + + @Override + public void unlock() { + switch (s.localLockState) { + case UNLOCKED: + case READ_LOCKED: + return; + case UPDATE_LOCKED: + s.segmentHeader.downgradeUpdateToReadLock(s.segmentHeaderAddress); + break; + case WRITE_LOCKED: + s.segmentHeader.downgradeWriteToReadLock(s.segmentHeaderAddress); + } + s.setLocalLockState(READ_LOCKED); + } +} diff --git a/src/main/java/net/openhft/chronicle/hash/impl/stage/entry/WriteLock.java b/src/main/java/net/openhft/chronicle/hash/impl/stage/entry/WriteLock.java new file mode 100644 index 000000000..b10e9f554 --- /dev/null +++ b/src/main/java/net/openhft/chronicle/hash/impl/stage/entry/WriteLock.java @@ -0,0 +1,146 @@ +/* + * Copyright 2015 Higher Frequency Trading + * + * http://www.higherfrequencytrading.com + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package net.openhft.chronicle.hash.impl.stage.entry; + +import net.openhft.sg.StageRef; +import net.openhft.sg.Staged; +import net.openhft.chronicle.hash.locks.InterProcessLock; +import org.jetbrains.annotations.NotNull; + +import java.util.concurrent.TimeUnit; + +import static net.openhft.chronicle.hash.impl.LocalLockState.UPDATE_LOCKED; +import static net.openhft.chronicle.hash.impl.LocalLockState.WRITE_LOCKED; + +@Staged +public class WriteLock implements InterProcessLock { + + @StageRef SegmentStages s; + + @Override + public boolean isHeldByCurrentThread() { + return s.localLockState.write; + } + + @Override + public void lock() { + switch (s.localLockState) { + case UNLOCKED: + s.segmentHeader.writeLock(s.segmentHeaderAddress); + s.setLocalLockState(WRITE_LOCKED); + return; + case READ_LOCKED: + throw forbiddenUpgrade(); + case UPDATE_LOCKED: + s.segmentHeader.upgradeUpdateToWriteLock(s.segmentHeaderAddress); + s.setLocalLockState(WRITE_LOCKED); + case WRITE_LOCKED: + // do nothing + } + } + + /** + * Non-static because after compilation it becomes inner class which forbids static methods + */ + @NotNull + private IllegalMonitorStateException forbiddenUpgrade() { + return new IllegalMonitorStateException("Cannot upgrade from read to write lock"); + } + + @Override + public void lockInterruptibly() throws InterruptedException { + switch (s.localLockState) { + case UNLOCKED: + s.segmentHeader.writeLockInterruptibly(s.segmentHeaderAddress); + s.setLocalLockState(WRITE_LOCKED); + return; + case READ_LOCKED: + throw forbiddenUpgrade(); + case UPDATE_LOCKED: + s.segmentHeader.upgradeUpdateToWriteLockInterruptibly(s.segmentHeaderAddress); + s.setLocalLockState(WRITE_LOCKED); + case WRITE_LOCKED: + // do nothing + } + } + + @Override + public boolean tryLock() { + switch (s.localLockState) { + case UNLOCKED: + if (s.segmentHeader.tryWriteLock(s.segmentHeaderAddress)) { + s.setLocalLockState(WRITE_LOCKED); + return true; + } else { + return false; + } + case READ_LOCKED: + throw forbiddenUpgrade(); + case UPDATE_LOCKED: + if (s.segmentHeader.tryUpgradeUpdateToWriteLock(s.segmentHeaderAddress)) { + s.setLocalLockState(WRITE_LOCKED); + return true; + } else { + return false; + } + case WRITE_LOCKED: + return true; + } + throw new AssertionError(); + } + + @Override + public boolean tryLock(long time, @NotNull TimeUnit unit) throws InterruptedException { + switch (s.localLockState) { + case UNLOCKED: + if (s.segmentHeader.tryWriteLock(s.segmentHeaderAddress, time, unit)) { + s.setLocalLockState(WRITE_LOCKED); + return true; + } else { + return false; + } + case READ_LOCKED: + throw forbiddenUpgrade(); + case UPDATE_LOCKED: + if (s.segmentHeader.tryUpgradeUpdateToWriteLock( + s.segmentHeaderAddress, time, unit)) { + s.setLocalLockState(WRITE_LOCKED); + return true; + } else { + return false; + } + case WRITE_LOCKED: + return true; + } + throw new AssertionError(); + } + + @Override + public void unlock() { + switch (s.localLockState) { + case UNLOCKED: + case READ_LOCKED: + case UPDATE_LOCKED: + return; + case WRITE_LOCKED: + s.segmentHeader.downgradeWriteToUpdateLock(s.segmentHeaderAddress); + } + s.setLocalLockState(UPDATE_LOCKED); + } +} diff --git a/src/main/java/net/openhft/chronicle/hash/impl/stage/hash/Chaining.java b/src/main/java/net/openhft/chronicle/hash/impl/stage/hash/Chaining.java new file mode 100644 index 000000000..79274ec64 --- /dev/null +++ b/src/main/java/net/openhft/chronicle/hash/impl/stage/hash/Chaining.java @@ -0,0 +1,87 @@ +/* + * Copyright 2015 Higher Frequency Trading + * + * http://www.higherfrequencytrading.com + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package net.openhft.chronicle.hash.impl.stage.hash; + +import net.openhft.sg.Staged; + +import java.util.ArrayList; +import java.util.List; + +@Staged +public class Chaining { + + public final List contextChain; + public final int indexInContextChain; + + public Chaining() { + contextChain = new ArrayList<>(); + contextChain.add(this); + indexInContextChain = 0; + } + + public Chaining(Chaining root) { + contextChain = root.contextChain; + indexInContextChain = contextChain.size(); + contextChain.add(this); + } + + public T contextAtIndexInChain(int index) { + //noinspection unchecked + return (T) contextChain.get(index); + } + + + boolean used; + + public boolean usedInit() { + return used; + } + + public void initUsed(boolean used) { + this.used = used; + } + + void closeUsed() { + used = false; + } + + public T getContext() { + for (Chaining context : contextChain) { + if (!context.usedInit()) { + //noinspection unchecked + return (T) context; + } + } + int maxNestedContexts = 1 << 16; + if (contextChain.size() > maxNestedContexts) { + throw new IllegalStateException("More than " + maxNestedContexts + + " nested ChronicleHash contexts are not supported. Very probable that " + + "you simply forgot to close context somewhere (recommended to use " + + "try-with-resources statement). " + + "Otherwise this is a bug, please report with this " + + "stack trace on https://github.com/OpenHFT/Chronicle-Map/issues"); + } + //noinspection unchecked + return (T) createChaining(); + } + + public Chaining createChaining() { + return new Chaining(this); + } +} diff --git a/src/main/java/net/openhft/chronicle/hash/impl/stage/hash/CheckOnEachPublicOperation.java b/src/main/java/net/openhft/chronicle/hash/impl/stage/hash/CheckOnEachPublicOperation.java new file mode 100644 index 000000000..d40e582bf --- /dev/null +++ b/src/main/java/net/openhft/chronicle/hash/impl/stage/hash/CheckOnEachPublicOperation.java @@ -0,0 +1,32 @@ +/* + * Copyright 2015 Higher Frequency Trading + * + * http://www.higherfrequencytrading.com + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package net.openhft.chronicle.hash.impl.stage.hash; + +import net.openhft.sg.StageRef; +import net.openhft.sg.Staged; + +@Staged +public abstract class CheckOnEachPublicOperation { + + @StageRef OwnerThreadHolder holder; + + public void checkOnEachPublicOperation() { + holder.checkAccessingFromOwnerThread(); + } +} diff --git a/src/main/java/net/openhft/chronicle/hash/impl/stage/hash/KeyBytesInterop.java b/src/main/java/net/openhft/chronicle/hash/impl/stage/hash/KeyBytesInterop.java new file mode 100644 index 000000000..60653eef4 --- /dev/null +++ b/src/main/java/net/openhft/chronicle/hash/impl/stage/hash/KeyBytesInterop.java @@ -0,0 +1,41 @@ +/* + * Copyright 2015 Higher Frequency Trading + * + * http://www.higherfrequencytrading.com + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package net.openhft.chronicle.hash.impl.stage.hash; + +import net.openhft.chronicle.hash.impl.VanillaChronicleHashHolder; +import net.openhft.chronicle.hash.serialization.BytesReader; +import net.openhft.chronicle.hash.serialization.internal.MetaBytesInterop; +import net.openhft.sg.StageRef; +import net.openhft.sg.Staged; + +@Staged +public class KeyBytesInterop> { + @StageRef + VanillaChronicleHashHolder hh; + @StageRef ThreadLocalCopiesHolder ch; + + public final BytesReader keyReader = + hh.h().keyReaderProvider.get(ch.copies, hh.h().originalKeyReader); + public final KI keyInterop = hh.h().keyInteropProvider.get(ch.copies, hh.h().originalKeyInterop); + + public MKI keyMetaInterop(K key) { + return hh.h().metaKeyInteropProvider.get( + ch.copies, hh.h().originalMetaKeyInterop, keyInterop, key); + } +} diff --git a/src/main/java/net/openhft/chronicle/hash/impl/stage/hash/LogHolder.java b/src/main/java/net/openhft/chronicle/hash/impl/stage/hash/LogHolder.java new file mode 100644 index 000000000..168bf073f --- /dev/null +++ b/src/main/java/net/openhft/chronicle/hash/impl/stage/hash/LogHolder.java @@ -0,0 +1,10 @@ +package net.openhft.chronicle.hash.impl.stage.hash; + +import net.openhft.sg.Staged; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +@Staged +public class LogHolder { + public static final Logger LOG = LoggerFactory.getLogger(LogHolder.class); +} diff --git a/src/main/java/net/openhft/chronicle/hash/impl/stage/hash/OwnerThreadHolder.java b/src/main/java/net/openhft/chronicle/hash/impl/stage/hash/OwnerThreadHolder.java new file mode 100644 index 000000000..f95aa5deb --- /dev/null +++ b/src/main/java/net/openhft/chronicle/hash/impl/stage/hash/OwnerThreadHolder.java @@ -0,0 +1,36 @@ +/* + * Copyright 2015 Higher Frequency Trading + * + * http://www.higherfrequencytrading.com + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package net.openhft.chronicle.hash.impl.stage.hash; + +import net.openhft.sg.Staged; + +import java.util.ConcurrentModificationException; + +@Staged +public class OwnerThreadHolder { + + final Thread owner = Thread.currentThread(); + + public void checkAccessingFromOwnerThread() { + if (owner != Thread.currentThread()) { + throw new ConcurrentModificationException( + "Context shouldn't be accessed from multiple threads"); + } + } +} diff --git a/src/main/java/net/openhft/chronicle/hash/impl/stage/hash/ThreadLocalCopiesHolder.java b/src/main/java/net/openhft/chronicle/hash/impl/stage/hash/ThreadLocalCopiesHolder.java new file mode 100644 index 000000000..09151740e --- /dev/null +++ b/src/main/java/net/openhft/chronicle/hash/impl/stage/hash/ThreadLocalCopiesHolder.java @@ -0,0 +1,27 @@ +/* + * Copyright 2015 Higher Frequency Trading + * + * http://www.higherfrequencytrading.com + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package net.openhft.chronicle.hash.impl.stage.hash; + +import net.openhft.lang.threadlocal.ThreadLocalCopies; +import net.openhft.sg.Staged; + +@Staged +public class ThreadLocalCopiesHolder { + public final ThreadLocalCopies copies = ThreadLocalCopies.get(); +} diff --git a/src/main/java/net/openhft/chronicle/hash/impl/stage/input/HashInputBytes.java b/src/main/java/net/openhft/chronicle/hash/impl/stage/input/HashInputBytes.java new file mode 100644 index 000000000..e6f295d52 --- /dev/null +++ b/src/main/java/net/openhft/chronicle/hash/impl/stage/input/HashInputBytes.java @@ -0,0 +1,48 @@ +/* + * Copyright 2015 Higher Frequency Trading + * + * http://www.higherfrequencytrading.com + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package net.openhft.chronicle.hash.impl.stage.input; + +import net.openhft.chronicle.hash.impl.JavaLangBytesReusableBytesStore; +import net.openhft.chronicle.hash.impl.VanillaChronicleHashHolder; +import net.openhft.lang.io.Bytes; +import net.openhft.sg.Stage; +import net.openhft.sg.StageRef; +import net.openhft.sg.Staged; + +@Staged +public class HashInputBytes { + + @StageRef VanillaChronicleHashHolder hh; + + public Bytes inputBytes = null; + public final JavaLangBytesReusableBytesStore inputStore = new JavaLangBytesReusableBytesStore(); + + public void initInputBytes(Bytes inputBytes) { + this.inputBytes = inputBytes; + inputStore.setBytes(inputBytes); + } + + @Stage("InputKeyOffsets") public long inputKeySize = -1; + @Stage("InputKeyOffsets") public long inputKeyOffset; + + private void initInputKeyOffsets() { + inputKeySize = hh.h().keySizeMarshaller.readSize(inputBytes); + inputKeyOffset = inputBytes.position(); + } +} diff --git a/src/main/java/net/openhft/chronicle/hash/impl/stage/iter/HashSegmentIteration.java b/src/main/java/net/openhft/chronicle/hash/impl/stage/iter/HashSegmentIteration.java new file mode 100644 index 000000000..5d902c17e --- /dev/null +++ b/src/main/java/net/openhft/chronicle/hash/impl/stage/iter/HashSegmentIteration.java @@ -0,0 +1,112 @@ +/* + * Copyright 2015 Higher Frequency Trading + * + * http://www.higherfrequencytrading.com + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package net.openhft.chronicle.hash.impl.stage.iter; + +import net.openhft.chronicle.hash.HashEntry; +import net.openhft.chronicle.hash.impl.stage.entry.HashEntryStages; +import net.openhft.chronicle.hash.impl.stage.entry.HashLookup; +import net.openhft.chronicle.hash.impl.stage.entry.HashLookupPos; +import net.openhft.chronicle.hash.impl.stage.entry.SegmentStages; +import net.openhft.chronicle.hash.impl.stage.hash.CheckOnEachPublicOperation; +import net.openhft.sg.StageRef; +import net.openhft.sg.Staged; + +import java.util.function.Predicate; + +@Staged +public abstract class HashSegmentIteration> implements HashEntry { + + @StageRef public SegmentStages s; + @StageRef HashEntryStages e; + @StageRef protected HashLookup hashLookup; + @StageRef public CheckOnEachPublicOperation checkOnEachPublicOperation; + @StageRef protected HashLookupPos hlp; + + public boolean entryIsPresent() { + return true; + } + + public boolean entryRemovedOnThisIteration = false; + + abstract boolean entryRemovedOnThisIterationInit(); + + protected void initEntryRemovedOnThisIteration(boolean entryRemovedOnThisIteration) { + this.entryRemovedOnThisIteration = entryRemovedOnThisIteration; + } + + public boolean forEachRemoving(Predicate action) { + s.innerUpdateLock.lock(); + try { + long size = s.size(); + if (size == 0) + return true; + boolean interrupted = false; + long startPos = 0L; + while (!hashLookup.empty(hashLookup.readEntry(startPos))) { + startPos = hashLookup.step(startPos); + } + hlp.initHashLookupPos(startPos); + do { + hlp.setHashLookupPos(hashLookup.step(hlp.hashLookupPos)); + long entry = hashLookup.readEntry(hlp.hashLookupPos); + if (!hashLookup.empty(entry)) { + e.readExistingEntry(hashLookup.value(entry)); + if (entryIsPresent()) { + initEntryRemovedOnThisIteration(false); + if (!action.test((E) this)) { + interrupted = true; + break; + } else { + if (--size == 0) + break; + } + + } + } + } while (hlp.hashLookupPos != startPos); + return !interrupted; + } finally { + s.innerReadLock.unlock(); + initEntryRemovedOnThisIteration(false); + } + } + + public void checkEntryNotRemovedOnThisIteration() { + if (entryRemovedOnThisIterationInit()) + throw new IllegalStateException("Entry was already removed on this iteration"); + } + + @Override + public void doRemove() { + checkOnEachPublicOperation.checkOnEachPublicOperation(); + initEntryRemovedOnThisIteration(true); + s.innerWriteLock.lock(); + try { + // this condition mean -- some other entry taken place of the removed one + if (hashLookup.remove(hlp.hashLookupPos) != hlp.hashLookupPos) { + // if so, should make step back, to compensate step forward on the next iteration, + // to consume the shifted entry + hlp.setHashLookupPos(hashLookup.stepBack(hlp.hashLookupPos)); + } + e.innerRemoveEntryExceptHashLookupUpdate(); + } finally { + s.innerWriteLock.unlock(); + } + } +} diff --git a/src/main/java/net/openhft/chronicle/hash/impl/stage/query/HashLookupSearch.java b/src/main/java/net/openhft/chronicle/hash/impl/stage/query/HashLookupSearch.java new file mode 100644 index 000000000..b4d981729 --- /dev/null +++ b/src/main/java/net/openhft/chronicle/hash/impl/stage/query/HashLookupSearch.java @@ -0,0 +1,107 @@ +/* + * Copyright 2015 Higher Frequency Trading + * + * http://www.higherfrequencytrading.com + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package net.openhft.chronicle.hash.impl.stage.query; + +import net.openhft.chronicle.hash.impl.VanillaChronicleHashHolder; +import net.openhft.chronicle.hash.impl.stage.entry.HashEntryStages; +import net.openhft.chronicle.hash.impl.stage.entry.HashLookup; +import net.openhft.chronicle.hash.impl.stage.entry.HashLookupPos; +import net.openhft.chronicle.hash.impl.stage.entry.SegmentStages; +import net.openhft.sg.Stage; +import net.openhft.sg.StageRef; +import net.openhft.sg.Staged; + +import static net.openhft.chronicle.hash.impl.stage.entry.HashLookup.UNSET_KEY; + +@Staged +public abstract class HashLookupSearch { + + @StageRef SegmentStages s; + @StageRef HashEntryStages e; + @StageRef HashLookup hl; + @StageRef HashQuery op; + @StageRef VanillaChronicleHashHolder hh; + @StageRef HashLookupPos hlp; + + @Stage("SearchKey") long searchKey = UNSET_KEY; + @Stage("SearchKey") long searchStartPos; + + void initSearchKey() { + searchKey = hl.maskUnsetKey(hh.h().hashSplitting.segmentHash(op.hashOfKey)); + searchStartPos = hl.hlPos(searchKey); + } + + public long nextPos() { + long pos = hlp.hashLookupPos; + while (true) { + long entry = hl.readEntry(pos); + if (hl.empty(entry)) { + hlp.setHashLookupPos(pos); + return -1L; + } + pos = hl.step(pos); + if (pos == searchStartPos) + break; + if (hl.key(entry) == searchKey) { + hlp.setHashLookupPos(pos); + return hl.value(entry); + } + } + throw new IllegalStateException("MultiMap is full, that most likely means you " + + "misconfigured entrySize/chunkSize, and entries tend to take less chunks than " + + "expected"); + } + + public void found() { + hlp.setHashLookupPos(hl.stepBack(hlp.hashLookupPos)); + } + + public void remove() { + hlp.setHashLookupPos(hl.remove(hlp.hashLookupPos)); + } + + void put(long value) { + hl.checkValueForPut(value); + hl.writeEntry(hlp.hashLookupPos, hl.readEntry(hlp.hashLookupPos), searchKey, value); + } + + public void putVolatile(long value) { + hl.checkValueForPut(value); + long currentEntry = hl.readEntry(hlp.hashLookupPos); + assert hl.key(currentEntry) == searchKey; + hl.writeEntryVolatile(hlp.hashLookupPos, currentEntry, searchKey, value); + } + + public void putNewVolatile(long value) { + hl.checkValueForPut(value); + long currentEntry = hl.readEntry(hlp.hashLookupPos); + hl.writeEntryVolatile(hlp.hashLookupPos, currentEntry, searchKey, value); + } + + public boolean checkSlotContainsExpectedKeyAndValue(long value) { + long entry = hl.readEntry(hlp.hashLookupPos); + return hl.key(entry) == searchKey && hl.value(entry) == value; + } + + public boolean checkSlotIsEmpty() { + return hl.empty(hl.readEntry(hlp.hashLookupPos)); + } + + +} diff --git a/src/main/java/net/openhft/chronicle/hash/impl/stage/query/HashQuery.java b/src/main/java/net/openhft/chronicle/hash/impl/stage/query/HashQuery.java new file mode 100644 index 000000000..c03735ae5 --- /dev/null +++ b/src/main/java/net/openhft/chronicle/hash/impl/stage/query/HashQuery.java @@ -0,0 +1,155 @@ +/* + * Copyright 2015 Higher Frequency Trading + * + * http://www.higherfrequencytrading.com + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package net.openhft.chronicle.hash.impl.stage.query; + +import net.openhft.chronicle.algo.hashing.LongHashFunction; +import net.openhft.chronicle.bytes.BytesUtil; +import net.openhft.chronicle.hash.Data; +import net.openhft.chronicle.hash.HashEntry; +import net.openhft.chronicle.hash.impl.VanillaChronicleHashHolder; +import net.openhft.chronicle.hash.impl.stage.data.bytes.InputKeyBytesData; +import net.openhft.chronicle.hash.impl.stage.data.instance.InputKeyInstanceData; +import net.openhft.chronicle.hash.impl.stage.entry.HashEntryStages; +import net.openhft.chronicle.hash.impl.stage.entry.HashLookupPos; +import net.openhft.chronicle.hash.impl.stage.entry.SegmentStages; +import net.openhft.chronicle.hash.impl.stage.hash.CheckOnEachPublicOperation; +import net.openhft.sg.Stage; +import net.openhft.sg.StageRef; +import net.openhft.sg.Staged; + +import static net.openhft.chronicle.hash.impl.stage.query.HashQuery.SearchState.DELETED; +import static net.openhft.chronicle.hash.impl.stage.query.HashQuery.SearchState.PRESENT; + +@Staged +public abstract class HashQuery implements HashEntry { + + @StageRef public VanillaChronicleHashHolder hh; + @StageRef public SegmentStages s; + @StageRef public HashEntryStages entry; + @StageRef public HashLookupSearch hashLookupSearch; + @StageRef public CheckOnEachPublicOperation checkOnEachPublicOperation; + @StageRef public HashLookupPos hlp; + + @StageRef public InputKeyInstanceData inputKeyInstanceValue; + @StageRef public InputKeyBytesData inputKeyBytesValue; + + public void dropSearchIfNestedContextsAndPresentHashLookupSlotCheckFailed() { + if (s.locksInit()) { + if (s.concurrentSameThreadContexts && + s.rootContextOnThisSegment.latestSameThreadSegmentModCount != + s.contextModCount) { + if (keySearchInit()) { + if (searchState == PRESENT) { + if (!hashLookupSearch.checkSlotContainsExpectedKeyAndValue(entry.pos)) + hlp.closeHashLookupPos(); + } + } + } + } + } + + public Data inputKey = null; + + public void initInputKey(Data inputKey) { + this.inputKey = inputKey; + } + + public Data queriedKey() { + checkOnEachPublicOperation.checkOnEachPublicOperation(); + return inputKey; + } + + public long hashOfKey = 0; + + void initHashOfKey() { + hashOfKey = inputKey.hash(LongHashFunction.city_1_1()); + } + + public enum SearchState { + PRESENT, + DELETED, + ABSENT + } + + @Stage("KeySearch") protected SearchState searchState = null; + + abstract boolean keySearchInit(); + + @Stage("KeySearch") + public void setSearchState(SearchState newSearchState) { + this.searchState = newSearchState; + } + + void initKeySearch() { + for (long pos; (pos = hashLookupSearch.nextPos()) >= 0L;) { + entry.readExistingEntry(pos); + if (!keyEquals()) + continue; + hashLookupSearch.found(); + keyFound(); + return; + } + searchState = SearchState.ABSENT; + } + + boolean keyEquals() { + return inputKey.size() == entry.keySize && + BytesUtil.bytesEqual(entry.entryBS, entry.keyOffset, + inputKey.bytes(), inputKey.offset(), entry.keySize); + } + + @Stage("KeySearch") + void keyFound() { + searchState = PRESENT; + } + + abstract void closeKeySearch(); + + public boolean searchStatePresent() { + return searchState == PRESENT; + } + + public boolean searchStateDeleted() { + return searchState == DELETED && !s.concurrentSameThreadContexts && + s.innerUpdateLock.isHeldByCurrentThread(); + } + + public boolean searchStateAbsent() { + return !searchStatePresent() && !searchStateDeleted(); + } + + public boolean entryPresent() { + return searchStatePresent(); + } + + @Override + public void doRemove() { + checkOnEachPublicOperation.checkOnEachPublicOperation(); + s.innerUpdateLock.lock(); + if (searchStatePresent()) { + // TODO optimize: if shift-deletion is trivial, updateLock.lock() + s.innerWriteLock.lock(); + hashLookupSearch.remove(); + entry.innerRemoveEntryExceptHashLookupUpdate(); + setSearchState(DELETED); + } else { + throw new IllegalStateException("Entry is absent when doRemove() is called"); + } + } +} diff --git a/src/main/java/net/openhft/chronicle/hash/impl/stage/query/QueryHashLookupPos.java b/src/main/java/net/openhft/chronicle/hash/impl/stage/query/QueryHashLookupPos.java new file mode 100644 index 000000000..ae2d54ff2 --- /dev/null +++ b/src/main/java/net/openhft/chronicle/hash/impl/stage/query/QueryHashLookupPos.java @@ -0,0 +1,18 @@ +package net.openhft.chronicle.hash.impl.stage.query; + +import net.openhft.chronicle.hash.impl.stage.entry.HashLookupPos; +import net.openhft.chronicle.hash.impl.stage.entry.SegmentStages; +import net.openhft.sg.StageRef; +import net.openhft.sg.Staged; + +@Staged +public abstract class QueryHashLookupPos extends HashLookupPos { + + @StageRef SegmentStages s; + @StageRef HashLookupSearch hashLookupSearch; + + public void initHashLookupPos() { + s.innerReadLock.lock(); + this.hashLookupPos = hashLookupSearch.searchStartPos; + } +} diff --git a/src/main/java/net/openhft/chronicle/hash/impl/stage/query/QuerySegmentStages.java b/src/main/java/net/openhft/chronicle/hash/impl/stage/query/QuerySegmentStages.java new file mode 100644 index 000000000..808e6a6d6 --- /dev/null +++ b/src/main/java/net/openhft/chronicle/hash/impl/stage/query/QuerySegmentStages.java @@ -0,0 +1,33 @@ +/* + * Copyright 2015 Higher Frequency Trading + * + * http://www.higherfrequencytrading.com + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package net.openhft.chronicle.hash.impl.stage.query; + +import net.openhft.chronicle.hash.impl.stage.entry.SegmentStages; +import net.openhft.sg.StageRef; +import net.openhft.sg.Staged; + +@Staged +public abstract class QuerySegmentStages extends SegmentStages { + + @StageRef HashQuery q; + + void initTheSegmentIndex() { + segmentIndex = hh.h().hashSplitting.segmentIndex(q.hashOfKey); + } +} diff --git a/src/main/java/net/openhft/chronicle/hash/impl/stage/query/SearchAllocatedChunks.java b/src/main/java/net/openhft/chronicle/hash/impl/stage/query/SearchAllocatedChunks.java new file mode 100644 index 000000000..c04a50e1e --- /dev/null +++ b/src/main/java/net/openhft/chronicle/hash/impl/stage/query/SearchAllocatedChunks.java @@ -0,0 +1,45 @@ +/* + * Copyright 2015 Higher Frequency Trading + * + * http://www.higherfrequencytrading.com + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package net.openhft.chronicle.hash.impl.stage.query; + +import net.openhft.chronicle.hash.impl.stage.entry.AllocatedChunks; +import net.openhft.sg.StageRef; +import net.openhft.sg.Staged; + +import static net.openhft.chronicle.hash.impl.stage.query.HashQuery.SearchState.PRESENT; + +@Staged +public class SearchAllocatedChunks extends AllocatedChunks { + + @StageRef HashQuery q; + + @Override + public void incrementSegmentEntriesIfNeeded() { + if (q.searchState != PRESENT) { + // update the size before the store fence + s.entries(s.entries() + 1L); + } + } + + public void initEntryAndKey(long entrySize) { + initAllocatedChunks(hh.h().inChunks(entrySize)); + entry.writeNewEntry(s.alloc(allocatedChunks), q.inputKey); + incrementSegmentEntriesIfNeeded(); + } +} diff --git a/src/main/java/net/openhft/chronicle/map/AbstractChronicleMap.java b/src/main/java/net/openhft/chronicle/map/AbstractChronicleMap.java index a475889e1..6787259e9 100644 --- a/src/main/java/net/openhft/chronicle/map/AbstractChronicleMap.java +++ b/src/main/java/net/openhft/chronicle/map/AbstractChronicleMap.java @@ -17,9 +17,7 @@ package net.openhft.chronicle.map; import net.openhft.chronicle.hash.function.SerializableFunction; -import net.openhft.chronicle.hash.impl.hashlookup.HashLookupIteration; import net.openhft.chronicle.hash.impl.util.CharSequences; -import net.openhft.chronicle.map.impl.CompiledMapIterationContext; import net.openhft.chronicle.map.impl.IterationContextInterface; import org.jetbrains.annotations.NotNull; diff --git a/src/main/java/net/openhft/chronicle/map/ReplicatedChronicleMap.java b/src/main/java/net/openhft/chronicle/map/ReplicatedChronicleMap.java index 3f1e76416..bb2b8ea79 100644 --- a/src/main/java/net/openhft/chronicle/map/ReplicatedChronicleMap.java +++ b/src/main/java/net/openhft/chronicle/map/ReplicatedChronicleMap.java @@ -23,7 +23,8 @@ import net.openhft.chronicle.hash.replication.AbstractReplication; import net.openhft.chronicle.hash.replication.ReplicableEntry; import net.openhft.chronicle.hash.replication.TimeProvider; import net.openhft.chronicle.hash.serialization.internal.MetaBytesInterop; -import net.openhft.chronicle.map.impl.*; +import net.openhft.chronicle.map.impl.CompiledReplicatedMapIterationContext; +import net.openhft.chronicle.map.impl.CompiledReplicatedMapQueryContext; import net.openhft.chronicle.map.replication.MapRemoteOperations; import net.openhft.chronicle.map.replication.MapReplicableEntry; import net.openhft.lang.Maths; @@ -522,7 +523,8 @@ public class ReplicatedChronicleMap 0L; + // Bizarrely the next line line cause NPE in JDT compiler + //assert re.originTimestamp() > 0L; if (debugEnabled) { - LOG.debug("Bootstrap decision: bs ts: {}, entry ts: {}, entry id: {}, " + - "local id: {}", fromTimeStamp, re.originTimestamp(), + LOG.debug("Bootstrap decision: bs ts: {}, entry ts: {}, " + + "entry id: {}, local id: {}", + fromTimeStamp, re.originTimestamp(), re.originIdentifier(), localIdentifier); } if (re.originTimestamp() >= fromTimeStamp && diff --git a/src/main/java/net/openhft/chronicle/map/TcpReplicator.java b/src/main/java/net/openhft/chronicle/map/TcpReplicator.java index 44944e328..5b790876c 100644 --- a/src/main/java/net/openhft/chronicle/map/TcpReplicator.java +++ b/src/main/java/net/openhft/chronicle/map/TcpReplicator.java @@ -24,11 +24,9 @@ import net.openhft.chronicle.hash.replication.RemoteNodeValidator; import net.openhft.chronicle.hash.replication.TcpTransportAndNetworkConfig; import net.openhft.chronicle.hash.replication.ThrottlingConfig; import net.openhft.chronicle.hash.serialization.BytesReader; -import net.openhft.chronicle.hash.serialization.internal.MetaBytesInterop; import net.openhft.chronicle.hash.serialization.internal.ReaderWithSize; import net.openhft.chronicle.hash.serialization.internal.SerializationBuilder; import net.openhft.chronicle.map.impl.CompiledReplicatedMapQueryContext; -import net.openhft.chronicle.map.impl.QueryContextInterface; import net.openhft.lang.io.AbstractBytes; import net.openhft.lang.io.ByteBufferBytes; import net.openhft.lang.io.Bytes; diff --git a/src/main/java/net/openhft/chronicle/map/VanillaChronicleMap.java b/src/main/java/net/openhft/chronicle/map/VanillaChronicleMap.java index 92c3f35dd..d66d06b07 100755 --- a/src/main/java/net/openhft/chronicle/map/VanillaChronicleMap.java +++ b/src/main/java/net/openhft/chronicle/map/VanillaChronicleMap.java @@ -18,8 +18,8 @@ package net.openhft.chronicle.map; -import net.openhft.chronicle.hash.KeyContext; import net.openhft.chronicle.hash.Data; +import net.openhft.chronicle.hash.KeyContext; import net.openhft.chronicle.hash.impl.VanillaChronicleHash; import net.openhft.chronicle.hash.serialization.BytesReader; import net.openhft.chronicle.hash.serialization.SizeMarshaller; @@ -27,6 +27,8 @@ import net.openhft.chronicle.hash.serialization.internal.MetaBytesInterop; import net.openhft.chronicle.hash.serialization.internal.MetaProvider; import net.openhft.chronicle.hash.serialization.internal.SerializationBuilder; import net.openhft.chronicle.map.impl.*; +import net.openhft.chronicle.map.impl.CompiledMapIterationContext; +import net.openhft.chronicle.map.impl.CompiledMapQueryContext; import net.openhft.chronicle.map.impl.ret.InstanceReturnValue; import net.openhft.lang.io.Bytes; import net.openhft.lang.model.DataValueClasses; @@ -265,11 +267,13 @@ public class VanillaChronicleMap, V, VI, MVI extends MetaBytesInterop, R> implements AutoCloseable , HashEntry , InterProcessReadWriteUpdateLock , MapContext , MapEntry , IterationContextInterface , VanillaChronicleMapHolder { - public void close() { - this.closeTheSegmentIndex(); - this.wrappedValueInstanceValue.closeValue(); - this.closeEntryRemovedOnThisIteration(); - this.wrappedValueInstanceValue.closeNext(); - this.closeUsed(); - this.closeKeySize(); - this.closePos(); - this.closeAllocatedChunks(); - this.closeHashLookupPos(); - this.closeKeyOffset(); - this.closeOwnerThreadHolderCheckAccessingFromOwnerThreadDependants(); - this.closeVanillaChronicleMapHolderImplContextAtIndexInChainDependants(); - this.closeValueBytesInteropValueMetaInteropDependants(); - this.closeMapSegmentIterationCheckEntryNotRemovedOnThisIterationDependants(); - } - - public void incrementModCountGuarded() { - if (!(this.locksInit())) - this.initLocks(); - - incrementModCount(); - } - - public void setHashLookupPosGuarded(long hashLookupPos) { - assert this.hashLookupPosInit() : "HashLookupPos should be init"; - setHashLookupPos(hashLookupPos); - } - - public void setLocalLockStateGuarded(LocalLockState newState) { - if (!(this.locksInit())) - this.initLocks(); - - setLocalLockState(newState); - } - - public CompiledMapIterationContext(VanillaChronicleMap m) { - contextChain = new ArrayList(); - contextChain.add(this); - indexInContextChain = 0; - this.m = m; - this.copies = ThreadLocalCopies.get(); - this.valueInterop = this.m().valueInteropProvider.get(this.copies, this.m().originalValueInterop); - this.valueReader = this.m().valueReaderProvider.get(this.copies, this.m().originalValueReader); - this.keyInterop = this.h().keyInteropProvider.get(this.copies, this.h().originalKeyInterop); - this.keyReader = this.h().keyReaderProvider.get(this.copies, this.h().originalKeyReader); - this.entryKey = new EntryKeyBytesData(); - this.innerUpdateLock = new UpdateLock(); - this.innerReadLock = new ReadLock(); - this.entryValue = new EntryValueBytesData(); - this.innerWriteLock = new WriteLock(); - this.entryBytes = this.h().ms.bytes(); - this.entryBS = new NativeBytesStore(entryBytes.address() , entryBytes.capacity() , null , false); - this.owner = Thread.currentThread(); - this.deprecatedMapKeyContextOnIteration = new DeprecatedMapKeyContextOnIteration(); - this.wrappedValueInstanceValue = new WrappedValueInstanceData(); - } - - public CompiledMapIterationContext(CompiledMapIterationContext c) { - contextChain = c.contextChain; - indexInContextChain = contextChain.size(); - contextChain.add(this); - this.m = ((VanillaChronicleMap)(c.m)); - this.copies = ThreadLocalCopies.get(); - this.valueInterop = this.m().valueInteropProvider.get(this.copies, this.m().originalValueInterop); - this.valueReader = this.m().valueReaderProvider.get(this.copies, this.m().originalValueReader); - this.keyInterop = this.h().keyInteropProvider.get(this.copies, this.h().originalKeyInterop); - this.keyReader = this.h().keyReaderProvider.get(this.copies, this.h().originalKeyReader); - this.entryKey = new EntryKeyBytesData(); - this.innerUpdateLock = new UpdateLock(); - this.innerReadLock = new ReadLock(); - this.entryValue = new EntryValueBytesData(); - this.innerWriteLock = new WriteLock(); - this.entryBytes = this.h().ms.bytes(); - this.entryBS = new NativeBytesStore(entryBytes.address() , entryBytes.capacity() , null , false); - this.owner = Thread.currentThread(); - this.deprecatedMapKeyContextOnIteration = new DeprecatedMapKeyContextOnIteration(); - this.wrappedValueInstanceValue = new WrappedValueInstanceData(); - } - - public class DeprecatedMapKeyContextOnIteration implements MapKeyContext { - @Override - public void close() { - throw new UnsupportedOperationException("close() is not supported during iteration"); - } - - @NotNull - private UnsupportedOperationException unsupportedLocks() { - return new UnsupportedOperationException("Lock operations are not supported (and not needed!) during iteration"); - } - - @NotNull - @Override - public InterProcessLock readLock() { - throw unsupportedLocks(); - } - - @NotNull - @Override - public InterProcessLock writeLock() { - throw unsupportedLocks(); - } - - @NotNull - @Override - public InterProcessLock updateLock() { - throw unsupportedLocks(); - } - - @Override - public V get() { - CompiledMapIterationContext.this.checkOnEachPublicOperation(); - return CompiledMapIterationContext.this.value().get(); - } - - @NotNull - @Override - public K key() { - CompiledMapIterationContext.this.checkOnEachPublicOperation(); - return CompiledMapIterationContext.this.key().get(); - } - - @Override - public boolean containsKey() { - CompiledMapIterationContext.this.checkOnEachPublicOperation(); - return true; - } - - @Override - public boolean put(V newValue) { - CompiledMapIterationContext.this.checkOnEachPublicOperation(); - CompiledMapIterationContext.this.replaceValue(CompiledMapIterationContext.this, CompiledMapIterationContext.this.context().wrapValueAsValue(newValue)); - return true; - } - - @NotNull - @Override - public Bytes entry() { - CompiledMapIterationContext.this.checkOnEachPublicOperation(); - return CompiledMapIterationContext.this.entryBytes; - } - - @Override - public boolean valueEqualTo(V value) { - CompiledMapIterationContext.this.checkOnEachPublicOperation(); - return Data.bytesEquivalent(CompiledMapIterationContext.this.entryValue, CompiledMapIterationContext.this.context().wrapValueAsValue(value)); - } - - @Override - public boolean remove() { - CompiledMapIterationContext.this.checkOnEachPublicOperation(); - CompiledMapIterationContext.this.remove(CompiledMapIterationContext.this); - return true; - } - - @Override - public V getUsing(V usingValue) { - CompiledMapIterationContext.this.checkOnEachPublicOperation(); - return CompiledMapIterationContext.this.value().getUsing(usingValue); - } - - @Override - public long keyOffset() { - CompiledMapIterationContext.this.checkOnEachPublicOperation(); - return CompiledMapIterationContext.this.keyOffset(); - } - - @Override - public long valueOffset() { - CompiledMapIterationContext.this.checkOnEachPublicOperation(); - return CompiledMapIterationContext.this.valueOffset(); - } - - @Override - public long valueSize() { - CompiledMapIterationContext.this.checkOnEachPublicOperation(); - return CompiledMapIterationContext.this.valueSize(); - } - - @Override - public long keySize() { - CompiledMapIterationContext.this.checkOnEachPublicOperation(); - return CompiledMapIterationContext.this.keySize(); - } - } - - public class EntryKeyBytesData extends AbstractData { - @Override - public RandomDataInput bytes() { - CompiledMapIterationContext.this.checkOnEachPublicOperation(); - return CompiledMapIterationContext.this.entryBS; - } - - @Override - public long offset() { - CompiledMapIterationContext.this.checkOnEachPublicOperation(); - return CompiledMapIterationContext.this.keyOffset(); - } - - @Override - public long size() { - CompiledMapIterationContext.this.checkOnEachPublicOperation(); - return CompiledMapIterationContext.this.keySize(); - } - - public void closeEntryKeyBytesDataSizeDependants() { - this.closeEntryKeyBytesDataInnerGetUsingDependants(); - } - - private K innerGetUsing(K usingKey) { - CompiledMapIterationContext.this.entryBytes.position(CompiledMapIterationContext.this.keyOffset()); - return CompiledMapIterationContext.this.keyReader.read(CompiledMapIterationContext.this.entryBytes, size(), usingKey); - } - - public void closeEntryKeyBytesDataInnerGetUsingDependants() { - this.closeCachedEntryKey(); - } - - private K cachedEntryKey; - - private boolean cachedEntryKeyRead = false; - - public boolean cachedEntryKeyInit() { - return (this.cachedEntryKeyRead) != false; - } - - private void initCachedEntryKey() { - cachedEntryKey = innerGetUsing(cachedEntryKey); - cachedEntryKeyRead = true; - } - - public K cachedEntryKey() { - if (!(this.cachedEntryKeyInit())) - this.initCachedEntryKey(); - - return this.cachedEntryKey; - } - - public void closeCachedEntryKey() { - if (!(this.cachedEntryKeyInit())) - return ; - - this.cachedEntryKeyRead = false; - } - - @Override - public K get() { - CompiledMapIterationContext.this.checkOnEachPublicOperation(); - return cachedEntryKey(); - } - - @Override - public K getUsing(K usingKey) { - CompiledMapIterationContext.this.checkOnEachPublicOperation(); - return innerGetUsing(usingKey); - } - } - - public class EntryValueBytesData extends AbstractData { - @Override - public RandomDataInput bytes() { - CompiledMapIterationContext.this.checkOnEachPublicOperation(); - return CompiledMapIterationContext.this.entryBS; - } - - @Override - public long offset() { - CompiledMapIterationContext.this.checkOnEachPublicOperation(); - return CompiledMapIterationContext.this.valueOffset(); - } - - @Override - public long size() { - CompiledMapIterationContext.this.checkOnEachPublicOperation(); - return CompiledMapIterationContext.this.valueSize(); - } - - public void closeEntryValueBytesDataSizeDependants() { - this.closeEntryValueBytesDataInnerGetUsingDependants(); - } - - private V innerGetUsing(V usingValue) { - CompiledMapIterationContext.this.entryBytes.position(CompiledMapIterationContext.this.valueOffset()); - return CompiledMapIterationContext.this.valueReader.read(CompiledMapIterationContext.this.entryBytes, size(), usingValue); - } - - public void closeEntryValueBytesDataInnerGetUsingDependants() { - this.closeCachedEntryValue(); - } - - @Override - public V getUsing(V usingValue) { - CompiledMapIterationContext.this.checkOnEachPublicOperation(); - return innerGetUsing(usingValue); - } - - private V cachedEntryValue; - - private boolean cachedEntryValueRead = false; - - public boolean cachedEntryValueInit() { - return (this.cachedEntryValueRead) != false; - } - - private void initCachedEntryValue() { - cachedEntryValue = innerGetUsing(cachedEntryValue); - cachedEntryValueRead = true; - } - - public V cachedEntryValue() { - if (!(this.cachedEntryValueInit())) - this.initCachedEntryValue(); - - return this.cachedEntryValue; - } - - public void closeCachedEntryValue() { - if (!(this.cachedEntryValueInit())) - return ; - - this.cachedEntryValueRead = false; - } - - @Override - public V get() { - CompiledMapIterationContext.this.checkOnEachPublicOperation(); - return cachedEntryValue(); - } - } - - public class ReadLock implements InterProcessLock { - @Override - public void lockInterruptibly() throws InterruptedException { - if ((CompiledMapIterationContext.this.localLockState()) == (LocalLockState.UNLOCKED)) { - CompiledMapIterationContext.this.segmentHeader().readLockInterruptibly(CompiledMapIterationContext.this.segmentHeaderAddress()); - CompiledMapIterationContext.this.setLocalLockStateGuarded(LocalLockState.READ_LOCKED); - } - } - - @Override - public void lock() { - if ((CompiledMapIterationContext.this.localLockState()) == (LocalLockState.UNLOCKED)) { - CompiledMapIterationContext.this.segmentHeader().readLock(CompiledMapIterationContext.this.segmentHeaderAddress()); - CompiledMapIterationContext.this.setLocalLockStateGuarded(LocalLockState.READ_LOCKED); - } - } - - @Override - public boolean isHeldByCurrentThread() { - return CompiledMapIterationContext.this.localLockState().read; - } - - @Override - public void unlock() { - switch (CompiledMapIterationContext.this.localLockState()) { - case UNLOCKED : - return ; - case READ_LOCKED : - CompiledMapIterationContext.this.segmentHeader().readUnlock(CompiledMapIterationContext.this.segmentHeaderAddress()); - break; - case UPDATE_LOCKED : - CompiledMapIterationContext.this.segmentHeader().updateUnlock(CompiledMapIterationContext.this.segmentHeaderAddress()); - break; - case WRITE_LOCKED : - CompiledMapIterationContext.this.segmentHeader().writeUnlock(CompiledMapIterationContext.this.segmentHeaderAddress()); - } - CompiledMapIterationContext.this.setLocalLockStateGuarded(LocalLockState.UNLOCKED); - CompiledMapIterationContext.this.closeHashLookupPos(); - CompiledMapIterationContext.this.closePos(); - } - - @Override - public boolean tryLock(long time, @NotNull - TimeUnit unit) throws InterruptedException { - if ((CompiledMapIterationContext.this.localLockState()) == (LocalLockState.UNLOCKED)) { - if (CompiledMapIterationContext.this.segmentHeader().tryReadLock(CompiledMapIterationContext.this.segmentHeaderAddress(), time, unit)) { - CompiledMapIterationContext.this.setLocalLockStateGuarded(LocalLockState.READ_LOCKED); - return true; - } else { - return false; - } - } else { - return true; - } - } - - @Override - public boolean tryLock() { - if ((CompiledMapIterationContext.this.localLockState()) == (LocalLockState.UNLOCKED)) { - if (CompiledMapIterationContext.this.segmentHeader().tryReadLock(CompiledMapIterationContext.this.segmentHeaderAddress())) { - CompiledMapIterationContext.this.setLocalLockStateGuarded(LocalLockState.READ_LOCKED); - return true; - } else { - return false; - } - } else { - return true; - } - } - } - - public class UpdateLock implements InterProcessLock { - @NotNull - private IllegalMonitorStateException forbiddenUpgrade() { - return new IllegalMonitorStateException("Cannot upgrade from read to update lock"); - } - - @Override - public void lockInterruptibly() throws InterruptedException { - switch (CompiledMapIterationContext.this.localLockState()) { - case UNLOCKED : - CompiledMapIterationContext.this.segmentHeader().updateLockInterruptibly(CompiledMapIterationContext.this.segmentHeaderAddress()); - CompiledMapIterationContext.this.setLocalLockStateGuarded(LocalLockState.UPDATE_LOCKED); - return ; - case READ_LOCKED : - throw forbiddenUpgrade(); - case UPDATE_LOCKED : - case WRITE_LOCKED : - } - } - - @Override - public void unlock() { - switch (CompiledMapIterationContext.this.localLockState()) { - case UNLOCKED : - case READ_LOCKED : - return ; - case UPDATE_LOCKED : - CompiledMapIterationContext.this.segmentHeader().downgradeUpdateToReadLock(CompiledMapIterationContext.this.segmentHeaderAddress()); - break; - case WRITE_LOCKED : - CompiledMapIterationContext.this.segmentHeader().downgradeWriteToReadLock(CompiledMapIterationContext.this.segmentHeaderAddress()); - } - CompiledMapIterationContext.this.setLocalLockStateGuarded(LocalLockState.READ_LOCKED); - } - - @Override - public boolean isHeldByCurrentThread() { - return CompiledMapIterationContext.this.localLockState().update; - } - - @Override - public void lock() { - switch (CompiledMapIterationContext.this.localLockState()) { - case UNLOCKED : - CompiledMapIterationContext.this.segmentHeader().updateLock(CompiledMapIterationContext.this.segmentHeaderAddress()); - CompiledMapIterationContext.this.setLocalLockStateGuarded(LocalLockState.UPDATE_LOCKED); - return ; - case READ_LOCKED : - throw forbiddenUpgrade(); - case UPDATE_LOCKED : - case WRITE_LOCKED : - } - } - - @Override - public boolean tryLock(long time, @NotNull - TimeUnit unit) throws InterruptedException { - switch (CompiledMapIterationContext.this.localLockState()) { - case UNLOCKED : - if (CompiledMapIterationContext.this.segmentHeader().tryUpdateLock(CompiledMapIterationContext.this.segmentHeaderAddress(), time, unit)) { - CompiledMapIterationContext.this.setLocalLockStateGuarded(LocalLockState.UPDATE_LOCKED); - return true; - } else { - return false; - } - case READ_LOCKED : - throw forbiddenUpgrade(); - case UPDATE_LOCKED : - case WRITE_LOCKED : - return true; - } - throw new AssertionError(); - } - - @Override - public boolean tryLock() { - switch (CompiledMapIterationContext.this.localLockState()) { - case UNLOCKED : - if (CompiledMapIterationContext.this.segmentHeader().tryUpdateLock(CompiledMapIterationContext.this.segmentHeaderAddress())) { - CompiledMapIterationContext.this.setLocalLockStateGuarded(LocalLockState.UPDATE_LOCKED); - return true; - } else { - return false; - } - case READ_LOCKED : - throw forbiddenUpgrade(); - case UPDATE_LOCKED : - case WRITE_LOCKED : - return true; - } - throw new AssertionError(); - } - } - - public class WrappedValueInstanceData extends CopyingInstanceData { - public WrappedValueInstanceData getUnusedWrappedValueGuarded() { - assert this.nextInit() : "Next should be init"; - return getUnusedWrappedValue(); - } - - public WrappedValueInstanceData getUnusedWrappedValue() { - if (!(valueInit())) - return this; - - if ((next) == null) - next = new WrappedValueInstanceData(); - - return next.getUnusedWrappedValue(); - } - - private WrappedValueInstanceData next; - - boolean nextInit() { - return true; - } - - void closeNext() { - if (!(this.nextInit())) - return ; - - } - - private V value; - - public boolean valueInit() { - return (value) != null; - } - - public void initValue(V value) { - CompiledMapIterationContext.this.m().checkValue(value); - this.value = value; - this.closeValueDependants(); - } - - public V value() { - assert this.valueInit() : "Value should be init"; - return this.value; - } - - public void closeValue() { - if (!(this.valueInit())) - return ; - - this.closeValueDependants(); - value = null; - if ((next) != null) - next.closeValue(); - - } - - public void closeValueDependants() { - this.closeBuffer(); - } - - @Override - public V instance() { - return value(); - } - - private boolean marshalled = false; - - private DirectBytes buf; - - public boolean bufferInit() { - return (this.marshalled) != false; - } - - private void initBuffer() { - MVI mvi = CompiledMapIterationContext.this.valueMetaInterop(value()); - long size = mvi.size(CompiledMapIterationContext.this.valueInterop, value()); - buf = getBuffer(this.buf, size); - mvi.write(CompiledMapIterationContext.this.valueInterop, buf, value()); - buf.flip(); - marshalled = true; - } - - public DirectBytes buf() { - if (!(this.bufferInit())) - this.initBuffer(); - - return this.buf; - } - - public void closeBuffer() { - if (!(this.bufferInit())) - return ; - - this.marshalled = false; - } - - @Override - public V getUsing(V usingValue) { - buf().position(0); - return CompiledMapIterationContext.this.valueReader.read(buf(), buf().limit(), usingValue); - } - - @Override - public DirectBytes buffer() { - return buf(); - } - } - - public class WriteLock implements InterProcessLock { - @NotNull - private IllegalMonitorStateException forbiddenUpgrade() { - return new IllegalMonitorStateException("Cannot upgrade from read to write lock"); - } - - @Override - public boolean tryLock(long time, @NotNull - TimeUnit unit) throws InterruptedException { - switch (CompiledMapIterationContext.this.localLockState()) { - case UNLOCKED : - if (CompiledMapIterationContext.this.segmentHeader().tryWriteLock(CompiledMapIterationContext.this.segmentHeaderAddress(), time, unit)) { - CompiledMapIterationContext.this.setLocalLockStateGuarded(LocalLockState.WRITE_LOCKED); - return true; - } else { - return false; - } - case READ_LOCKED : - throw forbiddenUpgrade(); - case UPDATE_LOCKED : - if (CompiledMapIterationContext.this.segmentHeader().tryUpgradeUpdateToWriteLock(CompiledMapIterationContext.this.segmentHeaderAddress(), time, unit)) { - CompiledMapIterationContext.this.setLocalLockStateGuarded(LocalLockState.WRITE_LOCKED); - return true; - } else { - return false; - } - case WRITE_LOCKED : - return true; - } - throw new AssertionError(); - } - - @Override - public boolean tryLock() { - switch (CompiledMapIterationContext.this.localLockState()) { - case UNLOCKED : - if (CompiledMapIterationContext.this.segmentHeader().tryWriteLock(CompiledMapIterationContext.this.segmentHeaderAddress())) { - CompiledMapIterationContext.this.setLocalLockStateGuarded(LocalLockState.WRITE_LOCKED); - return true; - } else { - return false; - } - case READ_LOCKED : - throw forbiddenUpgrade(); - case UPDATE_LOCKED : - if (CompiledMapIterationContext.this.segmentHeader().tryUpgradeUpdateToWriteLock(CompiledMapIterationContext.this.segmentHeaderAddress())) { - CompiledMapIterationContext.this.setLocalLockStateGuarded(LocalLockState.WRITE_LOCKED); - return true; - } else { - return false; - } - case WRITE_LOCKED : - return true; - } - throw new AssertionError(); - } - - @Override - public void lockInterruptibly() throws InterruptedException { - switch (CompiledMapIterationContext.this.localLockState()) { - case UNLOCKED : - CompiledMapIterationContext.this.segmentHeader().writeLockInterruptibly(CompiledMapIterationContext.this.segmentHeaderAddress()); - CompiledMapIterationContext.this.setLocalLockStateGuarded(LocalLockState.WRITE_LOCKED); - return ; - case READ_LOCKED : - throw forbiddenUpgrade(); - case UPDATE_LOCKED : - CompiledMapIterationContext.this.segmentHeader().upgradeUpdateToWriteLockInterruptibly(CompiledMapIterationContext.this.segmentHeaderAddress()); - CompiledMapIterationContext.this.setLocalLockStateGuarded(LocalLockState.WRITE_LOCKED); - case WRITE_LOCKED : - } - } - - @Override - public void unlock() { - switch (CompiledMapIterationContext.this.localLockState()) { - case UNLOCKED : - case READ_LOCKED : - case UPDATE_LOCKED : - return ; - case WRITE_LOCKED : - CompiledMapIterationContext.this.segmentHeader().downgradeWriteToUpdateLock(CompiledMapIterationContext.this.segmentHeaderAddress()); - } - CompiledMapIterationContext.this.setLocalLockStateGuarded(LocalLockState.UPDATE_LOCKED); - } - - @Override - public boolean isHeldByCurrentThread() { - return CompiledMapIterationContext.this.localLockState().write; - } - - @Override - public void lock() { - switch (CompiledMapIterationContext.this.localLockState()) { - case UNLOCKED : - CompiledMapIterationContext.this.segmentHeader().writeLock(CompiledMapIterationContext.this.segmentHeaderAddress()); - CompiledMapIterationContext.this.setLocalLockStateGuarded(LocalLockState.WRITE_LOCKED); - return ; - case READ_LOCKED : - throw forbiddenUpgrade(); - case UPDATE_LOCKED : - CompiledMapIterationContext.this.segmentHeader().upgradeUpdateToWriteLock(CompiledMapIterationContext.this.segmentHeaderAddress()); - CompiledMapIterationContext.this.setLocalLockStateGuarded(LocalLockState.WRITE_LOCKED); - case WRITE_LOCKED : - } - } - } - - private void _CheckOnEachPublicOperation_checkOnEachPublicOperation() { - this.checkAccessingFromOwnerThread(); - } - - public void incrementModCount() { - contextModCount = rootContextOnThisSegment.latestSameThreadSegmentModCount = (rootContextOnThisSegment.latestSameThreadSegmentModCount) + 1; - } - - public void setHashLookupPos(long hashLookupPos) { - this.hashLookupPos = hashLookupPos; - } - - public void setLocalLockState(LocalLockState newState) { - localLockState = newState; - } - - final Thread owner; - - public Thread owner() { - return this.owner; - } - - private void closeNestedLocks() { - unlinkFromSegmentContextsChain(); - switch (localLockState) { - case UNLOCKED : - break; - case READ_LOCKED : - int newTotalReadLockCount = this.rootContextOnThisSegment.totalReadLockCount -= 1; - if (newTotalReadLockCount == 0) { - if (((this.rootContextOnThisSegment.totalUpdateLockCount) == 0) && ((this.rootContextOnThisSegment.totalWriteLockCount) == 0)) { - segmentHeader().readUnlock(segmentHeaderAddress()); - } - } else if (newTotalReadLockCount < 0) { - throw new IllegalStateException("read underflow"); - } - break; - case UPDATE_LOCKED : - int newTotalUpdateLockCount = this.rootContextOnThisSegment.totalUpdateLockCount -= 1; - if (newTotalUpdateLockCount == 0) { - if ((this.rootContextOnThisSegment.totalWriteLockCount) == 0) { - if ((this.rootContextOnThisSegment.totalReadLockCount) == 0) { - segmentHeader().updateUnlock(segmentHeaderAddress()); - } else { - segmentHeader().downgradeUpdateToReadLock(segmentHeaderAddress()); - } - } - } else if (newTotalUpdateLockCount < 0) { - throw new IllegalStateException("update underflow"); - } - break; - case WRITE_LOCKED : - int newTotalWriteLockCount = this.rootContextOnThisSegment.totalWriteLockCount -= 1; - if (newTotalWriteLockCount == 0) { - if ((this.rootContextOnThisSegment.totalUpdateLockCount) > 0) { - segmentHeader().downgradeWriteToUpdateLock(segmentHeaderAddress()); - } else { - if ((this.rootContextOnThisSegment.totalReadLockCount) > 0) { - segmentHeader().downgradeWriteToReadLock(segmentHeaderAddress()); - } else { - segmentHeader().writeUnlock(segmentHeaderAddress()); - } - } - } - break; - } - } - - private void closeRootLocks() { - assert (nextNode) == null; - switch (localLockState) { - case UNLOCKED : - return ; - case READ_LOCKED : - segmentHeader().readUnlock(segmentHeaderAddress()); - return ; - case UPDATE_LOCKED : - segmentHeader().updateUnlock(segmentHeaderAddress()); - return ; - case WRITE_LOCKED : - segmentHeader().writeUnlock(segmentHeaderAddress()); - } - } - - private void innerInitSegmentHashLookup(long address, long capacity, int entrySize, int keyBits, int valueBits) { - this.address = address; - this.capacityMask = capacity - 1L; - this.hashLookupEntrySize = entrySize; - this.capacityMask2 = (capacityMask) * entrySize; - this.keyBits = keyBits; - this.keyMask = CompiledMapIterationContext.mask(keyBits); - this.valueMask = CompiledMapIterationContext.mask(valueBits); - this.entryMask = CompiledMapIterationContext.mask((keyBits + valueBits)); - } - - private void unlinkFromSegmentContextsChain() { - CompiledMapIterationContext prevContext = this.rootContextOnThisSegment; - while (true) { - assert (prevContext.nextNode) != null; - if ((prevContext.nextNode) == (this)) - break; - - prevContext = prevContext.nextNode; - } - assert (nextNode) == null; - prevContext.nextNode = null; - } - - private long _HashEntryStages_entryEnd() { - return keyEnd(); - } - - private CompiledMapIterationContext _Chaining_createChaining() { - return new CompiledMapIterationContext(this); - } - - public final int indexInContextChain; - - public int indexInContextChain() { - return this.indexInContextChain; - } - - public static int entrySize(int keyBits, int valueBits) { - return ((int)(MemoryUnit.BYTES.alignAndConvert(((long)(keyBits + valueBits)), MemoryUnit.BITS))); - } - - public static int keyBits(long entriesPerSegment, int valueBits) { - int minKeyBits = 64 - (Long.numberOfLeadingZeros((entriesPerSegment - 1L))); - minKeyBits += 3; - int actualEntryBits = ((int)(MemoryUnit.BYTES.align(((long)(minKeyBits + valueBits)), MemoryUnit.BITS))); - return actualEntryBits - valueBits; - } - - public static int valueBits(long actualChunksPerSegment) { - return 64 - (Long.numberOfLeadingZeros((actualChunksPerSegment - 1L))); - } - - public final Bytes entryBytes; - - public Bytes entryBytes() { - return this.entryBytes; - } - - public static long capacityFor(long entriesPerSegment) { - if (entriesPerSegment < 0L) - throw new IllegalArgumentException("entriesPerSegment should be positive"); - - long capacity = Maths.nextPower2(entriesPerSegment, 64L); - if ((((double)(entriesPerSegment)) / ((double)(capacity))) > (2.0 / 3.0)) { - capacity <<= 1L; - } - return capacity; - } - - public static long mask(int bits) { - return (1L << bits) - 1L; - } - - public static final int MAX_SEGMENT_CHUNKS = 1 << 30; - - public static final int MAX_SEGMENT_ENTRIES = 1 << 29; - - public int MAX_SEGMENT_ENTRIES() { - return this.MAX_SEGMENT_ENTRIES; - } - - public int MAX_SEGMENT_CHUNKS() { - return this.MAX_SEGMENT_CHUNKS; - } - - public static final long UNSET_KEY = 0L; - - public static final long UNSET_ENTRY = 0L; - - public long UNSET_ENTRY() { - return this.UNSET_ENTRY; - } - - public long UNSET_KEY() { - return this.UNSET_KEY; - } - - public final ReadLock innerReadLock; - - public ReadLock innerReadLock() { - return this.innerReadLock; - } - - public final WriteLock innerWriteLock; - - public WriteLock innerWriteLock() { - return this.innerWriteLock; - } - - public final List contextChain; - - public final UpdateLock innerUpdateLock; - - public UpdateLock innerUpdateLock() { - return this.innerUpdateLock; - } - - public List contextChain() { - return this.contextChain; - } - - public final ThreadLocalCopies copies; - - final EntryKeyBytesData entryKey; - - public EntryKeyBytesData entryKey() { - return this.entryKey; - } - - public ThreadLocalCopies copies() { - return this.copies; - } - - private void countValueOffset() { - this.m().alignment.alignPositionAddr(entryBytes); - valueOffset = entryBytes.position(); - } - - public final EntryValueBytesData entryValue; - - public EntryValueBytesData entryValue() { - return this.entryValue; - } - - final WrappedValueInstanceData wrappedValueInstanceValue; - - public WrappedValueInstanceData wrappedValueInstanceValue() { - return this.wrappedValueInstanceValue; - } - - public final DeprecatedMapKeyContextOnIteration deprecatedMapKeyContextOnIteration; - - public DeprecatedMapKeyContextOnIteration deprecatedMapKeyContextOnIteration() { - return this.deprecatedMapKeyContextOnIteration; - } - - private final VanillaChronicleMap m; - - public final VI valueInterop; - - public VI valueInterop() { - return this.valueInterop; - } - - public final BytesStore entryBS; - - public BytesStore entryBS() { - return this.entryBS; - } - - public final BytesReader valueReader; - - public BytesReader valueReader() { - return this.valueReader; - } - - public final KI keyInterop; - - public KI keyInterop() { - return this.keyInterop; - } - - public final BytesReader keyReader; - - public BytesReader keyReader() { - return this.keyReader; - } - - public boolean entryIsPresent() { - return true; - } - - @Override - public VanillaChronicleMap m() { - return m; - } - - @Override - public ChronicleMap map() { - return m(); - } - - public CompiledMapIterationContext createChaining() { - return new CompiledMapIterationContext(this); - } - - public T getContext() { - for (CompiledMapIterationContext context : contextChain) { - if (!(context.usedInit())) { - return ((T)(context)); - } - } - int maxNestedContexts = 1 << 16; - if ((contextChain.size()) > maxNestedContexts) { - throw new IllegalStateException((((((("More than " + maxNestedContexts) + " nested ChronicleHash contexts are not supported. Very probable that ") + "you simply forgot to close context somewhere (recommended to use ") + "try-with-resources statement). ") + "Otherwise this is a bug, please report with this ") + "stack trace on https://github.com/OpenHFT/Chronicle-Map/issues")); - } - return ((T)(createChaining())); - } - - public void incrementSegmentEntriesIfNeeded() { - } - - public void checkEntryNotRemovedOnThisIteration() { - if (entryRemovedOnThisIterationInit()) - throw new IllegalStateException("Entry was already removed on this iteration"); - - } - - public void closeMapSegmentIterationCheckEntryNotRemovedOnThisIterationDependants() { - this.closeIterationCheckOnEachPublicOperationCheckOnEachPublicOperationDependants(); - } - - long sizeOfEverythingBeforeValue(long keySize, long valueSize) { - return (((this.m().metaDataBytes) + (this.m().keySizeMarshaller.sizeEncodingSize(keySize))) + keySize) + (this.m().valueSizeMarshaller.sizeEncodingSize(valueSize)); - } - - @NotNull - @Override - public MapContext context() { - return this; - } - - public MVI valueMetaInterop(V value) { - return this.m().metaValueInteropProvider.get(this.copies, this.m().originalMetaValueInterop, valueInterop, value); - } - - public void closeValueBytesInteropValueMetaInteropDependants() { - this.wrappedValueInstanceValue.closeBuffer(); - } - - public T contextAtIndexInChain(int index) { - return ((T)(contextChain.get(index))); - } - - public void closeVanillaChronicleMapHolderImplContextAtIndexInChainDependants() { - this.closeSegmentStagesTryFindInitLocksOfThisSegmentDependants(); - } - - public MKI keyMetaInterop(K key) { - return this.h().metaKeyInteropProvider.get(this.copies, this.h().originalMetaKeyInterop, keyInterop, key); - } - - public long innerEntrySize(long sizeOfEverythingBeforeValue, long valueSize) { - if (this.m().constantlySizedEntry) { - return this.m().alignment.alignAddr((sizeOfEverythingBeforeValue + valueSize)); - } else if (this.m().couldNotDetermineAlignmentBeforeAllocation) { - return (sizeOfEverythingBeforeValue + (this.m().worstAlignment)) + valueSize; - } else { - return (this.m().alignment.alignAddr(sizeOfEverythingBeforeValue)) + valueSize; - } - } - - public final long entrySize(long keySize, long valueSize) { - long sizeOfEverythingBeforeValue = sizeOfEverythingBeforeValue(keySize, valueSize); - return innerEntrySize(sizeOfEverythingBeforeValue, valueSize); - } - - public void checkAccessingFromOwnerThread() { - if ((owner) != (Thread.currentThread())) { - throw new ConcurrentModificationException("Context shouldn\'t be accessed from multiple threads"); - } - } - - public void closeOwnerThreadHolderCheckAccessingFromOwnerThreadDependants() { - this.closeIterationCheckOnEachPublicOperationCheckOnEachPublicOperationDependants(); - } - - public void checkOnEachPublicOperation() { - _CheckOnEachPublicOperation_checkOnEachPublicOperation(); - this.checkEntryNotRemovedOnThisIteration(); - } - - public void closeIterationCheckOnEachPublicOperationCheckOnEachPublicOperationDependants() { - this.entryValue.closeEntryValueBytesDataSizeDependants(); - this.entryKey.closeEntryKeyBytesDataSizeDependants(); - } - - @NotNull - @Override - public InterProcessLock updateLock() { - this.checkOnEachPublicOperation(); - return this.innerUpdateLock; - } - - @Override - public R replaceValue(@NotNull - MapEntry entry, Data newValue) { - this.checkOnEachPublicOperation(); - return this.m().entryOperations.replaceValue(entry, newValue); - } - - @Override - public Data wrapValueAsValue(V value) { - this.checkOnEachPublicOperation(); - WrappedValueInstanceData wrapped = this.wrappedValueInstanceValue; - wrapped = wrapped.getUnusedWrappedValueGuarded(); - wrapped.initValue(value); - return wrapped; - } - - @NotNull - @Override - public InterProcessLock writeLock() { - this.checkOnEachPublicOperation(); - return this.innerWriteLock; - } - - @NotNull - @Override - public Data value() { - this.checkOnEachPublicOperation(); - return this.entryValue; - } - - @Override - public Data defaultValue(@NotNull - MapAbsentEntry absentEntry) { - this.checkOnEachPublicOperation(); - return this.m().entryOperations.defaultValue(absentEntry); - } - - @Override - public R remove(@NotNull - MapEntry entry) { - this.checkOnEachPublicOperation(); - return this.m().entryOperations.remove(entry); - } - - @NotNull - @Override - public Data key() { - this.checkOnEachPublicOperation(); - return this.entryKey; - } - - @NotNull - @Override - public InterProcessLock readLock() { - this.checkOnEachPublicOperation(); - return this.innerReadLock; - } - - @Override - public R insert(@NotNull - MapAbsentEntry absentEntry, Data value) { - this.checkOnEachPublicOperation(); - return this.m().entryOperations.insert(absentEntry, value); - } - - public long keyOffset = -1; - - public boolean keyOffsetInit() { - return (this.keyOffset) >= 0; - } - - public void initKeyOffset(long keyOffset) { - this.keyOffset = keyOffset; - this.closeKeyOffsetDependants(); - } - - public long keyOffset() { - assert this.keyOffsetInit() : "KeyOffset should be init"; - return this.keyOffset; - } - - public void closeKeyOffset() { - if (!(this.keyOffsetInit())) - return ; - - this.closeKeyOffsetDependants(); - this.keyOffset = -1; - } - - public void closeKeyOffsetDependants() { - this.closeMapEntryStagesKeyEndDependants(); - this.entryKey.closeEntryKeyBytesDataInnerGetUsingDependants(); - } - - public long hashLookupPos = -1; - - public boolean hashLookupPosInit() { - return (this.hashLookupPos) >= 0; - } - - public void initHashLookupPos(long hashLookupPos) { - this.hashLookupPos = hashLookupPos; - } - - public long hashLookupPos() { - assert this.hashLookupPosInit() : "HashLookupPos should be init"; - return this.hashLookupPos; - } - - public void closeHashLookupPos() { - if (!(this.hashLookupPosInit())) - return ; - - this.hashLookupPos = -1; - } - - public int allocatedChunks = 0; - - public boolean allocatedChunksInit() { - return (this.allocatedChunks) != 0; - } - - public void initAllocatedChunks(int allocatedChunks) { - this.allocatedChunks = allocatedChunks; - } - - public int allocatedChunks() { - assert this.allocatedChunksInit() : "AllocatedChunks should be init"; - return this.allocatedChunks; - } - - public void closeAllocatedChunks() { - if (!(this.allocatedChunksInit())) - return ; - - this.allocatedChunks = 0; - } - - public long pos = -1; - - public boolean posInit() { - return (this.pos) >= 0; - } - - public void initPos(long pos) { - this.pos = pos; - this.closePosDependants(); - } - - public long pos() { - assert this.posInit() : "Pos should be init"; - return this.pos; - } - - public void closePos() { - if (!(this.posInit())) - return ; - - this.closePosDependants(); - this.pos = -1; - } - - public void closePosDependants() { - this.closeEntryOffset(); - } - - public long keySize = -1; - - public boolean keySizeInit() { - return (this.keySize) >= 0; - } - - public void initKeySize(long keySize) { - this.keySize = keySize; - this.closeKeySizeDependants(); - } - - public long keySize() { - assert this.keySizeInit() : "KeySize should be init"; - return this.keySize; - } - - public void closeKeySize() { - if (!(this.keySizeInit())) - return ; - - this.closeKeySizeDependants(); - this.keySize = -1; - } - - public void closeKeySizeDependants() { - this.closeMapEntryStagesKeyEndDependants(); - this.entryKey.closeEntryKeyBytesDataSizeDependants(); - } - - public long keyEnd() { - return (keyOffset()) + (keySize()); - } - - public void closeMapEntryStagesKeyEndDependants() { - this.closeMapEntryStagesCountValueSizeOffsetDependants(); - this.closeMapEntryStagesEntryEndDependants(); - } - - long countValueSizeOffset() { - return keyEnd(); - } - - public void closeMapEntryStagesCountValueSizeOffsetDependants() { - this.closeValueSizeOffset(); - } - - public long valueSizeOffset = -1; - - public boolean valueSizeOffsetInit() { - return (this.valueSizeOffset) >= 0; - } - - void initValueSizeOffset() { - valueSizeOffset = countValueSizeOffset(); - this.closeValueSizeOffsetDependants(); - } - - public long valueSizeOffset() { - if (!(this.valueSizeOffsetInit())) - this.initValueSizeOffset(); - - return this.valueSizeOffset; - } - - public void closeValueSizeOffset() { - if (!(this.valueSizeOffsetInit())) - return ; - - this.closeValueSizeOffsetDependants(); - this.valueSizeOffset = -1; - } - - public void closeValueSizeOffsetDependants() { - this.closeValSize(); - } - - public long valueSize = -1; - - public long valueOffset; - - public boolean valSizeInit() { - return (this.valueSize) >= 0; - } - - void initValSize() { - entryBytes.position(valueSizeOffset()); - valueSize = this.m().readValueSize(entryBytes); - countValueOffset(); - this.closeValSizeDependants(); - } - - void initValSize(long valueSize) { - this.valueSize = valueSize; - entryBytes.position(valueSizeOffset()); - this.m().valueSizeMarshaller.writeSize(entryBytes, valueSize); - countValueOffset(); - this.closeValSizeDependants(); - } - - void initValSizeEqualToOld(long oldValueSizeOffset, long oldValueSize, long oldValueOffset) { - valueSize = oldValueSize; - valueOffset = (valueSizeOffset()) + (oldValueOffset - oldValueSizeOffset); - this.closeValSizeDependants(); - } - - public long valueOffset() { - if (!(this.valSizeInit())) - this.initValSize(); - - return this.valueOffset; - } - - public long valueSize() { - if (!(this.valSizeInit())) - this.initValSize(); - - return this.valueSize; - } - - public void closeValSize() { - if (!(this.valSizeInit())) - return ; - - this.closeValSizeDependants(); - this.valueSize = -1; - } - - public void closeValSizeDependants() { - this.closeMapEntryStagesEntryEndDependants(); - this.entryValue.closeEntryValueBytesDataSizeDependants(); - this.entryValue.closeEntryValueBytesDataInnerGetUsingDependants(); - } - - protected long entryEnd() { - return (valueOffset()) + (valueSize()); - } - - public void closeMapEntryStagesEntryEndDependants() { - this.closeMapEntryStagesEntrySizeDependants(); - } - - public void writeValue(Data value) { - value.writeTo(entryBS, valueOffset()); - } - - public void initValue(Data value) { - entryBytes.position(valueSizeOffset()); - initValSize(value.size()); - writeValue(value); - } - - public void initValueWithoutSize(Data value, long oldValueSizeOffset, long oldValueSize, long oldValueOffset) { - assert oldValueSize == (value.size()); - initValSizeEqualToOld(oldValueSizeOffset, oldValueSize, oldValueOffset); - writeValue(value); - } - - boolean used; - - public boolean usedInit() { - return used; - } - - public void initUsed(boolean used) { - this.used = used; - } - - void closeUsed() { - if (!(this.usedInit())) - return ; - - used = false; - } - - public boolean entryRemovedOnThisIteration = false; - - boolean entryRemovedOnThisIterationInit() { - return (this.entryRemovedOnThisIteration) != false; - } - - protected void initEntryRemovedOnThisIteration(boolean entryRemovedOnThisIteration) { - this.entryRemovedOnThisIteration = entryRemovedOnThisIteration; - } - - public void closeEntryRemovedOnThisIteration() { - if (!(this.entryRemovedOnThisIterationInit())) - return ; - - this.entryRemovedOnThisIteration = false; - } - - public int segmentIndex = -1; - - public boolean theSegmentIndexInit() { - return (this.segmentIndex) >= 0; - } - - public void initTheSegmentIndex(int segmentIndex) { - this.segmentIndex = segmentIndex; - this.closeTheSegmentIndexDependants(); - } - - public int segmentIndex() { - assert this.theSegmentIndexInit() : "TheSegmentIndex should be init"; - return this.segmentIndex; - } - - public void closeTheSegmentIndex() { - if (!(this.theSegmentIndexInit())) - return ; - - this.closeTheSegmentIndexDependants(); - this.segmentIndex = -1; - } - - public void closeTheSegmentIndexDependants() { - this.closeSegment(); - this.closeSegmentHashLookup(); - this.closeSegHeader(); - } - - long entrySpaceOffset = 0; - - MultiStoreBytes freeListBytes = new MultiStoreBytes(); - - public SingleThreadedDirectBitSet freeList = new SingleThreadedDirectBitSet(); - - boolean segmentInit() { - return (entrySpaceOffset) > 0; - } - - void initSegment() { - VanillaChronicleHash h = this.h(); - long hashLookupOffset = h.segmentOffset(segmentIndex()); - long freeListOffset = hashLookupOffset + (h.segmentHashLookupOuterSize); - freeListBytes.storePositionAndSize(h.ms, freeListOffset, h.segmentFreeListInnerSize); - freeList.reuse(freeListBytes); - entrySpaceOffset = (freeListOffset + (h.segmentFreeListOuterSize)) + (h.segmentEntrySpaceInnerOffset); - this.closeSegmentDependants(); - } - - public long entrySpaceOffset() { - if (!(this.segmentInit())) - this.initSegment(); - - return this.entrySpaceOffset; - } - - public SingleThreadedDirectBitSet freeList() { - if (!(this.segmentInit())) - this.initSegment(); - - return this.freeList; - } - - void closeSegment() { - if (!(this.segmentInit())) - return ; - - this.closeSegmentDependants(); - entrySpaceOffset = 0; - } - - public void closeSegmentDependants() { - this.closeEntryOffset(); - } - - public long keySizeOffset = -1; - - public boolean entryOffsetInit() { - return (this.keySizeOffset) >= 0; - } - - public void initEntryOffset() { - keySizeOffset = (this.entrySpaceOffset()) + ((pos()) * (this.h().chunkSize)); - entryBytes.limit(entryBytes.capacity()); - this.closeEntryOffsetDependants(); - } - - public long keySizeOffset() { - if (!(this.entryOffsetInit())) - this.initEntryOffset(); - - return this.keySizeOffset; - } - - public void closeEntryOffset() { - if (!(this.entryOffsetInit())) - return ; - - this.closeEntryOffsetDependants(); - this.keySizeOffset = -1; - } - - public void closeEntryOffsetDependants() { - this.closeMapEntryStagesEntrySizeDependants(); - } - - public void writeNewEntry(long pos, Data key) { - initPos(pos); - initKeySize(key.size()); - entryBytes.position(keySizeOffset()); - this.h().keySizeMarshaller.writeSize(entryBytes, keySize()); - initKeyOffset(entryBytes.position()); - key.writeTo(entryBS, keyOffset()); - } - - long entrySize() { - return (entryEnd()) - (keySizeOffset()); - } - - public void closeMapEntryStagesEntrySizeDependants() { - this.closeTheEntrySizeInChunks(); - } - - public int entrySizeInChunks = 0; - - public boolean theEntrySizeInChunksInit() { - return (this.entrySizeInChunks) != 0; - } - - void initTheEntrySizeInChunks() { - entrySizeInChunks = this.h().inChunks(entrySize()); - } - - public void initTheEntrySizeInChunks(int actuallyUsedChunks) { - entrySizeInChunks = actuallyUsedChunks; - } - - public int entrySizeInChunks() { - if (!(this.theEntrySizeInChunksInit())) - this.initTheEntrySizeInChunks(); - - return this.entrySizeInChunks; - } - - public void closeTheEntrySizeInChunks() { - if (!(this.theEntrySizeInChunksInit())) - return ; - - this.entrySizeInChunks = 0; - } - - public void copyExistingEntry(long newPos, long bytesToCopy) { - long oldKeySizeOffset = keySizeOffset(); - long oldKeyOffset = keyOffset(); - initPos(newPos); - initKeyOffset(((keySizeOffset()) + (oldKeyOffset - oldKeySizeOffset))); - entryBS.write(keySizeOffset(), entryBS, oldKeySizeOffset, bytesToCopy); - } - - public long newSizeOfEverythingBeforeValue(Data newValue) { - return ((valueSizeOffset()) + (this.m().valueSizeMarshaller.sizeEncodingSize(newValue.size()))) - (keySizeOffset()); - } - - public void readExistingEntry(long pos) { - initPos(pos); - entryBytes.position(keySizeOffset()); - initKeySize(this.h().keySizeMarshaller.readSize(entryBytes)); - initKeyOffset(entryBytes.position()); - } - - int hashLookupEntrySize; - - int keyBits; - - long address = -1; - - long capacityMask; - - long capacityMask2; - - long keyMask; - - long valueMask; - - long entryMask; - - public boolean segmentHashLookupInit() { - return (this.address) >= 0; - } - - public void initSegmentHashLookup() { - long hashLookupOffset = this.h().segmentOffset(this.segmentIndex()); - innerInitSegmentHashLookup(((this.h().ms.address()) + hashLookupOffset), this.h().segmentHashLookupCapacity, this.h().segmentHashLookupEntrySize, this.h().segmentHashLookupKeyBits, this.h().segmentHashLookupValueBits); - } - - public void initSegmentHashLookup(long address, long capacity, int entrySize, int keyBits, int valueBits) { - innerInitSegmentHashLookup(address, capacity, entrySize, keyBits, valueBits); - } - - public int hashLookupEntrySize() { - if (!(this.segmentHashLookupInit())) - this.initSegmentHashLookup(); - - return this.hashLookupEntrySize; - } - - public int keyBits() { - if (!(this.segmentHashLookupInit())) - this.initSegmentHashLookup(); - - return this.keyBits; - } - - public long address() { - if (!(this.segmentHashLookupInit())) - this.initSegmentHashLookup(); - - return this.address; - } - - public long capacityMask() { - if (!(this.segmentHashLookupInit())) - this.initSegmentHashLookup(); - - return this.capacityMask; - } - - public long capacityMask2() { - if (!(this.segmentHashLookupInit())) - this.initSegmentHashLookup(); - - return this.capacityMask2; - } - - public long entryMask() { - if (!(this.segmentHashLookupInit())) - this.initSegmentHashLookup(); - - return this.entryMask; - } - - public long keyMask() { - if (!(this.segmentHashLookupInit())) - this.initSegmentHashLookup(); - - return this.keyMask; - } - - public long valueMask() { - if (!(this.segmentHashLookupInit())) - this.initSegmentHashLookup(); - - return this.valueMask; - } - - public void closeSegmentHashLookup() { - if (!(this.segmentHashLookupInit())) - return ; - - this.address = -1; - } - - public long readEntry(long pos) { - return NativeBytes.UNSAFE.getLong(((address()) + pos)); - } - - public long step(long pos) { - return (pos += hashLookupEntrySize()) <= (capacityMask2()) ? pos : 0L; - } - - public long stepBack(long pos) { - return (pos -= hashLookupEntrySize()) >= 0 ? pos : capacityMask2(); - } - - long indexToPos(long index) { - return index * (hashLookupEntrySize()); - } - - public long maskUnsetKey(long key) { - return (key &= keyMask()) != (UNSET_KEY) ? key : keyMask(); - } - - long entry(long key, long value) { - return key | (value << (keyBits())); - } - - public void writeEntryVolatile(long pos, long prevEntry, long key, long value) { - long entry = (prevEntry & (~(entryMask()))) | (entry(key, value)); - NativeBytes.UNSAFE.putLongVolatile(null, ((address()) + pos), entry); - } - - public void clearHashLookup() { - NativeBytes.UNSAFE.setMemory(address(), ((capacityMask2()) + (hashLookupEntrySize())), ((byte)(0))); - } - - public long key(long entry) { - return entry & (keyMask()); - } - - public void writeEntry(long pos, long prevEntry, long key, long value) { - long entry = (prevEntry & (~(entryMask()))) | (entry(key, value)); - NativeBytes.UNSAFE.putLong(((address()) + pos), entry); - } - - void writeEntry(long pos, long prevEntry, long anotherEntry) { - long entry = (prevEntry & (~(entryMask()))) | (anotherEntry & (entryMask())); - NativeBytes.UNSAFE.putLong(((address()) + pos), entry); - } - - public long value(long entry) { - return (entry >>> (keyBits())) & (valueMask()); - } - - public long hlPos(long key) { - return indexToPos((key & (capacityMask()))); - } - - public void checkValueForPut(long value) { - assert (value & (~(valueMask()))) == 0L : "Value out of range, was " + value; - } - - public void putValueVolatile(long pos, long value) { - checkValueForPut(value); - long currentEntry = readEntry(pos); - writeEntryVolatile(pos, currentEntry, key(currentEntry), value); - } - - void clearEntry(long pos, long prevEntry) { - long entry = prevEntry & (~(entryMask())); - NativeBytes.UNSAFE.putLong(((address()) + pos), entry); - } - - public boolean empty(long entry) { - return (entry & (entryMask())) == (UNSET_ENTRY); - } - - public long remove(long posToRemove) { - long entryToRemove = readEntry(posToRemove); - long posToShift = posToRemove; - while (true) { - posToShift = step(posToShift); - long entryToShift = readEntry(posToShift); - if (empty(entryToShift)) - break; - - long insertPos = hlPos(key(entryToShift)); - boolean cond1 = insertPos <= posToRemove; - boolean cond2 = posToRemove <= posToShift; - if ((cond1 && cond2) || ((posToShift < insertPos) && (cond1 || cond2))) { - writeEntry(posToRemove, entryToRemove, entryToShift); - posToRemove = posToShift; - entryToRemove = entryToShift; - } - } - clearEntry(posToRemove, entryToRemove); - return posToRemove; - } - - void forEach(EntryConsumer action) { - for (long pos = 0L ; pos <= (capacityMask2()) ; pos += hashLookupEntrySize()) { - long entry = readEntry(pos); - if (!(empty(entry))) - action.accept(key(entry), value(entry)); - - } - } - - String hashLookupToString() { - final StringBuilder sb = new StringBuilder("{"); - forEach((long key,long value) -> sb.append(key).append('=').append(value).append(',')); - sb.append('}'); - return sb.toString(); - } - - long segmentHeaderAddress; - - SegmentHeader segmentHeader = null; - - public boolean segHeaderInit() { - return (this.segmentHeader) != null; - } - - private void initSegHeader() { - segmentHeaderAddress = (this.h().ms.address()) + (this.h().segmentHeaderOffset(segmentIndex())); - segmentHeader = BigSegmentHeader.INSTANCE; - this.closeSegHeaderDependants(); - } - - public long segmentHeaderAddress() { - if (!(this.segHeaderInit())) - this.initSegHeader(); - - return this.segmentHeaderAddress; - } - - public SegmentHeader segmentHeader() { - if (!(this.segHeaderInit())) - this.initSegHeader(); - - return this.segmentHeader; - } - - public void closeSegHeader() { - if (!(this.segHeaderInit())) - return ; - - this.closeSegHeaderDependants(); - this.segmentHeader = null; - } - - public void closeSegHeaderDependants() { - this.closeSegmentStagesTryFindInitLocksOfThisSegmentDependants(); - this.closeLocks(); - } - - public void nextPosToSearchFrom(long nextPosToSearchFrom) { - segmentHeader().nextPosToSearchFrom(segmentHeaderAddress(), nextPosToSearchFrom); - } - - public void updateNextPosToSearchFrom(long allocated, int chunks) { - long nextPosToSearchFrom = allocated + chunks; - if (nextPosToSearchFrom >= (this.h().actualChunksPerSegment)) - nextPosToSearchFrom = 0L; - - nextPosToSearchFrom(nextPosToSearchFrom); - } - - long nextPosToSearchFrom() { - return segmentHeader().nextPosToSearchFrom(segmentHeaderAddress()); - } - - public long alloc(int chunks) { - VanillaChronicleHash h = this.h(); - if (chunks > (h.maxChunksPerEntry)) - throw new IllegalArgumentException((((("Entry is too large: requires " + chunks) + " entry size chucks, ") + (h.maxChunksPerEntry)) + " is maximum.")); - - long ret = freeList().setNextNContinuousClearBits(nextPosToSearchFrom(), chunks); - if ((ret == (DirectBitSet.NOT_FOUND)) || ((ret + chunks) > (h.actualChunksPerSegment))) { - if (((ret != (DirectBitSet.NOT_FOUND)) && ((ret + chunks) > (h.actualChunksPerSegment))) && (ret < (h.actualChunksPerSegment))) - freeList().clear(ret, h.actualChunksPerSegment); - - ret = freeList().setNextNContinuousClearBits(0L, chunks); - if ((ret == (DirectBitSet.NOT_FOUND)) || ((ret + chunks) > (h.actualChunksPerSegment))) { - if (((ret != (DirectBitSet.NOT_FOUND)) && ((ret + chunks) > (h.actualChunksPerSegment))) && (ret < (h.actualChunksPerSegment))) - freeList().clear(ret, h.actualChunksPerSegment); - - if (chunks == 1) { - throw new IllegalStateException("Segment is full, no free entries found"); - } else { - throw new IllegalStateException((("Segment is full or has no ranges of " + chunks) + " continuous free chunks")); - } - } - updateNextPosToSearchFrom(ret, chunks); - } else { - if ((chunks == 1) || (freeList().isSet(nextPosToSearchFrom()))) { - updateNextPosToSearchFrom(ret, chunks); - } - } - return ret; - } - - public void initEntryAndKeyCopying(long entrySize, long bytesToCopy) { - initAllocatedChunks(this.h().inChunks(entrySize)); - this.copyExistingEntry(this.alloc(allocatedChunks()), bytesToCopy); - incrementSegmentEntriesIfNeeded(); - } - - public void free(long fromPos, int chunks) { - freeList().clear(fromPos, (fromPos + chunks)); - if (fromPos < (nextPosToSearchFrom())) - nextPosToSearchFrom(fromPos); - - } - - public final void freeExtraAllocatedChunks() { - if (((!(this.m().constantlySizedEntry)) && (this.m().couldNotDetermineAlignmentBeforeAllocation)) && ((entrySizeInChunks()) < (this.allocatedChunks()))) { - this.free(((pos()) + (entrySizeInChunks())), ((this.allocatedChunks()) - (entrySizeInChunks()))); - } else { - initTheEntrySizeInChunks(this.allocatedChunks()); - } - } - - public void writeValueAndPutPos(Data value) { - initValue(value); - freeExtraAllocatedChunks(); - this.putValueVolatile(this.hashLookupPos(), pos()); - } - - protected void relocation(Data newValue, long newSizeOfEverythingBeforeValue) { - this.free(pos(), entrySizeInChunks()); - long entrySize = innerEntrySize(newSizeOfEverythingBeforeValue, newValue.size()); - this.initEntryAndKeyCopying(entrySize, ((valueSizeOffset()) - (keySizeOffset()))); - writeValueAndPutPos(newValue); - } - - boolean tryFindInitLocksOfThisSegment(Object thisContext, int index) { - CompiledMapIterationContext c = this.contextAtIndexInChain(index); - if ((((c.segmentHeader()) != null) && ((c.segmentHeaderAddress()) == (segmentHeaderAddress()))) && ((c.rootContextOnThisSegment()) != null)) { - throw new IllegalStateException("Nested context not implemented yet"); - } else { - return false; - } - } - - public void closeSegmentStagesTryFindInitLocksOfThisSegmentDependants() { - this.closeLocks(); - } - - public void deleted(long deleted) { - segmentHeader().deleted(segmentHeaderAddress(), deleted); - } - - public long deleted() { - return segmentHeader().deleted(segmentHeaderAddress()); - } - - public void entries(long size) { - segmentHeader().size(segmentHeaderAddress(), size); - } - - public long entries() { - return segmentHeader().size(segmentHeaderAddress()); - } - - public long size() { - return (entries()) - (deleted()); - } - - int totalReadLockCount; - - int totalUpdateLockCount; - - int totalWriteLockCount; - - public int latestSameThreadSegmentModCount; - - public int contextModCount; - - CompiledMapIterationContext nextNode; - - public boolean concurrentSameThreadContexts; - - LocalLockState localLockState; - - public CompiledMapIterationContext rootContextOnThisSegment = null; - - public boolean locksInit() { - return (this.rootContextOnThisSegment) != null; - } - - void initLocks() { - localLockState = LocalLockState.UNLOCKED; - int indexOfThisContext = this.indexInContextChain; - for (int i = indexOfThisContext - 1 ; i >= 0 ; i--) { - if (tryFindInitLocksOfThisSegment(this, i)) - return ; - - } - for (int i = indexOfThisContext + 1, size = this.contextChain.size() ; i < size ; i++) { - if (tryFindInitLocksOfThisSegment(this, i)) - return ; - - } - rootContextOnThisSegment = this; - concurrentSameThreadContexts = false; - latestSameThreadSegmentModCount = 0; - contextModCount = 0; - nextNode = null; - totalReadLockCount = 0; - totalUpdateLockCount = 0; - totalWriteLockCount = 0; - } - - public LocalLockState localLockState() { - if (!(this.locksInit())) - this.initLocks(); - - return this.localLockState; - } - - public CompiledMapIterationContext rootContextOnThisSegment() { - if (!(this.locksInit())) - this.initLocks(); - - return this.rootContextOnThisSegment; - } - - void closeLocks() { - if (!(this.locksInit())) - return ; - - if ((rootContextOnThisSegment) == (this)) { - closeRootLocks(); - } else { - closeNestedLocks(); - } - localLockState = null; - rootContextOnThisSegment = null; - } - - public boolean forEachRemoving(Predicate> action) { - this.innerUpdateLock.lock(); - try { - long size = this.size(); - if (size == 0) - return true; - - boolean interrupted = false; - long startPos = 0L; - while (!(this.empty(this.readEntry(startPos)))) { - startPos = this.step(startPos); - } - this.initHashLookupPos(startPos); - do { - this.setHashLookupPosGuarded(this.step(this.hashLookupPos())); - long entry = this.readEntry(this.hashLookupPos()); - if (!(this.empty(entry))) { - this.readExistingEntry(this.value(entry)); - if (entryIsPresent()) { - initEntryRemovedOnThisIteration(false); - if (!(action.test(((MapEntry)(this))))) { - interrupted = true; - break; - } else { - if ((--size) == 0) - break; - - } - } - } - } while ((this.hashLookupPos()) != startPos ); - return !interrupted; - } finally { - this.innerReadLock.unlock(); - initEntryRemovedOnThisIteration(false); - } - } - - public void innerRemoveEntryExceptHashLookupUpdate() { - this.free(pos(), entrySizeInChunks()); - this.entries(((this.entries()) - 1L)); - this.incrementModCountGuarded(); - } - - @Override - public void doRemove() { - this.checkOnEachPublicOperation(); - initEntryRemovedOnThisIteration(true); - this.innerWriteLock.lock(); - try { - if ((this.remove(this.hashLookupPos())) != (this.hashLookupPos())) { - this.setHashLookupPosGuarded(this.stepBack(this.hashLookupPos())); - } - this.innerRemoveEntryExceptHashLookupUpdate(); - } finally { - this.innerWriteLock.unlock(); - } - } - - public void putValueDeletedEntry(Data newValue) { - assert this.innerUpdateLock.isHeldByCurrentThread(); - int newSizeInChunks; - long entryStartOffset = keySizeOffset(); - long newSizeOfEverythingBeforeValue = -1; - boolean newValueSizeIsDifferent = (newValue.size()) != (valueSize()); - if (newValueSizeIsDifferent) { - newSizeOfEverythingBeforeValue = newSizeOfEverythingBeforeValue(newValue); - long newValueOffset = this.m().alignment.alignAddr((entryStartOffset + newSizeOfEverythingBeforeValue)); - long newEntrySize = (newValueOffset + (newValue.size())) - entryStartOffset; - newSizeInChunks = this.m().inChunks(newEntrySize); - } else { - newSizeInChunks = entrySizeInChunks(); - } - if ((((pos()) + newSizeInChunks) < (this.freeList().size())) && (this.freeList().allClear(pos(), ((pos()) + newSizeInChunks)))) { - this.freeList().set(pos(), ((pos()) + newSizeInChunks)); - this.innerWriteLock.lock(); - this.incrementSegmentEntriesIfNeeded(); - if (newValueSizeIsDifferent) { - initValue(newValue); - } else { - writeValue(newValue); - } - } else { - if (newValueSizeIsDifferent) { - assert newSizeOfEverythingBeforeValue >= 0; - } else { - newSizeOfEverythingBeforeValue = newSizeOfEverythingBeforeValue(newValue); - } - long entrySize = innerEntrySize(newSizeOfEverythingBeforeValue, newValue.size()); - if (newValueSizeIsDifferent) { - this.initEntryAndKeyCopying(entrySize, ((valueSizeOffset()) - entryStartOffset)); - initValue(newValue); - } else { - long oldValueSizeOffset = valueSizeOffset(); - long oldValueSize = valueSize(); - long oldValueOffset = valueOffset(); - this.initEntryAndKeyCopying(entrySize, ((valueOffset()) - entryStartOffset)); - initValueWithoutSize(newValue, oldValueSizeOffset, oldValueSize, oldValueOffset); - } - freeExtraAllocatedChunks(); - } - this.putValueVolatile(this.hashLookupPos(), pos()); - } - - public void innerDefaultReplaceValue(Data newValue) { - assert this.innerUpdateLock.isHeldByCurrentThread(); - boolean newValueSizeIsDifferent = (newValue.size()) != (this.valueSize()); - if (newValueSizeIsDifferent) { - long newSizeOfEverythingBeforeValue = newSizeOfEverythingBeforeValue(newValue); - long entryStartOffset = keySizeOffset(); - VanillaChronicleMap m = this.m(); - long newValueOffset = m.alignment.alignAddr((entryStartOffset + newSizeOfEverythingBeforeValue)); - long newEntrySize = (newValueOffset + (newValue.size())) - entryStartOffset; - int newSizeInChunks = m.inChunks(newEntrySize); - newValueDoesNotFit : if (newSizeInChunks > (entrySizeInChunks())) { - if (newSizeInChunks > (m.maxChunksPerEntry)) { - throw new IllegalArgumentException(((((("Value too large: " + "entry takes ") + newSizeInChunks) + " chunks, ") + (m.maxChunksPerEntry)) + " is maximum.")); - } - if (this.freeList().allClear(((pos()) + (entrySizeInChunks())), ((pos()) + newSizeInChunks))) { - this.freeList().set(((pos()) + (entrySizeInChunks())), ((pos()) + newSizeInChunks)); - break newValueDoesNotFit; - } - relocation(newValue, newSizeOfEverythingBeforeValue); - return ; - } else if (newSizeInChunks < (entrySizeInChunks())) { - this.freeList().clear(((pos()) + newSizeInChunks), ((pos()) + (entrySizeInChunks()))); - } - } else { - } - this.innerWriteLock.lock(); - if (newValueSizeIsDifferent) { - initValue(newValue); - } else { - writeValue(newValue); - } - this.putValueVolatile(this.hashLookupPos(), pos()); - } - - @Override - public void doReplaceValue(Data newValue) { - this.checkOnEachPublicOperation(); - try { - this.innerDefaultReplaceValue(newValue); - } finally { - this.innerWriteLock.unlock(); - } - } - - public void clearSegment() { - this.innerWriteLock.lock(); - this.clearHashLookup(); - freeList().clear(); - nextPosToSearchFrom(0L); - entries(0L); - } - - public void clear() { - clearSegment(); - } -} diff --git a/src/main/java/net/openhft/chronicle/map/impl/CompiledMapQueryContext.java b/src/main/java/net/openhft/chronicle/map/impl/CompiledMapQueryContext.java deleted file mode 100644 index 56be52e15..000000000 --- a/src/main/java/net/openhft/chronicle/map/impl/CompiledMapQueryContext.java +++ /dev/null @@ -1,3487 +0,0 @@ -/* - * Copyright 2015 Higher Frequency Trading - * - * http://www.higherfrequencytrading.com - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package net.openhft.chronicle.map.impl; - -import net.openhft.chronicle.bytes.BytesStore; -import net.openhft.chronicle.bytes.BytesUtil; -import net.openhft.chronicle.bytes.NativeBytesStore; -import net.openhft.chronicle.bytes.RandomDataInput; -import net.openhft.chronicle.hash.AbstractData; -import net.openhft.chronicle.hash.Data; -import net.openhft.chronicle.hash.HashEntry; -import net.openhft.chronicle.hash.impl.*; -import net.openhft.chronicle.hash.impl.hashlookup.EntryConsumer; -import net.openhft.chronicle.hash.impl.value.instance.KeyInitableData; -import net.openhft.chronicle.hash.locks.InterProcessLock; -import net.openhft.chronicle.hash.locks.InterProcessReadWriteUpdateLock; -import net.openhft.chronicle.hash.serialization.BytesReader; -import net.openhft.chronicle.hash.serialization.internal.MetaBytesInterop; -import net.openhft.chronicle.map.*; -import net.openhft.chronicle.map.impl.data.instance.ValueInitableData; -import net.openhft.chronicle.map.impl.ret.InstanceReturnValue; -import net.openhft.chronicle.map.impl.ret.UsableReturnValue; -import net.openhft.lang.Maths; -import net.openhft.lang.MemoryUnit; -import net.openhft.lang.collection.DirectBitSet; -import net.openhft.lang.collection.SingleThreadedDirectBitSet; -import net.openhft.lang.io.Bytes; -import net.openhft.lang.io.DirectBytes; -import net.openhft.lang.io.MultiStoreBytes; -import net.openhft.lang.io.NativeBytes; -import net.openhft.lang.threadlocal.ThreadLocalCopies; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -import java.util.ArrayList; -import java.util.ConcurrentModificationException; -import java.util.List; -import java.util.concurrent.TimeUnit; - -public class CompiledMapQueryContext, V, VI, MVI extends MetaBytesInterop, R> implements AutoCloseable , HashEntry , InterProcessReadWriteUpdateLock , ExternalMapQueryContext , MapAbsentEntry , MapContext , MapEntry , MapAbsentEntryHolder , QueryContextInterface , VanillaChronicleMapHolder { - public void close() { - this.wrappedValueInstanceValue.closeValue(); - this.inputValueInstanceValue.closeValue(); - this.closeInputBytes(); - this.wrappedValueInstanceValue.closeNext(); - this.usingReturnValue.closeUsingReturnValue(); - this.defaultReturnValue.closeDefaultReturnedValue(); - this.closeUsed(); - this.closeKeySize(); - this.inputKeyInstanceValue.closeKey(); - this.closePos(); - this.closeInputKey(); - this.closeAllocatedChunks(); - this.closeKeyOffset(); - this.closeKeyBytesInteropKeyMetaInteropDependants(); - this.closeVanillaChronicleMapHolderImplContextAtIndexInChainDependants(); - this.closeOwnerThreadHolderCheckAccessingFromOwnerThreadDependants(); - this.closeValueBytesInteropValueMetaInteropDependants(); - } - - public void incrementModCountGuarded() { - if (!(this.locksInit())) - this.initLocks(); - - incrementModCount(); - } - - public void setHashLookupPosGuarded(long hashLookupPos) { - if (!(this.hashLookupPosInit())) - this.initHashLookupPos(); - - setHashLookupPos(hashLookupPos); - } - - public void setLocalLockStateGuarded(LocalLockState newState) { - if (!(this.locksInit())) - this.initLocks(); - - setLocalLockState(newState); - } - - public void setSearchStateGuarded(CompiledMapQueryContext.SearchState newSearchState) { - if (!(this.keySearchInit())) - this.initKeySearch(); - - setSearchState(newSearchState); - } - - void keyFound() { - searchState = CompiledMapQueryContext.SearchState.PRESENT; - } - - public CompiledMapQueryContext(VanillaChronicleMap m) { - contextChain = new ArrayList(); - contextChain.add(this); - indexInContextChain = 0; - this.m = m; - this.inputKeyBytesValue = new InputKeyBytesData(); - this.defaultReturnValue = new DefaultReturnValue(); - this.inputValueInstanceValue = new InputValueInstanceData(); - this.copies = ThreadLocalCopies.get(); - this.valueInterop = this.m().valueInteropProvider.get(this.copies, this.m().originalValueInterop); - this.valueReader = this.m().valueReaderProvider.get(this.copies, this.m().originalValueReader); - this.keyInterop = this.h().keyInteropProvider.get(this.copies, this.h().originalKeyInterop); - this.keyReader = this.h().keyReaderProvider.get(this.copies, this.h().originalKeyReader); - this.deprecatedMapAcquireContext = new DeprecatedMapAcquireContextOnQuery(); - this.usingReturnValue = new UsingReturnValue(); - this.entryKey = new EntryKeyBytesData(); - this.innerUpdateLock = new UpdateLock(); - this.innerReadLock = new ReadLock(); - this.inputStore = new JavaLangBytesReusableBytesStore(); - this.deprecatedMapKeyContext = new DeprecatedMapKeyContextOnQuery(); - this.entryValue = new EntryValueBytesData(); - this.innerWriteLock = new WriteLock(); - this.entryBytes = this.h().ms.bytes(); - this.entryBS = new NativeBytesStore(entryBytes.address() , entryBytes.capacity() , null , false); - this.owner = Thread.currentThread(); - this.inputFirstValueBytesValue = new InputFirstValueBytesData(); - this.inputKeyInstanceValue = new InputKeyInstanceData(); - this.wrappedValueInstanceValue = new WrappedValueInstanceData(); - this.inputSecondValueBytesValue = new InputSecondValueBytesData(); - } - - public CompiledMapQueryContext(CompiledMapQueryContext c) { - contextChain = c.contextChain; - indexInContextChain = contextChain.size(); - contextChain.add(this); - this.m = ((VanillaChronicleMap)(c.m)); - this.inputKeyBytesValue = new InputKeyBytesData(); - this.defaultReturnValue = new DefaultReturnValue(); - this.inputValueInstanceValue = new InputValueInstanceData(); - this.copies = ThreadLocalCopies.get(); - this.valueInterop = this.m().valueInteropProvider.get(this.copies, this.m().originalValueInterop); - this.valueReader = this.m().valueReaderProvider.get(this.copies, this.m().originalValueReader); - this.keyInterop = this.h().keyInteropProvider.get(this.copies, this.h().originalKeyInterop); - this.keyReader = this.h().keyReaderProvider.get(this.copies, this.h().originalKeyReader); - this.deprecatedMapAcquireContext = new DeprecatedMapAcquireContextOnQuery(); - this.usingReturnValue = new UsingReturnValue(); - this.entryKey = new EntryKeyBytesData(); - this.innerUpdateLock = new UpdateLock(); - this.innerReadLock = new ReadLock(); - this.inputStore = new JavaLangBytesReusableBytesStore(); - this.deprecatedMapKeyContext = new DeprecatedMapKeyContextOnQuery(); - this.entryValue = new EntryValueBytesData(); - this.innerWriteLock = new WriteLock(); - this.entryBytes = this.h().ms.bytes(); - this.entryBS = new NativeBytesStore(entryBytes.address() , entryBytes.capacity() , null , false); - this.owner = Thread.currentThread(); - this.inputFirstValueBytesValue = new InputFirstValueBytesData(); - this.inputKeyInstanceValue = new InputKeyInstanceData(); - this.wrappedValueInstanceValue = new WrappedValueInstanceData(); - this.inputSecondValueBytesValue = new InputSecondValueBytesData(); - } - - public class DeprecatedMapAcquireContextOnQuery implements MapKeyContext { - @NotNull - @Override - public InterProcessLock writeLock() { - return CompiledMapQueryContext.this.writeLock(); - } - - @NotNull - @Override - public InterProcessLock readLock() { - return CompiledMapQueryContext.this.readLock(); - } - - @NotNull - @Override - public InterProcessLock updateLock() { - return CompiledMapQueryContext.this.updateLock(); - } - - @Override - public long valueOffset() { - CompiledMapQueryContext.this.checkOnEachPublicOperation(); - return CompiledMapQueryContext.this.valueOffset(); - } - - @Override - public long keyOffset() { - CompiledMapQueryContext.this.checkOnEachPublicOperation(); - return CompiledMapQueryContext.this.keyOffset(); - } - - @NotNull - @Override - public Bytes entry() { - CompiledMapQueryContext.this.checkOnEachPublicOperation(); - return CompiledMapQueryContext.this.entryBytes; - } - - @Override - public long keySize() { - CompiledMapQueryContext.this.checkOnEachPublicOperation(); - return CompiledMapQueryContext.this.keySize(); - } - - @NotNull - @Override - public K key() { - CompiledMapQueryContext.this.checkOnEachPublicOperation(); - return CompiledMapQueryContext.this.queriedKey().get(); - } - - @Override - public long valueSize() { - CompiledMapQueryContext.this.checkOnEachPublicOperation(); - return CompiledMapQueryContext.this.valueSize(); - } - - @Override - public boolean valueEqualTo(V value) { - CompiledMapQueryContext.this.checkOnEachPublicOperation(); - return Data.bytesEquivalent(CompiledMapQueryContext.this.entryValue, CompiledMapQueryContext.this.wrapValueAsValue(value)); - } - - @Override - public boolean remove() { - CompiledMapQueryContext.this.checkOnEachPublicOperation(); - updateLock().lock(); - MapEntry entry = CompiledMapQueryContext.this.entry(); - if (entry != null) { - CompiledMapQueryContext.this.remove(entry); - return true; - } else { - return false; - } - } - - @Override - public boolean containsKey() { - CompiledMapQueryContext.this.checkOnEachPublicOperation(); - return (CompiledMapQueryContext.this.entry()) != null; - } - - @Override - public V getUsing(V usingValue) { - return containsKey() ? CompiledMapQueryContext.this.value().getUsing(usingValue) : null; - } - - @Override - public boolean put(V newValue) { - CompiledMapQueryContext.this.checkOnEachPublicOperation(); - updateLock().lock(); - MapEntry entry = CompiledMapQueryContext.this.entry(); - if (entry != null) { - CompiledMapQueryContext.this.replaceValue(entry, CompiledMapQueryContext.this.wrapValueAsValue(newValue)); - } else { - CompiledMapQueryContext.this.insert(CompiledMapQueryContext.this.absentEntry(), CompiledMapQueryContext.this.wrapValueAsValue(newValue)); - } - return true; - } - - @Override - public V get() { - assert containsKey(); - return CompiledMapQueryContext.this.usingReturnValue.returnValue(); - } - - @Override - public void close() { - CompiledMapQueryContext.this.checkOnEachPublicOperation(); - put(CompiledMapQueryContext.this.usingReturnValue.returnValue()); - CompiledMapQueryContext.this.close(); - } - } - - public class DeprecatedMapKeyContextOnQuery implements MapKeyContext { - @NotNull - @Override - public InterProcessLock writeLock() { - return CompiledMapQueryContext.this.writeLock(); - } - - @NotNull - @Override - public InterProcessLock readLock() { - return CompiledMapQueryContext.this.readLock(); - } - - @NotNull - @Override - public InterProcessLock updateLock() { - return CompiledMapQueryContext.this.updateLock(); - } - - @Override - public long keySize() { - CompiledMapQueryContext.this.checkOnEachPublicOperation(); - return CompiledMapQueryContext.this.keySize(); - } - - @Override - public long valueSize() { - CompiledMapQueryContext.this.checkOnEachPublicOperation(); - return CompiledMapQueryContext.this.valueSize(); - } - - @Override - public void close() { - CompiledMapQueryContext.this.checkOnEachPublicOperation(); - CompiledMapQueryContext.this.close(); - } - - @Override - public boolean valueEqualTo(V value) { - CompiledMapQueryContext.this.checkOnEachPublicOperation(); - return Data.bytesEquivalent(CompiledMapQueryContext.this.entryValue, CompiledMapQueryContext.this.wrapValueAsValue(value)); - } - - @Override - public long valueOffset() { - CompiledMapQueryContext.this.checkOnEachPublicOperation(); - return CompiledMapQueryContext.this.valueOffset(); - } - - @NotNull - @Override - public Bytes entry() { - CompiledMapQueryContext.this.checkOnEachPublicOperation(); - return CompiledMapQueryContext.this.entryBytes; - } - - @Override - public long keyOffset() { - CompiledMapQueryContext.this.checkOnEachPublicOperation(); - return CompiledMapQueryContext.this.keyOffset(); - } - - @NotNull - @Override - public K key() { - CompiledMapQueryContext.this.checkOnEachPublicOperation(); - return CompiledMapQueryContext.this.queriedKey().get(); - } - - @Override - public boolean remove() { - CompiledMapQueryContext.this.checkOnEachPublicOperation(); - updateLock().lock(); - MapEntry entry = CompiledMapQueryContext.this.entry(); - if (entry != null) { - CompiledMapQueryContext.this.remove(entry); - return true; - } else { - return false; - } - } - - @Override - public boolean containsKey() { - CompiledMapQueryContext.this.checkOnEachPublicOperation(); - return (CompiledMapQueryContext.this.entry()) != null; - } - - @Override - public V getUsing(V usingValue) { - return containsKey() ? CompiledMapQueryContext.this.value().getUsing(usingValue) : null; - } - - @Override - public V get() { - return containsKey() ? CompiledMapQueryContext.this.value().get() : null; - } - - @Override - public boolean put(V newValue) { - CompiledMapQueryContext.this.checkOnEachPublicOperation(); - updateLock().lock(); - MapEntry entry = CompiledMapQueryContext.this.entry(); - if (entry != null) { - CompiledMapQueryContext.this.replaceValue(entry, CompiledMapQueryContext.this.wrapValueAsValue(newValue)); - } else { - CompiledMapQueryContext.this.insert(CompiledMapQueryContext.this.absentEntry(), CompiledMapQueryContext.this.wrapValueAsValue(newValue)); - } - return true; - } - } - - public class EntryKeyBytesData extends AbstractData { - @Override - public long offset() { - CompiledMapQueryContext.this.checkOnEachPublicOperation(); - return CompiledMapQueryContext.this.keyOffset(); - } - - @Override - public long size() { - CompiledMapQueryContext.this.checkOnEachPublicOperation(); - return CompiledMapQueryContext.this.keySize(); - } - - public void closeEntryKeyBytesDataSizeDependants() { - this.closeEntryKeyBytesDataInnerGetUsingDependants(); - } - - private K innerGetUsing(K usingKey) { - CompiledMapQueryContext.this.entryBytes.position(CompiledMapQueryContext.this.keyOffset()); - return CompiledMapQueryContext.this.keyReader.read(CompiledMapQueryContext.this.entryBytes, size(), usingKey); - } - - public void closeEntryKeyBytesDataInnerGetUsingDependants() { - this.closeCachedEntryKey(); - } - - private K cachedEntryKey; - - private boolean cachedEntryKeyRead = false; - - public boolean cachedEntryKeyInit() { - return (this.cachedEntryKeyRead) != false; - } - - private void initCachedEntryKey() { - cachedEntryKey = innerGetUsing(cachedEntryKey); - cachedEntryKeyRead = true; - } - - public K cachedEntryKey() { - if (!(this.cachedEntryKeyInit())) - this.initCachedEntryKey(); - - return this.cachedEntryKey; - } - - public void closeCachedEntryKey() { - if (!(this.cachedEntryKeyInit())) - return ; - - this.cachedEntryKeyRead = false; - } - - @Override - public K get() { - CompiledMapQueryContext.this.checkOnEachPublicOperation(); - return cachedEntryKey(); - } - - @Override - public K getUsing(K usingKey) { - CompiledMapQueryContext.this.checkOnEachPublicOperation(); - return innerGetUsing(usingKey); - } - - @Override - public RandomDataInput bytes() { - CompiledMapQueryContext.this.checkOnEachPublicOperation(); - return CompiledMapQueryContext.this.entryBS; - } - } - - public class EntryValueBytesData extends AbstractData { - @Override - public long offset() { - CompiledMapQueryContext.this.checkOnEachPublicOperation(); - return CompiledMapQueryContext.this.valueOffset(); - } - - @Override - public long size() { - CompiledMapQueryContext.this.checkOnEachPublicOperation(); - return CompiledMapQueryContext.this.valueSize(); - } - - public void closeEntryValueBytesDataSizeDependants() { - this.closeEntryValueBytesDataInnerGetUsingDependants(); - } - - private V innerGetUsing(V usingValue) { - CompiledMapQueryContext.this.entryBytes.position(CompiledMapQueryContext.this.valueOffset()); - return CompiledMapQueryContext.this.valueReader.read(CompiledMapQueryContext.this.entryBytes, size(), usingValue); - } - - public void closeEntryValueBytesDataInnerGetUsingDependants() { - this.closeCachedEntryValue(); - } - - private V cachedEntryValue; - - private boolean cachedEntryValueRead = false; - - public boolean cachedEntryValueInit() { - return (this.cachedEntryValueRead) != false; - } - - private void initCachedEntryValue() { - cachedEntryValue = innerGetUsing(cachedEntryValue); - cachedEntryValueRead = true; - } - - public V cachedEntryValue() { - if (!(this.cachedEntryValueInit())) - this.initCachedEntryValue(); - - return this.cachedEntryValue; - } - - public void closeCachedEntryValue() { - if (!(this.cachedEntryValueInit())) - return ; - - this.cachedEntryValueRead = false; - } - - @Override - public V get() { - CompiledMapQueryContext.this.checkOnEachPublicOperation(); - return cachedEntryValue(); - } - - @Override - public V getUsing(V usingValue) { - CompiledMapQueryContext.this.checkOnEachPublicOperation(); - return innerGetUsing(usingValue); - } - - @Override - public RandomDataInput bytes() { - CompiledMapQueryContext.this.checkOnEachPublicOperation(); - return CompiledMapQueryContext.this.entryBS; - } - } - - public class InputFirstValueBytesData extends AbstractData { - @Override - public RandomDataInput bytes() { - return CompiledMapQueryContext.this.inputStore; - } - - @Override - public long offset() { - return CompiledMapQueryContext.this.firstInputValueOffset(); - } - - @Override - public long size() { - return CompiledMapQueryContext.this.firstInputValueSize(); - } - - public void closeInputFirstValueBytesDataSizeDependants() { - this.closeInputFirstValueBytesDataGetUsingDependants(); - } - - @Override - public V getUsing(V usingValue) { - CompiledMapQueryContext.this.inputBytes().position(CompiledMapQueryContext.this.firstInputValueOffset()); - return CompiledMapQueryContext.this.valueReader.read(CompiledMapQueryContext.this.inputBytes(), size(), usingValue); - } - - public void closeInputFirstValueBytesDataGetUsingDependants() { - this.closeCachedBytesInputFirstValue(); - } - - private V cachedBytesInputFirstValue; - - private boolean cachedBytesInputFirstValueRead = false; - - public boolean cachedBytesInputFirstValueInit() { - return (this.cachedBytesInputFirstValueRead) != false; - } - - private void initCachedBytesInputFirstValue() { - cachedBytesInputFirstValue = getUsing(cachedBytesInputFirstValue); - cachedBytesInputFirstValueRead = true; - } - - public V cachedBytesInputFirstValue() { - if (!(this.cachedBytesInputFirstValueInit())) - this.initCachedBytesInputFirstValue(); - - return this.cachedBytesInputFirstValue; - } - - public void closeCachedBytesInputFirstValue() { - if (!(this.cachedBytesInputFirstValueInit())) - return ; - - this.cachedBytesInputFirstValueRead = false; - } - - @Override - public V get() { - return cachedBytesInputFirstValue(); - } - } - - public class InputKeyBytesData extends AbstractData { - @Override - public RandomDataInput bytes() { - return CompiledMapQueryContext.this.inputStore; - } - - @Override - public long offset() { - return CompiledMapQueryContext.this.inputKeyOffset(); - } - - @Override - public long size() { - return CompiledMapQueryContext.this.inputKeySize(); - } - - public void closeInputKeyBytesDataSizeDependants() { - this.closeInputKeyBytesDataGetUsingDependants(); - } - - @Override - public K getUsing(K usingKey) { - Bytes inputBytes = CompiledMapQueryContext.this.inputBytes(); - inputBytes.position(CompiledMapQueryContext.this.inputKeyOffset()); - return CompiledMapQueryContext.this.keyReader.read(inputBytes, size(), usingKey); - } - - public void closeInputKeyBytesDataGetUsingDependants() { - this.closeCachedBytesInputKey(); - } - - private K cachedBytesInputKey; - - private boolean cachedBytesInputKeyRead = false; - - public boolean cachedBytesInputKeyInit() { - return (this.cachedBytesInputKeyRead) != false; - } - - private void initCachedBytesInputKey() { - cachedBytesInputKey = getUsing(cachedBytesInputKey); - cachedBytesInputKeyRead = true; - } - - public K cachedBytesInputKey() { - if (!(this.cachedBytesInputKeyInit())) - this.initCachedBytesInputKey(); - - return this.cachedBytesInputKey; - } - - public void closeCachedBytesInputKey() { - if (!(this.cachedBytesInputKeyInit())) - return ; - - this.cachedBytesInputKeyRead = false; - } - - @Override - public K get() { - return cachedBytesInputKey(); - } - } - - public class InputSecondValueBytesData extends AbstractData { - @Override - public RandomDataInput bytes() { - return CompiledMapQueryContext.this.inputStore; - } - - @Override - public long offset() { - return CompiledMapQueryContext.this.secondInputValueOffset(); - } - - @Override - public long size() { - return CompiledMapQueryContext.this.secondInputValueSize(); - } - - public void closeInputSecondValueBytesDataSizeDependants() { - this.closeInputSecondValueBytesDataGetUsingDependants(); - } - - @Override - public V getUsing(V usingValue) { - CompiledMapQueryContext.this.inputBytes().position(CompiledMapQueryContext.this.secondInputValueOffset()); - return CompiledMapQueryContext.this.valueReader.read(CompiledMapQueryContext.this.inputBytes(), size(), usingValue); - } - - public void closeInputSecondValueBytesDataGetUsingDependants() { - this.closeCachedBytesInputSecondValue(); - } - - private V cachedBytesInputSecondValue; - - private boolean cachedBytesInputSecondValueRead = false; - - public boolean cachedBytesInputSecondValueInit() { - return (this.cachedBytesInputSecondValueRead) != false; - } - - private void initCachedBytesInputSecondValue() { - cachedBytesInputSecondValue = getUsing(cachedBytesInputSecondValue); - cachedBytesInputSecondValueRead = true; - } - - public V cachedBytesInputSecondValue() { - if (!(this.cachedBytesInputSecondValueInit())) - this.initCachedBytesInputSecondValue(); - - return this.cachedBytesInputSecondValue; - } - - public void closeCachedBytesInputSecondValue() { - if (!(this.cachedBytesInputSecondValueInit())) - return ; - - this.cachedBytesInputSecondValueRead = false; - } - - @Override - public V get() { - return cachedBytesInputSecondValue(); - } - } - - public class ReadLock implements InterProcessLock { - @Override - public void lockInterruptibly() throws InterruptedException { - if ((CompiledMapQueryContext.this.localLockState()) == (LocalLockState.UNLOCKED)) { - CompiledMapQueryContext.this.segmentHeader().readLockInterruptibly(CompiledMapQueryContext.this.segmentHeaderAddress()); - CompiledMapQueryContext.this.setLocalLockStateGuarded(LocalLockState.READ_LOCKED); - } - } - - @Override - public void lock() { - if ((CompiledMapQueryContext.this.localLockState()) == (LocalLockState.UNLOCKED)) { - CompiledMapQueryContext.this.segmentHeader().readLock(CompiledMapQueryContext.this.segmentHeaderAddress()); - CompiledMapQueryContext.this.setLocalLockStateGuarded(LocalLockState.READ_LOCKED); - } - } - - public void closeReadLockLockDependants() { - CompiledMapQueryContext.this.closeHashLookupPos(); - } - - @Override - public boolean isHeldByCurrentThread() { - return CompiledMapQueryContext.this.localLockState().read; - } - - @Override - public void unlock() { - switch (CompiledMapQueryContext.this.localLockState()) { - case UNLOCKED : - return ; - case READ_LOCKED : - CompiledMapQueryContext.this.segmentHeader().readUnlock(CompiledMapQueryContext.this.segmentHeaderAddress()); - break; - case UPDATE_LOCKED : - CompiledMapQueryContext.this.segmentHeader().updateUnlock(CompiledMapQueryContext.this.segmentHeaderAddress()); - break; - case WRITE_LOCKED : - CompiledMapQueryContext.this.segmentHeader().writeUnlock(CompiledMapQueryContext.this.segmentHeaderAddress()); - } - CompiledMapQueryContext.this.setLocalLockStateGuarded(LocalLockState.UNLOCKED); - CompiledMapQueryContext.this.closeHashLookupPos(); - CompiledMapQueryContext.this.closePos(); - } - - @Override - public boolean tryLock(long time, @NotNull - TimeUnit unit) throws InterruptedException { - if ((CompiledMapQueryContext.this.localLockState()) == (LocalLockState.UNLOCKED)) { - if (CompiledMapQueryContext.this.segmentHeader().tryReadLock(CompiledMapQueryContext.this.segmentHeaderAddress(), time, unit)) { - CompiledMapQueryContext.this.setLocalLockStateGuarded(LocalLockState.READ_LOCKED); - return true; - } else { - return false; - } - } else { - return true; - } - } - - @Override - public boolean tryLock() { - if ((CompiledMapQueryContext.this.localLockState()) == (LocalLockState.UNLOCKED)) { - if (CompiledMapQueryContext.this.segmentHeader().tryReadLock(CompiledMapQueryContext.this.segmentHeaderAddress())) { - CompiledMapQueryContext.this.setLocalLockStateGuarded(LocalLockState.READ_LOCKED); - return true; - } else { - return false; - } - } else { - return true; - } - } - } - - public class UpdateLock implements InterProcessLock { - @NotNull - private IllegalMonitorStateException forbiddenUpgrade() { - return new IllegalMonitorStateException("Cannot upgrade from read to update lock"); - } - - @Override - public void lockInterruptibly() throws InterruptedException { - switch (CompiledMapQueryContext.this.localLockState()) { - case UNLOCKED : - CompiledMapQueryContext.this.segmentHeader().updateLockInterruptibly(CompiledMapQueryContext.this.segmentHeaderAddress()); - CompiledMapQueryContext.this.setLocalLockStateGuarded(LocalLockState.UPDATE_LOCKED); - return ; - case READ_LOCKED : - throw forbiddenUpgrade(); - case UPDATE_LOCKED : - case WRITE_LOCKED : - } - } - - @Override - public boolean isHeldByCurrentThread() { - return CompiledMapQueryContext.this.localLockState().update; - } - - @Override - public void unlock() { - switch (CompiledMapQueryContext.this.localLockState()) { - case UNLOCKED : - case READ_LOCKED : - return ; - case UPDATE_LOCKED : - CompiledMapQueryContext.this.segmentHeader().downgradeUpdateToReadLock(CompiledMapQueryContext.this.segmentHeaderAddress()); - break; - case WRITE_LOCKED : - CompiledMapQueryContext.this.segmentHeader().downgradeWriteToReadLock(CompiledMapQueryContext.this.segmentHeaderAddress()); - } - CompiledMapQueryContext.this.setLocalLockStateGuarded(LocalLockState.READ_LOCKED); - } - - @Override - public void lock() { - switch (CompiledMapQueryContext.this.localLockState()) { - case UNLOCKED : - CompiledMapQueryContext.this.segmentHeader().updateLock(CompiledMapQueryContext.this.segmentHeaderAddress()); - CompiledMapQueryContext.this.setLocalLockStateGuarded(LocalLockState.UPDATE_LOCKED); - return ; - case READ_LOCKED : - throw forbiddenUpgrade(); - case UPDATE_LOCKED : - case WRITE_LOCKED : - } - } - - @Override - public boolean tryLock(long time, @NotNull - TimeUnit unit) throws InterruptedException { - switch (CompiledMapQueryContext.this.localLockState()) { - case UNLOCKED : - if (CompiledMapQueryContext.this.segmentHeader().tryUpdateLock(CompiledMapQueryContext.this.segmentHeaderAddress(), time, unit)) { - CompiledMapQueryContext.this.setLocalLockStateGuarded(LocalLockState.UPDATE_LOCKED); - return true; - } else { - return false; - } - case READ_LOCKED : - throw forbiddenUpgrade(); - case UPDATE_LOCKED : - case WRITE_LOCKED : - return true; - } - throw new AssertionError(); - } - - @Override - public boolean tryLock() { - switch (CompiledMapQueryContext.this.localLockState()) { - case UNLOCKED : - if (CompiledMapQueryContext.this.segmentHeader().tryUpdateLock(CompiledMapQueryContext.this.segmentHeaderAddress())) { - CompiledMapQueryContext.this.setLocalLockStateGuarded(LocalLockState.UPDATE_LOCKED); - return true; - } else { - return false; - } - case READ_LOCKED : - throw forbiddenUpgrade(); - case UPDATE_LOCKED : - case WRITE_LOCKED : - return true; - } - throw new AssertionError(); - } - } - - public class WrappedValueInstanceData extends CopyingInstanceData { - public WrappedValueInstanceData getUnusedWrappedValueGuarded() { - assert this.nextInit() : "Next should be init"; - return getUnusedWrappedValue(); - } - - public WrappedValueInstanceData getUnusedWrappedValue() { - if (!(valueInit())) - return this; - - if ((next) == null) - next = new WrappedValueInstanceData(); - - return next.getUnusedWrappedValue(); - } - - private WrappedValueInstanceData next; - - boolean nextInit() { - return true; - } - - void closeNext() { - if (!(this.nextInit())) - return ; - - } - - private V value; - - public boolean valueInit() { - return (value) != null; - } - - public void initValue(V value) { - CompiledMapQueryContext.this.m().checkValue(value); - this.value = value; - this.closeValueDependants(); - } - - public V value() { - assert this.valueInit() : "Value should be init"; - return this.value; - } - - public void closeValue() { - if (!(this.valueInit())) - return ; - - this.closeValueDependants(); - value = null; - if ((next) != null) - next.closeValue(); - - } - - public void closeValueDependants() { - this.closeBuffer(); - } - - @Override - public V instance() { - return value(); - } - - private boolean marshalled = false; - - private DirectBytes buf; - - public boolean bufferInit() { - return (this.marshalled) != false; - } - - private void initBuffer() { - MVI mvi = CompiledMapQueryContext.this.valueMetaInterop(value()); - long size = mvi.size(CompiledMapQueryContext.this.valueInterop, value()); - buf = getBuffer(this.buf, size); - mvi.write(CompiledMapQueryContext.this.valueInterop, buf, value()); - buf.flip(); - marshalled = true; - } - - public DirectBytes buf() { - if (!(this.bufferInit())) - this.initBuffer(); - - return this.buf; - } - - public void closeBuffer() { - if (!(this.bufferInit())) - return ; - - this.marshalled = false; - } - - @Override - public V getUsing(V usingValue) { - buf().position(0); - return CompiledMapQueryContext.this.valueReader.read(buf(), buf().limit(), usingValue); - } - - @Override - public DirectBytes buffer() { - return buf(); - } - } - - public class WriteLock implements InterProcessLock { - @NotNull - private IllegalMonitorStateException forbiddenUpgrade() { - return new IllegalMonitorStateException("Cannot upgrade from read to write lock"); - } - - @Override - public boolean tryLock(long time, @NotNull - TimeUnit unit) throws InterruptedException { - switch (CompiledMapQueryContext.this.localLockState()) { - case UNLOCKED : - if (CompiledMapQueryContext.this.segmentHeader().tryWriteLock(CompiledMapQueryContext.this.segmentHeaderAddress(), time, unit)) { - CompiledMapQueryContext.this.setLocalLockStateGuarded(LocalLockState.WRITE_LOCKED); - return true; - } else { - return false; - } - case READ_LOCKED : - throw forbiddenUpgrade(); - case UPDATE_LOCKED : - if (CompiledMapQueryContext.this.segmentHeader().tryUpgradeUpdateToWriteLock(CompiledMapQueryContext.this.segmentHeaderAddress(), time, unit)) { - CompiledMapQueryContext.this.setLocalLockStateGuarded(LocalLockState.WRITE_LOCKED); - return true; - } else { - return false; - } - case WRITE_LOCKED : - return true; - } - throw new AssertionError(); - } - - @Override - public boolean tryLock() { - switch (CompiledMapQueryContext.this.localLockState()) { - case UNLOCKED : - if (CompiledMapQueryContext.this.segmentHeader().tryWriteLock(CompiledMapQueryContext.this.segmentHeaderAddress())) { - CompiledMapQueryContext.this.setLocalLockStateGuarded(LocalLockState.WRITE_LOCKED); - return true; - } else { - return false; - } - case READ_LOCKED : - throw forbiddenUpgrade(); - case UPDATE_LOCKED : - if (CompiledMapQueryContext.this.segmentHeader().tryUpgradeUpdateToWriteLock(CompiledMapQueryContext.this.segmentHeaderAddress())) { - CompiledMapQueryContext.this.setLocalLockStateGuarded(LocalLockState.WRITE_LOCKED); - return true; - } else { - return false; - } - case WRITE_LOCKED : - return true; - } - throw new AssertionError(); - } - - @Override - public void lockInterruptibly() throws InterruptedException { - switch (CompiledMapQueryContext.this.localLockState()) { - case UNLOCKED : - CompiledMapQueryContext.this.segmentHeader().writeLockInterruptibly(CompiledMapQueryContext.this.segmentHeaderAddress()); - CompiledMapQueryContext.this.setLocalLockStateGuarded(LocalLockState.WRITE_LOCKED); - return ; - case READ_LOCKED : - throw forbiddenUpgrade(); - case UPDATE_LOCKED : - CompiledMapQueryContext.this.segmentHeader().upgradeUpdateToWriteLockInterruptibly(CompiledMapQueryContext.this.segmentHeaderAddress()); - CompiledMapQueryContext.this.setLocalLockStateGuarded(LocalLockState.WRITE_LOCKED); - case WRITE_LOCKED : - } - } - - @Override - public void unlock() { - switch (CompiledMapQueryContext.this.localLockState()) { - case UNLOCKED : - case READ_LOCKED : - case UPDATE_LOCKED : - return ; - case WRITE_LOCKED : - CompiledMapQueryContext.this.segmentHeader().downgradeWriteToUpdateLock(CompiledMapQueryContext.this.segmentHeaderAddress()); - } - CompiledMapQueryContext.this.setLocalLockStateGuarded(LocalLockState.UPDATE_LOCKED); - } - - @Override - public boolean isHeldByCurrentThread() { - return CompiledMapQueryContext.this.localLockState().write; - } - - @Override - public void lock() { - switch (CompiledMapQueryContext.this.localLockState()) { - case UNLOCKED : - CompiledMapQueryContext.this.segmentHeader().writeLock(CompiledMapQueryContext.this.segmentHeaderAddress()); - CompiledMapQueryContext.this.setLocalLockStateGuarded(LocalLockState.WRITE_LOCKED); - return ; - case READ_LOCKED : - throw forbiddenUpgrade(); - case UPDATE_LOCKED : - CompiledMapQueryContext.this.segmentHeader().upgradeUpdateToWriteLock(CompiledMapQueryContext.this.segmentHeaderAddress()); - CompiledMapQueryContext.this.setLocalLockStateGuarded(LocalLockState.WRITE_LOCKED); - case WRITE_LOCKED : - } - } - } - - public enum SearchState { - PRESENT, DELETED, ABSENT; } - - private void _AllocatedChunks_incrementSegmentEntriesIfNeeded() { - } - - private void _CheckOnEachPublicOperation_checkOnEachPublicOperation() { - this.checkAccessingFromOwnerThread(); - } - - public void incrementModCount() { - contextModCount = rootContextOnThisSegment.latestSameThreadSegmentModCount = (rootContextOnThisSegment.latestSameThreadSegmentModCount) + 1; - } - - public void setHashLookupPos(long hashLookupPos) { - this.hashLookupPos = hashLookupPos; - } - - public void setLocalLockState(LocalLockState newState) { - localLockState = newState; - } - - public void setSearchState(CompiledMapQueryContext.SearchState newSearchState) { - this.searchState = newSearchState; - } - - final Thread owner; - - public Thread owner() { - return this.owner; - } - - private void closeNestedLocks() { - unlinkFromSegmentContextsChain(); - switch (localLockState) { - case UNLOCKED : - break; - case READ_LOCKED : - int newTotalReadLockCount = this.rootContextOnThisSegment.totalReadLockCount -= 1; - if (newTotalReadLockCount == 0) { - if (((this.rootContextOnThisSegment.totalUpdateLockCount) == 0) && ((this.rootContextOnThisSegment.totalWriteLockCount) == 0)) { - segmentHeader().readUnlock(segmentHeaderAddress()); - } - } else if (newTotalReadLockCount < 0) { - throw new IllegalStateException("read underflow"); - } - break; - case UPDATE_LOCKED : - int newTotalUpdateLockCount = this.rootContextOnThisSegment.totalUpdateLockCount -= 1; - if (newTotalUpdateLockCount == 0) { - if ((this.rootContextOnThisSegment.totalWriteLockCount) == 0) { - if ((this.rootContextOnThisSegment.totalReadLockCount) == 0) { - segmentHeader().updateUnlock(segmentHeaderAddress()); - } else { - segmentHeader().downgradeUpdateToReadLock(segmentHeaderAddress()); - } - } - } else if (newTotalUpdateLockCount < 0) { - throw new IllegalStateException("update underflow"); - } - break; - case WRITE_LOCKED : - int newTotalWriteLockCount = this.rootContextOnThisSegment.totalWriteLockCount -= 1; - if (newTotalWriteLockCount == 0) { - if ((this.rootContextOnThisSegment.totalUpdateLockCount) > 0) { - segmentHeader().downgradeWriteToUpdateLock(segmentHeaderAddress()); - } else { - if ((this.rootContextOnThisSegment.totalReadLockCount) > 0) { - segmentHeader().downgradeWriteToReadLock(segmentHeaderAddress()); - } else { - segmentHeader().writeUnlock(segmentHeaderAddress()); - } - } - } - break; - } - } - - private void closeRootLocks() { - assert (nextNode) == null; - switch (localLockState) { - case UNLOCKED : - return ; - case READ_LOCKED : - segmentHeader().readUnlock(segmentHeaderAddress()); - return ; - case UPDATE_LOCKED : - segmentHeader().updateUnlock(segmentHeaderAddress()); - return ; - case WRITE_LOCKED : - segmentHeader().writeUnlock(segmentHeaderAddress()); - } - } - - private void innerInitSegmentHashLookup(long address, long capacity, int entrySize, int keyBits, int valueBits) { - this.address = address; - this.capacityMask = capacity - 1L; - this.hashLookupEntrySize = entrySize; - this.capacityMask2 = (capacityMask) * entrySize; - this.keyBits = keyBits; - this.keyMask = CompiledMapQueryContext.mask(keyBits); - this.valueMask = CompiledMapQueryContext.mask(valueBits); - this.entryMask = CompiledMapQueryContext.mask((keyBits + valueBits)); - } - - private void unlinkFromSegmentContextsChain() { - CompiledMapQueryContext prevContext = this.rootContextOnThisSegment; - while (true) { - assert (prevContext.nextNode) != null; - if ((prevContext.nextNode) == (this)) - break; - - prevContext = prevContext.nextNode; - } - assert (nextNode) == null; - prevContext.nextNode = null; - } - - private long _HashEntryStages_entryEnd() { - return keyEnd(); - } - - private CompiledMapQueryContext _Chaining_createChaining() { - return new CompiledMapQueryContext(this); - } - - public final int indexInContextChain; - - public int indexInContextChain() { - return this.indexInContextChain; - } - - public class DefaultReturnValue implements InstanceReturnValue { - @Override - public void returnValue(@NotNull - Data value) { - initDefaultReturnedValue(value); - } - - private V defaultReturnedValue = null; - - boolean defaultReturnedValueInit() { - return (this.defaultReturnedValue) != null; - } - - private void initDefaultReturnedValue(@NotNull - Data value) { - defaultReturnedValue = value.getUsing(null); - } - - public V defaultReturnedValue() { - assert this.defaultReturnedValueInit() : "DefaultReturnedValue should be init"; - return this.defaultReturnedValue; - } - - public void closeDefaultReturnedValue() { - if (!(this.defaultReturnedValueInit())) - return ; - - this.defaultReturnedValue = null; - } - - @Override - public V returnValue() { - if (defaultReturnedValueInit()) { - return defaultReturnedValue(); - } else { - return null; - } - } - } - - public class InputKeyInstanceData extends CopyingInstanceData implements KeyInitableData { - private K key = null; - - public boolean keyInit() { - return (this.key) != null; - } - - @Override - public void initKey(K key) { - this.key = key; - this.closeKeyDependants(); - } - - public K key() { - assert this.keyInit() : "Key should be init"; - return this.key; - } - - public void closeKey() { - if (!(this.keyInit())) - return ; - - this.closeKeyDependants(); - this.key = null; - } - - public void closeKeyDependants() { - this.closeBuffer(); - } - - @Override - public K instance() { - return key(); - } - - private boolean marshalled = false; - - private DirectBytes buffer; - - public boolean bufferInit() { - return (this.marshalled) != false; - } - - private void initBuffer() { - MKI mki = CompiledMapQueryContext.this.keyMetaInterop(key()); - long size = mki.size(CompiledMapQueryContext.this.keyInterop, key()); - buffer = getBuffer(this.buffer, size); - mki.write(CompiledMapQueryContext.this.keyInterop, buffer, key()); - buffer.flip(); - marshalled = true; - } - - public DirectBytes buffer() { - if (!(this.bufferInit())) - this.initBuffer(); - - return this.buffer; - } - - public void closeBuffer() { - if (!(this.bufferInit())) - return ; - - this.marshalled = false; - } - - @Override - public K getUsing(K usingKey) { - buffer().position(0); - return CompiledMapQueryContext.this.keyReader.read(buffer(), buffer().limit(), usingKey); - } - } - - public class InputValueInstanceData extends CopyingInstanceData implements ValueInitableData { - private V value = null; - - public boolean valueInit() { - return (this.value) != null; - } - - @Override - public void initValue(V value) { - this.value = value; - this.closeValueDependants(); - } - - public V value() { - assert this.valueInit() : "Value should be init"; - return this.value; - } - - public void closeValue() { - if (!(this.valueInit())) - return ; - - this.closeValueDependants(); - this.value = null; - } - - public void closeValueDependants() { - this.closeBuffer(); - } - - @Override - public V instance() { - return value(); - } - - private boolean marshalled = false; - - private DirectBytes buffer; - - public boolean bufferInit() { - return (this.marshalled) != false; - } - - private void initBuffer() { - MVI mvi = CompiledMapQueryContext.this.valueMetaInterop(value()); - long size = mvi.size(CompiledMapQueryContext.this.valueInterop, value()); - buffer = getBuffer(this.buffer, size); - mvi.write(CompiledMapQueryContext.this.valueInterop, buffer, value()); - buffer.flip(); - marshalled = true; - } - - public DirectBytes buffer() { - if (!(this.bufferInit())) - this.initBuffer(); - - return this.buffer; - } - - public void closeBuffer() { - if (!(this.bufferInit())) - return ; - - this.marshalled = false; - } - - @Override - public V getUsing(V usingValue) { - buffer().position(0); - return CompiledMapQueryContext.this.valueReader.read(buffer(), buffer().limit(), usingValue); - } - } - - public class UsingReturnValue implements UsableReturnValue { - @Override - public void returnValue(@NotNull - Data value) { - initReturnedValue(value); - } - - private V usingReturnValue = ((V)(UsableReturnValue.USING_RETURN_VALUE_UNINT)); - - public boolean usingReturnValueInit() { - return (this.usingReturnValue) != ((V)(UsableReturnValue.USING_RETURN_VALUE_UNINT)); - } - - @Override - public void initUsingReturnValue(V usingReturnValue) { - this.usingReturnValue = usingReturnValue; - this.closeUsingReturnValueDependants(); - } - - public V usingReturnValue() { - assert this.usingReturnValueInit() : "UsingReturnValue should be init"; - return this.usingReturnValue; - } - - public void closeUsingReturnValue() { - if (!(this.usingReturnValueInit())) - return ; - - this.closeUsingReturnValueDependants(); - this.usingReturnValue = ((V)(UsableReturnValue.USING_RETURN_VALUE_UNINT)); - } - - public void closeUsingReturnValueDependants() { - this.closeReturnedValue(); - } - - private V returnedValue = null; - - boolean returnedValueInit() { - return (this.returnedValue) != null; - } - - private void initReturnedValue(@NotNull - Data value) { - returnedValue = value.getUsing(usingReturnValue()); - } - - public V returnedValue() { - assert this.returnedValueInit() : "ReturnedValue should be init"; - return this.returnedValue; - } - - public void closeReturnedValue() { - if (!(this.returnedValueInit())) - return ; - - this.returnedValue = null; - } - - @Override - public V returnValue() { - if (returnedValueInit()) { - return returnedValue(); - } else { - return null; - } - } - } - - public static int entrySize(int keyBits, int valueBits) { - return ((int)(MemoryUnit.BYTES.alignAndConvert(((long)(keyBits + valueBits)), MemoryUnit.BITS))); - } - - public static int keyBits(long entriesPerSegment, int valueBits) { - int minKeyBits = 64 - (Long.numberOfLeadingZeros((entriesPerSegment - 1L))); - minKeyBits += 3; - int actualEntryBits = ((int)(MemoryUnit.BYTES.align(((long)(minKeyBits + valueBits)), MemoryUnit.BITS))); - return actualEntryBits - valueBits; - } - - public static int valueBits(long actualChunksPerSegment) { - return 64 - (Long.numberOfLeadingZeros((actualChunksPerSegment - 1L))); - } - - public final Bytes entryBytes; - - public Bytes entryBytes() { - return this.entryBytes; - } - - public static long capacityFor(long entriesPerSegment) { - if (entriesPerSegment < 0L) - throw new IllegalArgumentException("entriesPerSegment should be positive"); - - long capacity = Maths.nextPower2(entriesPerSegment, 64L); - if ((((double)(entriesPerSegment)) / ((double)(capacity))) > (2.0 / 3.0)) { - capacity <<= 1L; - } - return capacity; - } - - public static long mask(int bits) { - return (1L << bits) - 1L; - } - - public static final int MAX_SEGMENT_CHUNKS = 1 << 30; - - public static final int MAX_SEGMENT_ENTRIES = 1 << 29; - - public int MAX_SEGMENT_ENTRIES() { - return this.MAX_SEGMENT_ENTRIES; - } - - public int MAX_SEGMENT_CHUNKS() { - return this.MAX_SEGMENT_CHUNKS; - } - - public static final long UNSET_KEY = 0L; - - public static final long UNSET_ENTRY = 0L; - - public long UNSET_ENTRY() { - return this.UNSET_ENTRY; - } - - public long UNSET_KEY() { - return this.UNSET_KEY; - } - - public final ReadLock innerReadLock; - - public ReadLock innerReadLock() { - return this.innerReadLock; - } - - public final WriteLock innerWriteLock; - - public WriteLock innerWriteLock() { - return this.innerWriteLock; - } - - public final List contextChain; - - public final UpdateLock innerUpdateLock; - - public UpdateLock innerUpdateLock() { - return this.innerUpdateLock; - } - - public List contextChain() { - return this.contextChain; - } - - public final ThreadLocalCopies copies; - - final EntryKeyBytesData entryKey; - - public EntryKeyBytesData entryKey() { - return this.entryKey; - } - - public ThreadLocalCopies copies() { - return this.copies; - } - - private void countValueOffset() { - this.m().alignment.alignPositionAddr(entryBytes); - valueOffset = entryBytes.position(); - } - - public final UsingReturnValue usingReturnValue; - - public UsingReturnValue usingReturnValue() { - return this.usingReturnValue; - } - - public final InputKeyBytesData inputKeyBytesValue; - - public InputKeyBytesData inputKeyBytesValue() { - return this.inputKeyBytesValue; - } - - public final DefaultReturnValue defaultReturnValue; - - public DefaultReturnValue defaultReturnValue() { - return this.defaultReturnValue; - } - - public final EntryValueBytesData entryValue; - - public EntryValueBytesData entryValue() { - return this.entryValue; - } - - final WrappedValueInstanceData wrappedValueInstanceValue; - - public WrappedValueInstanceData wrappedValueInstanceValue() { - return this.wrappedValueInstanceValue; - } - - public final InputFirstValueBytesData inputFirstValueBytesValue; - - public final JavaLangBytesReusableBytesStore inputStore; - - public JavaLangBytesReusableBytesStore inputStore() { - return this.inputStore; - } - - public InputFirstValueBytesData inputFirstValueBytesValue() { - return this.inputFirstValueBytesValue; - } - - public final InputSecondValueBytesData inputSecondValueBytesValue; - - public InputSecondValueBytesData inputSecondValueBytesValue() { - return this.inputSecondValueBytesValue; - } - - public final InputKeyInstanceData inputKeyInstanceValue; - - public InputKeyInstanceData inputKeyInstanceValue() { - return this.inputKeyInstanceValue; - } - - public final InputValueInstanceData inputValueInstanceValue; - - public InputValueInstanceData inputValueInstanceValue() { - return this.inputValueInstanceValue; - } - - public final DeprecatedMapKeyContextOnQuery deprecatedMapKeyContext; - - public DeprecatedMapKeyContextOnQuery deprecatedMapKeyContext() { - return this.deprecatedMapKeyContext; - } - - public final DeprecatedMapAcquireContextOnQuery deprecatedMapAcquireContext; - - public DeprecatedMapAcquireContextOnQuery deprecatedMapAcquireContext() { - return this.deprecatedMapAcquireContext; - } - - private final VanillaChronicleMap m; - - public final VI valueInterop; - - public VI valueInterop() { - return this.valueInterop; - } - - public final BytesStore entryBS; - - public BytesStore entryBS() { - return this.entryBS; - } - - public final BytesReader valueReader; - - public BytesReader valueReader() { - return this.valueReader; - } - - public final KI keyInterop; - - public KI keyInterop() { - return this.keyInterop; - } - - public final BytesReader keyReader; - - public BytesReader keyReader() { - return this.keyReader; - } - - @Override - public MapAbsentEntry absent() { - return this; - } - - @Override - public VanillaChronicleMap m() { - return m; - } - - @Override - public ChronicleMap map() { - return m(); - } - - long sizeOfEverythingBeforeValue(long keySize, long valueSize) { - return (((this.m().metaDataBytes) + (this.m().keySizeMarshaller.sizeEncodingSize(keySize))) + keySize) + (this.m().valueSizeMarshaller.sizeEncodingSize(valueSize)); - } - - public MVI valueMetaInterop(V value) { - return this.m().metaValueInteropProvider.get(this.copies, this.m().originalMetaValueInterop, valueInterop, value); - } - - public void closeValueBytesInteropValueMetaInteropDependants() { - this.wrappedValueInstanceValue.closeBuffer(); - this.inputValueInstanceValue.closeBuffer(); - } - - public long innerEntrySize(long sizeOfEverythingBeforeValue, long valueSize) { - if (this.m().constantlySizedEntry) { - return this.m().alignment.alignAddr((sizeOfEverythingBeforeValue + valueSize)); - } else if (this.m().couldNotDetermineAlignmentBeforeAllocation) { - return (sizeOfEverythingBeforeValue + (this.m().worstAlignment)) + valueSize; - } else { - return (this.m().alignment.alignAddr(sizeOfEverythingBeforeValue)) + valueSize; - } - } - - public final long entrySize(long keySize, long valueSize) { - long sizeOfEverythingBeforeValue = sizeOfEverythingBeforeValue(keySize, valueSize); - return innerEntrySize(sizeOfEverythingBeforeValue, valueSize); - } - - public void checkAccessingFromOwnerThread() { - if ((owner) != (Thread.currentThread())) { - throw new ConcurrentModificationException("Context shouldn\'t be accessed from multiple threads"); - } - } - - public void closeOwnerThreadHolderCheckAccessingFromOwnerThreadDependants() { - this.closeQueryCheckOnEachPublicOperationCheckOnEachPublicOperationDependants(); - } - - public CompiledMapQueryContext createChaining() { - return new CompiledMapQueryContext(this); - } - - public T getContext() { - for (CompiledMapQueryContext context : contextChain) { - if (!(context.usedInit())) { - return ((T)(context)); - } - } - int maxNestedContexts = 1 << 16; - if ((contextChain.size()) > maxNestedContexts) { - throw new IllegalStateException((((((("More than " + maxNestedContexts) + " nested ChronicleHash contexts are not supported. Very probable that ") + "you simply forgot to close context somewhere (recommended to use ") + "try-with-resources statement). ") + "Otherwise this is a bug, please report with this ") + "stack trace on https://github.com/OpenHFT/Chronicle-Map/issues")); - } - return ((T)(createChaining())); - } - - public T contextAtIndexInChain(int index) { - return ((T)(contextChain.get(index))); - } - - public void closeVanillaChronicleMapHolderImplContextAtIndexInChainDependants() { - this.closeQuerySegmentStagesTryFindInitLocksOfThisSegmentDependants(); - } - - public MKI keyMetaInterop(K key) { - return this.h().metaKeyInteropProvider.get(this.copies, this.h().originalMetaKeyInterop, keyInterop, key); - } - - public void closeKeyBytesInteropKeyMetaInteropDependants() { - this.inputKeyInstanceValue.closeBuffer(); - } - - public long keyOffset = -1; - - public boolean keyOffsetInit() { - return (this.keyOffset) >= 0; - } - - public void initKeyOffset(long keyOffset) { - this.keyOffset = keyOffset; - this.closeKeyOffsetDependants(); - } - - public long keyOffset() { - assert this.keyOffsetInit() : "KeyOffset should be init"; - return this.keyOffset; - } - - public void closeKeyOffset() { - if (!(this.keyOffsetInit())) - return ; - - this.closeKeyOffsetDependants(); - this.keyOffset = -1; - } - - public void closeKeyOffsetDependants() { - this.closeMapEntryStagesKeyEndDependants(); - this.closeMapQueryKeyEqualsDependants(); - this.entryKey.closeEntryKeyBytesDataInnerGetUsingDependants(); - } - - public int allocatedChunks = 0; - - public boolean allocatedChunksInit() { - return (this.allocatedChunks) != 0; - } - - public void initAllocatedChunks(int allocatedChunks) { - this.allocatedChunks = allocatedChunks; - } - - public int allocatedChunks() { - assert this.allocatedChunksInit() : "AllocatedChunks should be init"; - return this.allocatedChunks; - } - - public void closeAllocatedChunks() { - if (!(this.allocatedChunksInit())) - return ; - - this.allocatedChunks = 0; - } - - public Data inputKey = null; - - public boolean inputKeyInit() { - return (this.inputKey) != null; - } - - public void initInputKey(Data inputKey) { - this.inputKey = inputKey; - this.closeInputKeyDependants(); - } - - public Data inputKey() { - assert this.inputKeyInit() : "InputKey should be init"; - return this.inputKey; - } - - public void closeInputKey() { - if (!(this.inputKeyInit())) - return ; - - this.closeInputKeyDependants(); - this.inputKey = null; - } - - public void closeInputKeyDependants() { - this.closeHashOfKey(); - this.closeMapQueryKeyEqualsDependants(); - } - - public long hashOfKey = 0; - - public boolean hashOfKeyInit() { - return (this.hashOfKey) != 0; - } - - void initHashOfKey() { - hashOfKey = inputKey().hash(net.openhft.chronicle.algo.hashing.LongHashFunction.city_1_1()); - this.closeHashOfKeyDependants(); - } - - public long hashOfKey() { - if (!(this.hashOfKeyInit())) - this.initHashOfKey(); - - return this.hashOfKey; - } - - public void closeHashOfKey() { - if (!(this.hashOfKeyInit())) - return ; - - this.closeHashOfKeyDependants(); - this.hashOfKey = 0; - } - - public void closeHashOfKeyDependants() { - this.closeTheSegmentIndex(); - this.closeSearchKey(); - } - - public int segmentIndex = -1; - - public boolean theSegmentIndexInit() { - return (this.segmentIndex) >= 0; - } - - void initTheSegmentIndex() { - segmentIndex = this.h().hashSplitting.segmentIndex(this.hashOfKey()); - this.closeTheSegmentIndexDependants(); - } - - public void initTheSegmentIndex(int segmentIndex) { - this.segmentIndex = segmentIndex; - this.closeTheSegmentIndexDependants(); - } - - public int segmentIndex() { - if (!(this.theSegmentIndexInit())) - this.initTheSegmentIndex(); - - return this.segmentIndex; - } - - public void closeTheSegmentIndex() { - if (!(this.theSegmentIndexInit())) - return ; - - this.closeTheSegmentIndexDependants(); - this.segmentIndex = -1; - } - - public void closeTheSegmentIndexDependants() { - this.closeSegment(); - this.closeSegmentHashLookup(); - this.closeSegHeader(); - } - - long entrySpaceOffset = 0; - - MultiStoreBytes freeListBytes = new MultiStoreBytes(); - - public SingleThreadedDirectBitSet freeList = new SingleThreadedDirectBitSet(); - - boolean segmentInit() { - return (entrySpaceOffset) > 0; - } - - void initSegment() { - VanillaChronicleHash h = this.h(); - long hashLookupOffset = h.segmentOffset(segmentIndex()); - long freeListOffset = hashLookupOffset + (h.segmentHashLookupOuterSize); - freeListBytes.storePositionAndSize(h.ms, freeListOffset, h.segmentFreeListInnerSize); - freeList.reuse(freeListBytes); - entrySpaceOffset = (freeListOffset + (h.segmentFreeListOuterSize)) + (h.segmentEntrySpaceInnerOffset); - this.closeSegmentDependants(); - } - - public long entrySpaceOffset() { - if (!(this.segmentInit())) - this.initSegment(); - - return this.entrySpaceOffset; - } - - public SingleThreadedDirectBitSet freeList() { - if (!(this.segmentInit())) - this.initSegment(); - - return this.freeList; - } - - void closeSegment() { - if (!(this.segmentInit())) - return ; - - this.closeSegmentDependants(); - entrySpaceOffset = 0; - } - - public void closeSegmentDependants() { - this.closeEntryOffset(); - } - - int hashLookupEntrySize; - - int keyBits; - - long address = -1; - - long capacityMask; - - long capacityMask2; - - long keyMask; - - long valueMask; - - long entryMask; - - public boolean segmentHashLookupInit() { - return (this.address) >= 0; - } - - public void initSegmentHashLookup() { - long hashLookupOffset = this.h().segmentOffset(this.segmentIndex()); - innerInitSegmentHashLookup(((this.h().ms.address()) + hashLookupOffset), this.h().segmentHashLookupCapacity, this.h().segmentHashLookupEntrySize, this.h().segmentHashLookupKeyBits, this.h().segmentHashLookupValueBits); - this.closeSegmentHashLookupDependants(); - } - - public void initSegmentHashLookup(long address, long capacity, int entrySize, int keyBits, int valueBits) { - innerInitSegmentHashLookup(address, capacity, entrySize, keyBits, valueBits); - this.closeSegmentHashLookupDependants(); - } - - public int hashLookupEntrySize() { - if (!(this.segmentHashLookupInit())) - this.initSegmentHashLookup(); - - return this.hashLookupEntrySize; - } - - public int keyBits() { - if (!(this.segmentHashLookupInit())) - this.initSegmentHashLookup(); - - return this.keyBits; - } - - public long address() { - if (!(this.segmentHashLookupInit())) - this.initSegmentHashLookup(); - - return this.address; - } - - public long capacityMask() { - if (!(this.segmentHashLookupInit())) - this.initSegmentHashLookup(); - - return this.capacityMask; - } - - public long capacityMask2() { - if (!(this.segmentHashLookupInit())) - this.initSegmentHashLookup(); - - return this.capacityMask2; - } - - public long entryMask() { - if (!(this.segmentHashLookupInit())) - this.initSegmentHashLookup(); - - return this.entryMask; - } - - public long keyMask() { - if (!(this.segmentHashLookupInit())) - this.initSegmentHashLookup(); - - return this.keyMask; - } - - public long valueMask() { - if (!(this.segmentHashLookupInit())) - this.initSegmentHashLookup(); - - return this.valueMask; - } - - public void closeSegmentHashLookup() { - if (!(this.segmentHashLookupInit())) - return ; - - this.closeSegmentHashLookupDependants(); - this.address = -1; - } - - public void closeSegmentHashLookupDependants() { - this.closeHashLookupReadEntryDependants(); - this.closeHashLookupStepDependants(); - this.closeHashLookupStepBackDependants(); - this.closeHashLookupIndexToPosDependants(); - this.closeHashLookupMaskUnsetKeyDependants(); - this.closeHashLookupKeyDependants(); - this.closeHashLookupValueDependants(); - this.closeHashLookupHlPosDependants(); - this.closeHashLookupEmptyDependants(); - } - - public long readEntry(long pos) { - return NativeBytes.UNSAFE.getLong(((address()) + pos)); - } - - public void closeHashLookupReadEntryDependants() { - this.closeHashLookupSearchNextPosDependants(); - this.closeHashLookupSearchCheckSlotContainsExpectedKeyAndValueDependants(); - } - - public long step(long pos) { - return (pos += hashLookupEntrySize()) <= (capacityMask2()) ? pos : 0L; - } - - public void closeHashLookupStepDependants() { - this.closeHashLookupSearchNextPosDependants(); - } - - public long stepBack(long pos) { - return (pos -= hashLookupEntrySize()) >= 0 ? pos : capacityMask2(); - } - - public void closeHashLookupStepBackDependants() { - this.closeHashLookupSearchFoundDependants(); - } - - long indexToPos(long index) { - return index * (hashLookupEntrySize()); - } - - public void closeHashLookupIndexToPosDependants() { - this.closeHashLookupHlPosDependants(); - } - - public long maskUnsetKey(long key) { - return (key &= keyMask()) != (UNSET_KEY) ? key : keyMask(); - } - - public void closeHashLookupMaskUnsetKeyDependants() { - this.closeSearchKey(); - } - - long entry(long key, long value) { - return key | (value << (keyBits())); - } - - public void writeEntryVolatile(long pos, long prevEntry, long key, long value) { - long entry = (prevEntry & (~(entryMask()))) | (entry(key, value)); - NativeBytes.UNSAFE.putLongVolatile(null, ((address()) + pos), entry); - } - - public void clearHashLookup() { - NativeBytes.UNSAFE.setMemory(address(), ((capacityMask2()) + (hashLookupEntrySize())), ((byte)(0))); - } - - public long key(long entry) { - return entry & (keyMask()); - } - - public void closeHashLookupKeyDependants() { - this.closeHashLookupSearchNextPosDependants(); - this.closeHashLookupSearchCheckSlotContainsExpectedKeyAndValueDependants(); - } - - public void writeEntry(long pos, long prevEntry, long key, long value) { - long entry = (prevEntry & (~(entryMask()))) | (entry(key, value)); - NativeBytes.UNSAFE.putLong(((address()) + pos), entry); - } - - void writeEntry(long pos, long prevEntry, long anotherEntry) { - long entry = (prevEntry & (~(entryMask()))) | (anotherEntry & (entryMask())); - NativeBytes.UNSAFE.putLong(((address()) + pos), entry); - } - - public long value(long entry) { - return (entry >>> (keyBits())) & (valueMask()); - } - - public void closeHashLookupValueDependants() { - this.closeHashLookupSearchNextPosDependants(); - this.closeHashLookupSearchCheckSlotContainsExpectedKeyAndValueDependants(); - } - - public long hlPos(long key) { - return indexToPos((key & (capacityMask()))); - } - - public void closeHashLookupHlPosDependants() { - this.closeSearchKey(); - } - - public void checkValueForPut(long value) { - assert (value & (~(valueMask()))) == 0L : "Value out of range, was " + value; - } - - public void putValueVolatile(long pos, long value) { - checkValueForPut(value); - long currentEntry = readEntry(pos); - writeEntryVolatile(pos, currentEntry, key(currentEntry), value); - } - - void clearEntry(long pos, long prevEntry) { - long entry = prevEntry & (~(entryMask())); - NativeBytes.UNSAFE.putLong(((address()) + pos), entry); - } - - public boolean empty(long entry) { - return (entry & (entryMask())) == (UNSET_ENTRY); - } - - public void closeHashLookupEmptyDependants() { - this.closeHashLookupSearchNextPosDependants(); - } - - public long remove(long posToRemove) { - long entryToRemove = readEntry(posToRemove); - long posToShift = posToRemove; - while (true) { - posToShift = step(posToShift); - long entryToShift = readEntry(posToShift); - if (empty(entryToShift)) - break; - - long insertPos = hlPos(key(entryToShift)); - boolean cond1 = insertPos <= posToRemove; - boolean cond2 = posToRemove <= posToShift; - if ((cond1 && cond2) || ((posToShift < insertPos) && (cond1 || cond2))) { - writeEntry(posToRemove, entryToRemove, entryToShift); - posToRemove = posToShift; - entryToRemove = entryToShift; - } - } - clearEntry(posToRemove, entryToRemove); - return posToRemove; - } - - void forEach(EntryConsumer action) { - for (long pos = 0L ; pos <= (capacityMask2()) ; pos += hashLookupEntrySize()) { - long entry = readEntry(pos); - if (!(empty(entry))) - action.accept(key(entry), value(entry)); - - } - } - - String hashLookupToString() { - final StringBuilder sb = new StringBuilder("{"); - forEach((long key,long value) -> sb.append(key).append('=').append(value).append(',')); - sb.append('}'); - return sb.toString(); - } - - long segmentHeaderAddress; - - SegmentHeader segmentHeader = null; - - public boolean segHeaderInit() { - return (this.segmentHeader) != null; - } - - private void initSegHeader() { - segmentHeaderAddress = (this.h().ms.address()) + (this.h().segmentHeaderOffset(segmentIndex())); - segmentHeader = BigSegmentHeader.INSTANCE; - this.closeSegHeaderDependants(); - } - - public long segmentHeaderAddress() { - if (!(this.segHeaderInit())) - this.initSegHeader(); - - return this.segmentHeaderAddress; - } - - public SegmentHeader segmentHeader() { - if (!(this.segHeaderInit())) - this.initSegHeader(); - - return this.segmentHeader; - } - - public void closeSegHeader() { - if (!(this.segHeaderInit())) - return ; - - this.closeSegHeaderDependants(); - this.segmentHeader = null; - } - - public void closeSegHeaderDependants() { - this.closeQuerySegmentStagesTryFindInitLocksOfThisSegmentDependants(); - this.closeLocks(); - this.innerReadLock.closeReadLockLockDependants(); - } - - public void nextPosToSearchFrom(long nextPosToSearchFrom) { - segmentHeader().nextPosToSearchFrom(segmentHeaderAddress(), nextPosToSearchFrom); - } - - public void updateNextPosToSearchFrom(long allocated, int chunks) { - long nextPosToSearchFrom = allocated + chunks; - if (nextPosToSearchFrom >= (this.h().actualChunksPerSegment)) - nextPosToSearchFrom = 0L; - - nextPosToSearchFrom(nextPosToSearchFrom); - } - - long nextPosToSearchFrom() { - return segmentHeader().nextPosToSearchFrom(segmentHeaderAddress()); - } - - public long alloc(int chunks) { - VanillaChronicleHash h = this.h(); - if (chunks > (h.maxChunksPerEntry)) - throw new IllegalArgumentException((((("Entry is too large: requires " + chunks) + " entry size chucks, ") + (h.maxChunksPerEntry)) + " is maximum.")); - - long ret = freeList().setNextNContinuousClearBits(nextPosToSearchFrom(), chunks); - if ((ret == (DirectBitSet.NOT_FOUND)) || ((ret + chunks) > (h.actualChunksPerSegment))) { - if (((ret != (DirectBitSet.NOT_FOUND)) && ((ret + chunks) > (h.actualChunksPerSegment))) && (ret < (h.actualChunksPerSegment))) - freeList().clear(ret, h.actualChunksPerSegment); - - ret = freeList().setNextNContinuousClearBits(0L, chunks); - if ((ret == (DirectBitSet.NOT_FOUND)) || ((ret + chunks) > (h.actualChunksPerSegment))) { - if (((ret != (DirectBitSet.NOT_FOUND)) && ((ret + chunks) > (h.actualChunksPerSegment))) && (ret < (h.actualChunksPerSegment))) - freeList().clear(ret, h.actualChunksPerSegment); - - if (chunks == 1) { - throw new IllegalStateException("Segment is full, no free entries found"); - } else { - throw new IllegalStateException((("Segment is full or has no ranges of " + chunks) + " continuous free chunks")); - } - } - updateNextPosToSearchFrom(ret, chunks); - } else { - if ((chunks == 1) || (freeList().isSet(nextPosToSearchFrom()))) { - updateNextPosToSearchFrom(ret, chunks); - } - } - return ret; - } - - public void free(long fromPos, int chunks) { - freeList().clear(fromPos, (fromPos + chunks)); - if (fromPos < (nextPosToSearchFrom())) - nextPosToSearchFrom(fromPos); - - } - - boolean tryFindInitLocksOfThisSegment(Object thisContext, int index) { - CompiledMapQueryContext c = this.contextAtIndexInChain(index); - if ((((c.segmentHeader()) != null) && ((c.segmentHeaderAddress()) == (segmentHeaderAddress()))) && ((c.rootContextOnThisSegment()) != null)) { - throw new IllegalStateException("Nested context not implemented yet"); - } else { - return false; - } - } - - public void closeQuerySegmentStagesTryFindInitLocksOfThisSegmentDependants() { - this.closeLocks(); - } - - public void entries(long size) { - segmentHeader().size(segmentHeaderAddress(), size); - } - - public long entries() { - return segmentHeader().size(segmentHeaderAddress()); - } - - public void deleted(long deleted) { - segmentHeader().deleted(segmentHeaderAddress(), deleted); - } - - public long deleted() { - return segmentHeader().deleted(segmentHeaderAddress()); - } - - public long size() { - return (entries()) - (deleted()); - } - - int totalReadLockCount; - - int totalUpdateLockCount; - - int totalWriteLockCount; - - public int latestSameThreadSegmentModCount; - - public int contextModCount; - - CompiledMapQueryContext nextNode; - - public boolean concurrentSameThreadContexts; - - LocalLockState localLockState; - - public CompiledMapQueryContext rootContextOnThisSegment = null; - - public boolean locksInit() { - return (this.rootContextOnThisSegment) != null; - } - - void initLocks() { - localLockState = LocalLockState.UNLOCKED; - int indexOfThisContext = this.indexInContextChain; - for (int i = indexOfThisContext - 1 ; i >= 0 ; i--) { - if (tryFindInitLocksOfThisSegment(this, i)) - return ; - - } - for (int i = indexOfThisContext + 1, size = this.contextChain.size() ; i < size ; i++) { - if (tryFindInitLocksOfThisSegment(this, i)) - return ; - - } - rootContextOnThisSegment = this; - concurrentSameThreadContexts = false; - latestSameThreadSegmentModCount = 0; - contextModCount = 0; - nextNode = null; - totalReadLockCount = 0; - totalUpdateLockCount = 0; - totalWriteLockCount = 0; - this.closeLocksDependants(); - } - - public boolean concurrentSameThreadContexts() { - if (!(this.locksInit())) - this.initLocks(); - - return this.concurrentSameThreadContexts; - } - - public int contextModCount() { - if (!(this.locksInit())) - this.initLocks(); - - return this.contextModCount; - } - - public int latestSameThreadSegmentModCount() { - if (!(this.locksInit())) - this.initLocks(); - - return this.latestSameThreadSegmentModCount; - } - - public LocalLockState localLockState() { - if (!(this.locksInit())) - this.initLocks(); - - return this.localLockState; - } - - public CompiledMapQueryContext rootContextOnThisSegment() { - if (!(this.locksInit())) - this.initLocks(); - - return this.rootContextOnThisSegment; - } - - void closeLocks() { - if (!(this.locksInit())) - return ; - - this.closeLocksDependants(); - if ((rootContextOnThisSegment) == (this)) { - closeRootLocks(); - } else { - closeNestedLocks(); - } - localLockState = null; - rootContextOnThisSegment = null; - } - - public void closeLocksDependants() { - this.innerReadLock.closeReadLockLockDependants(); - this.closeMapQueryDropSearchIfNestedContextsAndPresentHashLookupSlotCheckFailedDependants(); - } - - public void clearSegment() { - this.innerWriteLock.lock(); - this.clearHashLookup(); - freeList().clear(); - nextPosToSearchFrom(0L); - entries(0L); - } - - public void clear() { - clearSegment(); - } - - long searchKey = UNSET_KEY; - - long searchStartPos; - - public boolean searchKeyInit() { - return (this.searchKey) != (UNSET_KEY); - } - - void initSearchKey() { - searchKey = this.maskUnsetKey(this.h().hashSplitting.segmentHash(this.hashOfKey())); - searchStartPos = this.hlPos(searchKey); - this.closeSearchKeyDependants(); - } - - public long searchKey() { - if (!(this.searchKeyInit())) - this.initSearchKey(); - - return this.searchKey; - } - - public long searchStartPos() { - if (!(this.searchKeyInit())) - this.initSearchKey(); - - return this.searchStartPos; - } - - public void closeSearchKey() { - if (!(this.searchKeyInit())) - return ; - - this.closeSearchKeyDependants(); - this.searchKey = UNSET_KEY; - } - - public void closeSearchKeyDependants() { - this.closeHashLookupPos(); - this.closeHashLookupSearchNextPosDependants(); - this.closeHashLookupSearchCheckSlotContainsExpectedKeyAndValueDependants(); - } - - public long hashLookupPos = -1; - - public boolean hashLookupPosInit() { - return (this.hashLookupPos) >= 0; - } - - public void initHashLookupPos() { - this.innerReadLock.lock(); - this.hashLookupPos = this.searchStartPos(); - this.closeHashLookupPosDependants(); - } - - public void initHashLookupPos(long hashLookupPos) { - this.hashLookupPos = hashLookupPos; - this.closeHashLookupPosDependants(); - } - - public long hashLookupPos() { - if (!(this.hashLookupPosInit())) - this.initHashLookupPos(); - - return this.hashLookupPos; - } - - public void closeHashLookupPos() { - if (!(this.hashLookupPosInit())) - return ; - - this.closeHashLookupPosDependants(); - this.hashLookupPos = -1; - } - - public void closeHashLookupPosDependants() { - this.closeHashLookupSearchNextPosDependants(); - this.closeHashLookupSearchFoundDependants(); - this.closeHashLookupSearchCheckSlotContainsExpectedKeyAndValueDependants(); - } - - public void putVolatile(long value) { - this.checkValueForPut(value); - long currentEntry = this.readEntry(this.hashLookupPos()); - assert (this.key(currentEntry)) == (searchKey()); - this.writeEntryVolatile(this.hashLookupPos(), currentEntry, searchKey(), value); - } - - public long nextPos() { - long pos = this.hashLookupPos(); - while (true) { - long entry = this.readEntry(pos); - if (this.empty(entry)) { - this.setHashLookupPosGuarded(pos); - return -1L; - } - pos = this.step(pos); - if (pos == (searchStartPos())) - break; - - if ((this.key(entry)) == (searchKey())) { - this.setHashLookupPosGuarded(pos); - return this.value(entry); - } - } - throw new IllegalStateException(("MultiMap is full, that most likely means you " + ("misconfigured entrySize/chunkSize, and entries tend to take less chunks than " + "expected"))); - } - - public void closeHashLookupSearchNextPosDependants() { - this.closeKeySearch(); - } - - public void putNewVolatile(long value) { - this.checkValueForPut(value); - long currentEntry = this.readEntry(this.hashLookupPos()); - this.writeEntryVolatile(this.hashLookupPos(), currentEntry, searchKey(), value); - } - - void put(long value) { - this.checkValueForPut(value); - this.writeEntry(this.hashLookupPos(), this.readEntry(this.hashLookupPos()), searchKey(), value); - } - - public void found() { - this.setHashLookupPosGuarded(this.stepBack(this.hashLookupPos())); - } - - public void closeHashLookupSearchFoundDependants() { - this.closeKeySearch(); - } - - public boolean checkSlotContainsExpectedKeyAndValue(long value) { - long entry = this.readEntry(this.hashLookupPos()); - return ((this.key(entry)) == (searchKey())) && ((this.value(entry)) == value); - } - - public void closeHashLookupSearchCheckSlotContainsExpectedKeyAndValueDependants() { - this.closeMapQueryDropSearchIfNestedContextsAndPresentHashLookupSlotCheckFailedDependants(); - } - - public void remove() { - this.setHashLookupPosGuarded(this.remove(this.hashLookupPos())); - } - - public boolean checkSlotIsEmpty() { - return this.empty(this.readEntry(this.hashLookupPos())); - } - - public long pos = -1; - - public boolean posInit() { - return (this.pos) >= 0; - } - - public void initPos(long pos) { - this.pos = pos; - this.closePosDependants(); - } - - public long pos() { - assert this.posInit() : "Pos should be init"; - return this.pos; - } - - public void closePos() { - if (!(this.posInit())) - return ; - - this.closePosDependants(); - this.pos = -1; - } - - public void closePosDependants() { - this.closeEntryOffset(); - this.closeMapQueryDropSearchIfNestedContextsAndPresentHashLookupSlotCheckFailedDependants(); - } - - public long keySizeOffset = -1; - - public boolean entryOffsetInit() { - return (this.keySizeOffset) >= 0; - } - - public void initEntryOffset() { - keySizeOffset = (this.entrySpaceOffset()) + ((pos()) * (this.h().chunkSize)); - entryBytes.limit(entryBytes.capacity()); - this.closeEntryOffsetDependants(); - } - - public long keySizeOffset() { - if (!(this.entryOffsetInit())) - this.initEntryOffset(); - - return this.keySizeOffset; - } - - public void closeEntryOffset() { - if (!(this.entryOffsetInit())) - return ; - - this.closeEntryOffsetDependants(); - this.keySizeOffset = -1; - } - - public void closeEntryOffsetDependants() { - this.closeMapEntryStagesEntrySizeDependants(); - this.closeMapEntryStagesReadExistingEntryDependants(); - } - - public void copyExistingEntry(long newPos, long bytesToCopy) { - long oldKeySizeOffset = keySizeOffset(); - long oldKeyOffset = keyOffset(); - initPos(newPos); - initKeyOffset(((keySizeOffset()) + (oldKeyOffset - oldKeySizeOffset))); - entryBS.write(keySizeOffset(), entryBS, oldKeySizeOffset, bytesToCopy); - } - - public void readExistingEntry(long pos) { - initPos(pos); - entryBytes.position(keySizeOffset()); - initKeySize(this.h().keySizeMarshaller.readSize(entryBytes)); - initKeyOffset(entryBytes.position()); - } - - public void closeMapEntryStagesReadExistingEntryDependants() { - this.closeKeySearch(); - } - - public long keySize = -1; - - public boolean keySizeInit() { - return (this.keySize) >= 0; - } - - public void initKeySize(long keySize) { - this.keySize = keySize; - this.closeKeySizeDependants(); - } - - public long keySize() { - assert this.keySizeInit() : "KeySize should be init"; - return this.keySize; - } - - public void closeKeySize() { - if (!(this.keySizeInit())) - return ; - - this.closeKeySizeDependants(); - this.keySize = -1; - } - - public void closeKeySizeDependants() { - this.closeMapEntryStagesKeyEndDependants(); - this.closeMapQueryKeyEqualsDependants(); - this.entryKey.closeEntryKeyBytesDataSizeDependants(); - } - - public void writeNewEntry(long pos, Data key) { - initPos(pos); - initKeySize(key.size()); - entryBytes.position(keySizeOffset()); - this.h().keySizeMarshaller.writeSize(entryBytes, keySize()); - initKeyOffset(entryBytes.position()); - key.writeTo(entryBS, keyOffset()); - } - - public long keyEnd() { - return (keyOffset()) + (keySize()); - } - - public void closeMapEntryStagesKeyEndDependants() { - this.closeMapEntryStagesCountValueSizeOffsetDependants(); - this.closeMapEntryStagesEntryEndDependants(); - } - - long countValueSizeOffset() { - return keyEnd(); - } - - public void closeMapEntryStagesCountValueSizeOffsetDependants() { - this.closeValueSizeOffset(); - } - - public long valueSizeOffset = -1; - - public boolean valueSizeOffsetInit() { - return (this.valueSizeOffset) >= 0; - } - - void initValueSizeOffset() { - valueSizeOffset = countValueSizeOffset(); - this.closeValueSizeOffsetDependants(); - } - - public long valueSizeOffset() { - if (!(this.valueSizeOffsetInit())) - this.initValueSizeOffset(); - - return this.valueSizeOffset; - } - - public void closeValueSizeOffset() { - if (!(this.valueSizeOffsetInit())) - return ; - - this.closeValueSizeOffsetDependants(); - this.valueSizeOffset = -1; - } - - public void closeValueSizeOffsetDependants() { - this.closeValSize(); - } - - public long valueSize = -1; - - public long valueOffset; - - public boolean valSizeInit() { - return (this.valueSize) >= 0; - } - - void initValSize() { - entryBytes.position(valueSizeOffset()); - valueSize = this.m().readValueSize(entryBytes); - countValueOffset(); - this.closeValSizeDependants(); - } - - void initValSize(long valueSize) { - this.valueSize = valueSize; - entryBytes.position(valueSizeOffset()); - this.m().valueSizeMarshaller.writeSize(entryBytes, valueSize); - countValueOffset(); - this.closeValSizeDependants(); - } - - void initValSizeEqualToOld(long oldValueSizeOffset, long oldValueSize, long oldValueOffset) { - valueSize = oldValueSize; - valueOffset = (valueSizeOffset()) + (oldValueOffset - oldValueSizeOffset); - this.closeValSizeDependants(); - } - - public long valueOffset() { - if (!(this.valSizeInit())) - this.initValSize(); - - return this.valueOffset; - } - - public long valueSize() { - if (!(this.valSizeInit())) - this.initValSize(); - - return this.valueSize; - } - - public void closeValSize() { - if (!(this.valSizeInit())) - return ; - - this.closeValSizeDependants(); - this.valueSize = -1; - } - - public void closeValSizeDependants() { - this.closeMapEntryStagesEntryEndDependants(); - this.entryValue.closeEntryValueBytesDataSizeDependants(); - this.entryValue.closeEntryValueBytesDataInnerGetUsingDependants(); - } - - protected long entryEnd() { - return (valueOffset()) + (valueSize()); - } - - public void closeMapEntryStagesEntryEndDependants() { - this.closeMapEntryStagesEntrySizeDependants(); - } - - long entrySize() { - return (entryEnd()) - (keySizeOffset()); - } - - public void closeMapEntryStagesEntrySizeDependants() { - this.closeTheEntrySizeInChunks(); - } - - public int entrySizeInChunks = 0; - - public boolean theEntrySizeInChunksInit() { - return (this.entrySizeInChunks) != 0; - } - - void initTheEntrySizeInChunks() { - entrySizeInChunks = this.h().inChunks(entrySize()); - } - - public void initTheEntrySizeInChunks(int actuallyUsedChunks) { - entrySizeInChunks = actuallyUsedChunks; - } - - public int entrySizeInChunks() { - if (!(this.theEntrySizeInChunksInit())) - this.initTheEntrySizeInChunks(); - - return this.entrySizeInChunks; - } - - public void closeTheEntrySizeInChunks() { - if (!(this.theEntrySizeInChunksInit())) - return ; - - this.entrySizeInChunks = 0; - } - - public final void freeExtraAllocatedChunks() { - if (((!(this.m().constantlySizedEntry)) && (this.m().couldNotDetermineAlignmentBeforeAllocation)) && ((entrySizeInChunks()) < (this.allocatedChunks()))) { - this.free(((pos()) + (entrySizeInChunks())), ((this.allocatedChunks()) - (entrySizeInChunks()))); - } else { - initTheEntrySizeInChunks(this.allocatedChunks()); - } - } - - public void innerRemoveEntryExceptHashLookupUpdate() { - this.free(pos(), entrySizeInChunks()); - this.entries(((this.entries()) - 1L)); - this.incrementModCountGuarded(); - } - - public void writeValue(Data value) { - value.writeTo(entryBS, valueOffset()); - } - - public void initValue(Data value) { - entryBytes.position(valueSizeOffset()); - initValSize(value.size()); - writeValue(value); - } - - public void writeValueAndPutPos(Data value) { - initValue(value); - freeExtraAllocatedChunks(); - this.putValueVolatile(this.hashLookupPos(), pos()); - } - - public void initValueWithoutSize(Data value, long oldValueSizeOffset, long oldValueSize, long oldValueOffset) { - assert oldValueSize == (value.size()); - initValSizeEqualToOld(oldValueSizeOffset, oldValueSize, oldValueOffset); - writeValue(value); - } - - public long newSizeOfEverythingBeforeValue(Data newValue) { - return ((valueSizeOffset()) + (this.m().valueSizeMarshaller.sizeEncodingSize(newValue.size()))) - (keySizeOffset()); - } - - boolean keyEquals() { - return ((inputKey().size()) == (this.keySize())) && (BytesUtil.bytesEqual(this.entryBS, this.keyOffset(), inputKey().bytes(), inputKey().offset(), this.keySize())); - } - - public void closeMapQueryKeyEqualsDependants() { - this.closeKeySearch(); - } - - protected CompiledMapQueryContext.SearchState searchState = null; - - boolean keySearchInit() { - return (this.searchState) != null; - } - - void initKeySearch() { - for (long pos ; (pos = this.nextPos()) >= 0L ; ) { - this.readExistingEntry(pos); - if (!(keyEquals())) - continue; - - this.found(); - keyFound(); - return ; - } - searchState = CompiledMapQueryContext.SearchState.ABSENT; - this.closeKeySearchDependants(); - } - - public CompiledMapQueryContext.SearchState searchState() { - if (!(this.keySearchInit())) - this.initKeySearch(); - - return this.searchState; - } - - void closeKeySearch() { - if (!(this.keySearchInit())) - return ; - - this.closeKeySearchDependants(); - this.searchState = null; - } - - public void closeKeySearchDependants() { - this.closeMapQueryDropSearchIfNestedContextsAndPresentHashLookupSlotCheckFailedDependants(); - } - - public void incrementSegmentEntriesIfNeeded() { - if ((this.searchState()) != (CompiledMapQueryContext.SearchState.PRESENT)) { - this.entries(((this.entries()) + 1L)); - } - } - - public void initEntryAndKeyCopying(long entrySize, long bytesToCopy) { - initAllocatedChunks(this.h().inChunks(entrySize)); - this.copyExistingEntry(this.alloc(allocatedChunks()), bytesToCopy); - incrementSegmentEntriesIfNeeded(); - } - - protected void relocation(Data newValue, long newSizeOfEverythingBeforeValue) { - this.free(pos(), entrySizeInChunks()); - long entrySize = innerEntrySize(newSizeOfEverythingBeforeValue, newValue.size()); - this.initEntryAndKeyCopying(entrySize, ((valueSizeOffset()) - (keySizeOffset()))); - writeValueAndPutPos(newValue); - } - - public void innerDefaultReplaceValue(Data newValue) { - assert this.innerUpdateLock.isHeldByCurrentThread(); - boolean newValueSizeIsDifferent = (newValue.size()) != (this.valueSize()); - if (newValueSizeIsDifferent) { - long newSizeOfEverythingBeforeValue = newSizeOfEverythingBeforeValue(newValue); - long entryStartOffset = keySizeOffset(); - VanillaChronicleMap m = this.m(); - long newValueOffset = m.alignment.alignAddr((entryStartOffset + newSizeOfEverythingBeforeValue)); - long newEntrySize = (newValueOffset + (newValue.size())) - entryStartOffset; - int newSizeInChunks = m.inChunks(newEntrySize); - newValueDoesNotFit : if (newSizeInChunks > (entrySizeInChunks())) { - if (newSizeInChunks > (m.maxChunksPerEntry)) { - throw new IllegalArgumentException(((((("Value too large: " + "entry takes ") + newSizeInChunks) + " chunks, ") + (m.maxChunksPerEntry)) + " is maximum.")); - } - if (this.freeList().allClear(((pos()) + (entrySizeInChunks())), ((pos()) + newSizeInChunks))) { - this.freeList().set(((pos()) + (entrySizeInChunks())), ((pos()) + newSizeInChunks)); - break newValueDoesNotFit; - } - relocation(newValue, newSizeOfEverythingBeforeValue); - return ; - } else if (newSizeInChunks < (entrySizeInChunks())) { - this.freeList().clear(((pos()) + newSizeInChunks), ((pos()) + (entrySizeInChunks()))); - } - } else { - } - this.innerWriteLock.lock(); - if (newValueSizeIsDifferent) { - initValue(newValue); - } else { - writeValue(newValue); - } - this.putValueVolatile(this.hashLookupPos(), pos()); - } - - public void putValueDeletedEntry(Data newValue) { - assert this.innerUpdateLock.isHeldByCurrentThread(); - int newSizeInChunks; - long entryStartOffset = keySizeOffset(); - long newSizeOfEverythingBeforeValue = -1; - boolean newValueSizeIsDifferent = (newValue.size()) != (valueSize()); - if (newValueSizeIsDifferent) { - newSizeOfEverythingBeforeValue = newSizeOfEverythingBeforeValue(newValue); - long newValueOffset = this.m().alignment.alignAddr((entryStartOffset + newSizeOfEverythingBeforeValue)); - long newEntrySize = (newValueOffset + (newValue.size())) - entryStartOffset; - newSizeInChunks = this.m().inChunks(newEntrySize); - } else { - newSizeInChunks = entrySizeInChunks(); - } - if ((((pos()) + newSizeInChunks) < (this.freeList().size())) && (this.freeList().allClear(pos(), ((pos()) + newSizeInChunks)))) { - this.freeList().set(pos(), ((pos()) + newSizeInChunks)); - this.innerWriteLock.lock(); - this.incrementSegmentEntriesIfNeeded(); - if (newValueSizeIsDifferent) { - initValue(newValue); - } else { - writeValue(newValue); - } - } else { - if (newValueSizeIsDifferent) { - assert newSizeOfEverythingBeforeValue >= 0; - } else { - newSizeOfEverythingBeforeValue = newSizeOfEverythingBeforeValue(newValue); - } - long entrySize = innerEntrySize(newSizeOfEverythingBeforeValue, newValue.size()); - if (newValueSizeIsDifferent) { - this.initEntryAndKeyCopying(entrySize, ((valueSizeOffset()) - entryStartOffset)); - initValue(newValue); - } else { - long oldValueSizeOffset = valueSizeOffset(); - long oldValueSize = valueSize(); - long oldValueOffset = valueOffset(); - this.initEntryAndKeyCopying(entrySize, ((valueOffset()) - entryStartOffset)); - initValueWithoutSize(newValue, oldValueSizeOffset, oldValueSize, oldValueOffset); - } - freeExtraAllocatedChunks(); - } - this.putValueVolatile(this.hashLookupPos(), pos()); - } - - public void initEntryAndKey(long entrySize) { - initAllocatedChunks(this.h().inChunks(entrySize)); - this.writeNewEntry(this.alloc(allocatedChunks()), this.inputKey()); - incrementSegmentEntriesIfNeeded(); - } - - public boolean searchStateDeleted() { - return (((searchState()) == (CompiledMapQueryContext.SearchState.DELETED)) && (!(this.concurrentSameThreadContexts()))) && (this.innerUpdateLock.isHeldByCurrentThread()); - } - - public void dropSearchIfNestedContextsAndPresentHashLookupSlotCheckFailed() { - if (this.locksInit()) { - if ((this.concurrentSameThreadContexts()) && ((this.rootContextOnThisSegment().latestSameThreadSegmentModCount()) != (this.contextModCount()))) { - if (keySearchInit()) { - if ((searchState()) == (CompiledMapQueryContext.SearchState.PRESENT)) { - if (!(this.checkSlotContainsExpectedKeyAndValue(this.pos()))) - this.closeHashLookupPos(); - - } - } - } - } - } - - public void closeMapQueryDropSearchIfNestedContextsAndPresentHashLookupSlotCheckFailedDependants() { - this.closeQueryCheckOnEachPublicOperationCheckOnEachPublicOperationDependants(); - } - - public void checkOnEachPublicOperation() { - _CheckOnEachPublicOperation_checkOnEachPublicOperation(); - this.dropSearchIfNestedContextsAndPresentHashLookupSlotCheckFailed(); - } - - public void closeQueryCheckOnEachPublicOperationCheckOnEachPublicOperationDependants() { - this.entryValue.closeEntryValueBytesDataSizeDependants(); - this.entryKey.closeEntryKeyBytesDataSizeDependants(); - } - - @Override - public R replaceValue(@NotNull - MapEntry entry, Data newValue) { - this.checkOnEachPublicOperation(); - return this.m().entryOperations.replaceValue(entry, newValue); - } - - @NotNull - @Override - public InterProcessLock updateLock() { - this.checkOnEachPublicOperation(); - return this.innerUpdateLock; - } - - @NotNull - @Override - public InterProcessLock readLock() { - this.checkOnEachPublicOperation(); - return this.innerReadLock; - } - - @NotNull - @Override - public Data value() { - this.checkOnEachPublicOperation(); - return this.entryValue; - } - - @Override - public R remove(@NotNull - MapEntry entry) { - this.checkOnEachPublicOperation(); - return this.m().entryOperations.remove(entry); - } - - @NotNull - @Override - public Data defaultValue() { - this.checkOnEachPublicOperation(); - return this.wrapValueAsValue(this.m().defaultValue(this.deprecatedMapKeyContext)); - } - - @NotNull - @Override - public InterProcessLock writeLock() { - this.checkOnEachPublicOperation(); - return this.innerWriteLock; - } - - @NotNull - @Override - public MapContext context() { - this.checkOnEachPublicOperation(); - return this; - } - - @Override - public R insert(@NotNull - MapAbsentEntry absentEntry, Data value) { - this.checkOnEachPublicOperation(); - return this.m().entryOperations.insert(absentEntry, value); - } - - @Override - public Data wrapValueAsValue(V value) { - this.checkOnEachPublicOperation(); - WrappedValueInstanceData wrapped = this.wrappedValueInstanceValue; - wrapped = wrapped.getUnusedWrappedValueGuarded(); - wrapped.initValue(value); - return wrapped; - } - - public Data queriedKey() { - this.checkOnEachPublicOperation(); - return inputKey(); - } - - @Override - public Data defaultValue(@NotNull - MapAbsentEntry absentEntry) { - this.checkOnEachPublicOperation(); - return this.m().entryOperations.defaultValue(absentEntry); - } - - @NotNull - @Override - public Data absentKey() { - this.checkOnEachPublicOperation(); - return this.inputKey(); - } - - @NotNull - @Override - public Data key() { - this.checkOnEachPublicOperation(); - return this.entryKey; - } - - public boolean searchStatePresent() { - return (searchState()) == (CompiledMapQueryContext.SearchState.PRESENT); - } - - public boolean entryPresent() { - return searchStatePresent(); - } - - @Override - public MapEntry entry() { - this.checkOnEachPublicOperation(); - return entryPresent() ? this : null; - } - - @Nullable - @Override - public MapAbsentEntry absentEntry() { - this.checkOnEachPublicOperation(); - return entryPresent() ? null : this.absent(); - } - - public boolean searchStateAbsent() { - return (!(searchStatePresent())) && (!(searchStateDeleted())); - } - - void putEntry(Data value) { - assert this.searchStateAbsent(); - long entrySize = this.entrySize(this.inputKey().size(), value.size()); - this.initEntryAndKey(entrySize); - this.initValue(value); - this.freeExtraAllocatedChunks(); - this.putNewVolatile(this.pos()); - } - - protected void putPrefix() { - this.checkOnEachPublicOperation(); - boolean underUpdatedLockIsHeld = !(this.innerUpdateLock.isHeldByCurrentThread()); - if (underUpdatedLockIsHeld) - this.innerUpdateLock.lock(); - - boolean searchResultsNotTrusted = underUpdatedLockIsHeld || (this.concurrentSameThreadContexts()); - if (((this.hashLookupPosInit()) && (searchStateAbsent())) && searchResultsNotTrusted) - this.closeHashLookupPos(); - - } - - @Override - public void doInsert(Data value) { - this.putPrefix(); - if (!(this.searchStatePresent())) { - if (this.searchStateDeleted()) { - this.putValueDeletedEntry(value); - } else { - putEntry(value); - } - this.incrementModCountGuarded(); - this.setSearchStateGuarded(CompiledMapQueryContext.SearchState.PRESENT); - } else { - throw new IllegalStateException("Entry is present in the map when doInsert() is called"); - } - } - - @Override - public void doReplaceValue(Data newValue) { - putPrefix(); - if (searchStatePresent()) { - this.innerDefaultReplaceValue(newValue); - this.incrementModCountGuarded(); - setSearchStateGuarded(CompiledMapQueryContext.SearchState.PRESENT); - } else { - throw new IllegalStateException("Entry is absent in the map when doReplaceValue() is called"); - } - } - - @Override - public void doRemove() { - this.checkOnEachPublicOperation(); - this.innerUpdateLock.lock(); - if (searchStatePresent()) { - this.innerWriteLock.lock(); - this.remove(); - this.innerRemoveEntryExceptHashLookupUpdate(); - setSearchStateGuarded(CompiledMapQueryContext.SearchState.DELETED); - } else { - throw new IllegalStateException("Entry is absent when doRemove() is called"); - } - } - - boolean used; - - public boolean usedInit() { - return used; - } - - public void initUsed(boolean used) { - this.used = used; - } - - void closeUsed() { - if (!(this.usedInit())) - return ; - - used = false; - } - - public Bytes inputBytes = null; - - public boolean inputBytesInit() { - return (this.inputBytes) != null; - } - - public void initInputBytes(Bytes inputBytes) { - this.inputBytes = inputBytes; - inputStore.setBytes(inputBytes); - this.closeInputBytesDependants(); - } - - public Bytes inputBytes() { - assert this.inputBytesInit() : "InputBytes should be init"; - return this.inputBytes; - } - - public void closeInputBytes() { - if (!(this.inputBytesInit())) - return ; - - this.closeInputBytesDependants(); - this.inputBytes = null; - } - - public void closeInputBytesDependants() { - this.closeInputKeyOffsets(); - this.closeFirstInputValueOffsets(); - this.inputFirstValueBytesValue.closeInputFirstValueBytesDataGetUsingDependants(); - this.inputKeyBytesValue.closeInputKeyBytesDataGetUsingDependants(); - this.closeSecondInputValueOffsets(); - this.inputSecondValueBytesValue.closeInputSecondValueBytesDataGetUsingDependants(); - } - - public long inputKeySize = -1; - - public long inputKeyOffset; - - public boolean inputKeyOffsetsInit() { - return (this.inputKeySize) >= 0; - } - - private void initInputKeyOffsets() { - inputKeySize = this.h().keySizeMarshaller.readSize(inputBytes()); - inputKeyOffset = inputBytes().position(); - this.closeInputKeyOffsetsDependants(); - } - - public long inputKeyOffset() { - if (!(this.inputKeyOffsetsInit())) - this.initInputKeyOffsets(); - - return this.inputKeyOffset; - } - - public long inputKeySize() { - if (!(this.inputKeyOffsetsInit())) - this.initInputKeyOffsets(); - - return this.inputKeySize; - } - - public void closeInputKeyOffsets() { - if (!(this.inputKeyOffsetsInit())) - return ; - - this.closeInputKeyOffsetsDependants(); - this.inputKeySize = -1; - } - - public void closeInputKeyOffsetsDependants() { - this.closeFirstInputValueOffsets(); - this.inputKeyBytesValue.closeInputKeyBytesDataSizeDependants(); - this.inputKeyBytesValue.closeInputKeyBytesDataGetUsingDependants(); - } - - public long firstInputValueSize = -1; - - public long firstInputValueOffset; - - public boolean firstInputValueOffsetsInit() { - return (this.firstInputValueSize) >= 0; - } - - private void initFirstInputValueOffsets() { - this.inputBytes().position(((this.inputKeyOffset()) + (this.inputKeySize()))); - firstInputValueSize = this.m().valueSizeMarshaller.readSize(this.inputBytes()); - firstInputValueOffset = this.inputBytes().position(); - this.closeFirstInputValueOffsetsDependants(); - } - - public long firstInputValueOffset() { - if (!(this.firstInputValueOffsetsInit())) - this.initFirstInputValueOffsets(); - - return this.firstInputValueOffset; - } - - public long firstInputValueSize() { - if (!(this.firstInputValueOffsetsInit())) - this.initFirstInputValueOffsets(); - - return this.firstInputValueSize; - } - - public void closeFirstInputValueOffsets() { - if (!(this.firstInputValueOffsetsInit())) - return ; - - this.closeFirstInputValueOffsetsDependants(); - this.firstInputValueSize = -1; - } - - public void closeFirstInputValueOffsetsDependants() { - this.closeSecondInputValueOffsets(); - this.inputFirstValueBytesValue.closeInputFirstValueBytesDataSizeDependants(); - this.inputFirstValueBytesValue.closeInputFirstValueBytesDataGetUsingDependants(); - } - - public long secondInputValueSize = -1; - - public long secondInputValueOffset; - - public boolean secondInputValueOffsetsInit() { - return (this.secondInputValueSize) >= 0; - } - - private void initSecondInputValueOffsets() { - this.inputBytes().position(((firstInputValueOffset()) + (firstInputValueSize()))); - secondInputValueSize = this.m().valueSizeMarshaller.readSize(this.inputBytes()); - secondInputValueOffset = this.inputBytes().position(); - this.closeSecondInputValueOffsetsDependants(); - } - - public long secondInputValueOffset() { - if (!(this.secondInputValueOffsetsInit())) - this.initSecondInputValueOffsets(); - - return this.secondInputValueOffset; - } - - public long secondInputValueSize() { - if (!(this.secondInputValueOffsetsInit())) - this.initSecondInputValueOffsets(); - - return this.secondInputValueSize; - } - - public void closeSecondInputValueOffsets() { - if (!(this.secondInputValueOffsetsInit())) - return ; - - this.closeSecondInputValueOffsetsDependants(); - this.secondInputValueSize = -1; - } - - public void closeSecondInputValueOffsetsDependants() { - this.inputSecondValueBytesValue.closeInputSecondValueBytesDataSizeDependants(); - this.inputSecondValueBytesValue.closeInputSecondValueBytesDataGetUsingDependants(); - } -} diff --git a/src/main/java/net/openhft/chronicle/map/impl/CompiledReplicatedMapIterationContext.java b/src/main/java/net/openhft/chronicle/map/impl/CompiledReplicatedMapIterationContext.java deleted file mode 100644 index 7d117fad4..000000000 --- a/src/main/java/net/openhft/chronicle/map/impl/CompiledReplicatedMapIterationContext.java +++ /dev/null @@ -1,2559 +0,0 @@ -package net.openhft.chronicle.map.impl; - -import net.openhft.chronicle.bytes.BytesStore; -import net.openhft.chronicle.bytes.NativeBytesStore; -import net.openhft.chronicle.bytes.RandomDataInput; -import net.openhft.chronicle.bytes.ZeroRandomDataInput; -import net.openhft.chronicle.hash.AbstractData; -import net.openhft.chronicle.hash.Data; -import net.openhft.chronicle.hash.HashEntry; -import net.openhft.chronicle.hash.impl.*; -import net.openhft.chronicle.hash.impl.hashlookup.EntryConsumer; -import net.openhft.chronicle.hash.locks.InterProcessLock; -import net.openhft.chronicle.hash.locks.InterProcessReadWriteUpdateLock; -import net.openhft.chronicle.hash.replication.RemoteOperationContext; -import net.openhft.chronicle.hash.replication.ReplicableEntry; -import net.openhft.chronicle.hash.replication.TimeProvider; -import net.openhft.chronicle.hash.serialization.BytesReader; -import net.openhft.chronicle.hash.serialization.internal.MetaBytesInterop; -import net.openhft.chronicle.map.*; -import net.openhft.chronicle.map.replication.MapReplicableEntry; -import net.openhft.lang.Maths; -import net.openhft.lang.MemoryUnit; -import net.openhft.lang.collection.DirectBitSet; -import net.openhft.lang.collection.SingleThreadedDirectBitSet; -import net.openhft.lang.io.Bytes; -import net.openhft.lang.io.DirectBytes; -import net.openhft.lang.io.MultiStoreBytes; -import net.openhft.lang.io.NativeBytes; -import net.openhft.lang.threadlocal.ThreadLocalCopies; -import org.jetbrains.annotations.NotNull; - -import java.util.ArrayList; -import java.util.ConcurrentModificationException; -import java.util.List; -import java.util.concurrent.TimeUnit; -import java.util.function.Consumer; -import java.util.function.Predicate; - -public class CompiledReplicatedMapIterationContext, V, VI, MVI extends MetaBytesInterop, R, T> implements AutoCloseable , HashEntry , InterProcessReadWriteUpdateLock , RemoteOperationContext , ReplicableEntry , MapContext , MapEntry , IterationContextInterface , ReplicatedChronicleMapHolder , ReplicatedIterationContextInterface , MapReplicableEntry { - public void close() { - this.closeTheSegmentIndex(); - this.wrappedValueInstanceValue.closeValue(); - this.closeEntryRemovedOnThisIteration(); - this.wrappedValueInstanceValue.closeNext(); - this.closeUsed(); - this.closeKeySize(); - this.closePos(); - this.closeReplicationUpdate(); - this.closeAllocatedChunks(); - this.closeHashLookupPos(); - this.closeKeyOffset(); - this.closeReplicatedChronicleMapHolderImplContextAtIndexInChainDependants(); - this.closeOwnerThreadHolderCheckAccessingFromOwnerThreadDependants(); - this.closeValueBytesInteropValueMetaInteropDependants(); - this.closeReplicatedMapSegmentIterationCheckEntryNotRemovedOnThisIterationDependants(); - } - - public void incrementModCountGuarded() { - if (!(this.locksInit())) - this.initLocks(); - - incrementModCount(); - } - - public void setHashLookupPosGuarded(long hashLookupPos) { - assert this.hashLookupPosInit() : "HashLookupPos should be init"; - setHashLookupPos(hashLookupPos); - } - - public void setLocalLockStateGuarded(LocalLockState newState) { - if (!(this.locksInit())) - this.initLocks(); - - setLocalLockState(newState); - } - - private long _MapEntryStages_countValueSizeOffset() { - return keyEnd(); - } - - private long _MapEntryStages_sizeOfEverythingBeforeValue(long keySize, long valueSize) { - return (((this.m().metaDataBytes) + (this.m().keySizeMarshaller.sizeEncodingSize(keySize))) + keySize) + (this.m().valueSizeMarshaller.sizeEncodingSize(valueSize)); - } - - public CompiledReplicatedMapIterationContext(ReplicatedChronicleMap m) { - contextChain = new ArrayList(); - contextChain.add(this); - indexInContextChain = 0; - this.m = m; - this.copies = ThreadLocalCopies.get(); - this.valueInterop = this.m().valueInteropProvider.get(this.copies, this.m().originalValueInterop); - this.valueReader = this.m().valueReaderProvider.get(this.copies, this.m().originalValueReader); - this.keyInterop = this.h().keyInteropProvider.get(this.copies, this.h().originalKeyInterop); - this.keyReader = this.h().keyReaderProvider.get(this.copies, this.h().originalKeyReader); - this.entryKey = new EntryKeyBytesData(); - this.innerUpdateLock = new UpdateLock(); - this.innerReadLock = new ReadLock(); - this.entryValue = new EntryValueBytesData(); - this.innerWriteLock = new WriteLock(); - this.entryBytes = this.h().ms.bytes(); - this.entryBS = new NativeBytesStore(entryBytes.address() , entryBytes.capacity() , null , false); - this.owner = Thread.currentThread(); - this.deprecatedMapKeyContextOnIteration = new DeprecatedMapKeyContextOnIteration(); - this.dummyValue = new DummyValueZeroData(); - this.wrappedValueInstanceValue = new WrappedValueInstanceData(); - } - - public CompiledReplicatedMapIterationContext(CompiledReplicatedMapIterationContext c) { - contextChain = c.contextChain; - indexInContextChain = contextChain.size(); - contextChain.add(this); - this.m = ((ReplicatedChronicleMap)(c.m)); - this.copies = ThreadLocalCopies.get(); - this.valueInterop = this.m().valueInteropProvider.get(this.copies, this.m().originalValueInterop); - this.valueReader = this.m().valueReaderProvider.get(this.copies, this.m().originalValueReader); - this.keyInterop = this.h().keyInteropProvider.get(this.copies, this.h().originalKeyInterop); - this.keyReader = this.h().keyReaderProvider.get(this.copies, this.h().originalKeyReader); - this.entryKey = new EntryKeyBytesData(); - this.innerUpdateLock = new UpdateLock(); - this.innerReadLock = new ReadLock(); - this.entryValue = new EntryValueBytesData(); - this.innerWriteLock = new WriteLock(); - this.entryBytes = this.h().ms.bytes(); - this.entryBS = new NativeBytesStore(entryBytes.address() , entryBytes.capacity() , null , false); - this.owner = Thread.currentThread(); - this.deprecatedMapKeyContextOnIteration = new DeprecatedMapKeyContextOnIteration(); - this.dummyValue = new DummyValueZeroData(); - this.wrappedValueInstanceValue = new WrappedValueInstanceData(); - } - - public class DeprecatedMapKeyContextOnIteration implements MapKeyContext { - @Override - public void close() { - throw new UnsupportedOperationException("close() is not supported during iteration"); - } - - @Override - public V get() { - CompiledReplicatedMapIterationContext.this.checkOnEachPublicOperation(); - return CompiledReplicatedMapIterationContext.this.value().get(); - } - - @NotNull - @Override - public K key() { - CompiledReplicatedMapIterationContext.this.checkOnEachPublicOperation(); - return CompiledReplicatedMapIterationContext.this.key().get(); - } - - @Override - public boolean containsKey() { - CompiledReplicatedMapIterationContext.this.checkOnEachPublicOperation(); - return true; - } - - @Override - public boolean put(V newValue) { - CompiledReplicatedMapIterationContext.this.checkOnEachPublicOperation(); - CompiledReplicatedMapIterationContext.this.replaceValue(CompiledReplicatedMapIterationContext.this, CompiledReplicatedMapIterationContext.this.context().wrapValueAsValue(newValue)); - return true; - } - - @NotNull - @Override - public Bytes entry() { - CompiledReplicatedMapIterationContext.this.checkOnEachPublicOperation(); - return CompiledReplicatedMapIterationContext.this.entryBytes; - } - - @Override - public boolean valueEqualTo(V value) { - CompiledReplicatedMapIterationContext.this.checkOnEachPublicOperation(); - return Data.bytesEquivalent(CompiledReplicatedMapIterationContext.this.entryValue, CompiledReplicatedMapIterationContext.this.context().wrapValueAsValue(value)); - } - - @Override - public boolean remove() { - CompiledReplicatedMapIterationContext.this.checkOnEachPublicOperation(); - CompiledReplicatedMapIterationContext.this.remove(CompiledReplicatedMapIterationContext.this); - return true; - } - - @Override - public V getUsing(V usingValue) { - CompiledReplicatedMapIterationContext.this.checkOnEachPublicOperation(); - return CompiledReplicatedMapIterationContext.this.value().getUsing(usingValue); - } - - @NotNull - private UnsupportedOperationException unsupportedLocks() { - return new UnsupportedOperationException("Lock operations are not supported (and not needed!) during iteration"); - } - - @NotNull - @Override - public InterProcessLock readLock() { - throw unsupportedLocks(); - } - - @NotNull - @Override - public InterProcessLock writeLock() { - throw unsupportedLocks(); - } - - @NotNull - @Override - public InterProcessLock updateLock() { - throw unsupportedLocks(); - } - - @Override - public long keyOffset() { - CompiledReplicatedMapIterationContext.this.checkOnEachPublicOperation(); - return CompiledReplicatedMapIterationContext.this.keyOffset(); - } - - @Override - public long valueOffset() { - CompiledReplicatedMapIterationContext.this.checkOnEachPublicOperation(); - return CompiledReplicatedMapIterationContext.this.valueOffset(); - } - - @Override - public long valueSize() { - CompiledReplicatedMapIterationContext.this.checkOnEachPublicOperation(); - return CompiledReplicatedMapIterationContext.this.valueSize(); - } - - @Override - public long keySize() { - CompiledReplicatedMapIterationContext.this.checkOnEachPublicOperation(); - return CompiledReplicatedMapIterationContext.this.keySize(); - } - } - - public class DummyValueZeroData extends AbstractData { - @Override - public long size() { - return CompiledReplicatedMapIterationContext.this.m().valueSizeMarshaller.minEncodableSize(); - } - - @Override - public RandomDataInput bytes() { - return ZeroRandomDataInput.INSTANCE; - } - - @Override - public V get() { - throw new UnsupportedOperationException(); - } - - @Override - public V getUsing(V usingInstance) { - throw new UnsupportedOperationException(); - } - - @Override - public long offset() { - return 0; - } - } - - public class EntryKeyBytesData extends AbstractData { - @Override - public RandomDataInput bytes() { - CompiledReplicatedMapIterationContext.this.checkOnEachPublicOperation(); - return CompiledReplicatedMapIterationContext.this.entryBS; - } - - @Override - public long offset() { - CompiledReplicatedMapIterationContext.this.checkOnEachPublicOperation(); - return CompiledReplicatedMapIterationContext.this.keyOffset(); - } - - @Override - public long size() { - CompiledReplicatedMapIterationContext.this.checkOnEachPublicOperation(); - return CompiledReplicatedMapIterationContext.this.keySize(); - } - - public void closeEntryKeyBytesDataSizeDependants() { - this.closeEntryKeyBytesDataInnerGetUsingDependants(); - } - - private K innerGetUsing(K usingKey) { - CompiledReplicatedMapIterationContext.this.entryBytes.position(CompiledReplicatedMapIterationContext.this.keyOffset()); - return CompiledReplicatedMapIterationContext.this.keyReader.read(CompiledReplicatedMapIterationContext.this.entryBytes, size(), usingKey); - } - - public void closeEntryKeyBytesDataInnerGetUsingDependants() { - this.closeCachedEntryKey(); - } - - private K cachedEntryKey; - - private boolean cachedEntryKeyRead = false; - - public boolean cachedEntryKeyInit() { - return (this.cachedEntryKeyRead) != false; - } - - private void initCachedEntryKey() { - cachedEntryKey = innerGetUsing(cachedEntryKey); - cachedEntryKeyRead = true; - } - - public K cachedEntryKey() { - if (!(this.cachedEntryKeyInit())) - this.initCachedEntryKey(); - - return this.cachedEntryKey; - } - - public void closeCachedEntryKey() { - if (!(this.cachedEntryKeyInit())) - return ; - - this.cachedEntryKeyRead = false; - } - - @Override - public K get() { - CompiledReplicatedMapIterationContext.this.checkOnEachPublicOperation(); - return cachedEntryKey(); - } - - @Override - public K getUsing(K usingKey) { - CompiledReplicatedMapIterationContext.this.checkOnEachPublicOperation(); - return innerGetUsing(usingKey); - } - } - - public class EntryValueBytesData extends AbstractData { - @Override - public RandomDataInput bytes() { - CompiledReplicatedMapIterationContext.this.checkOnEachPublicOperation(); - return CompiledReplicatedMapIterationContext.this.entryBS; - } - - @Override - public long offset() { - CompiledReplicatedMapIterationContext.this.checkOnEachPublicOperation(); - return CompiledReplicatedMapIterationContext.this.valueOffset(); - } - - @Override - public long size() { - CompiledReplicatedMapIterationContext.this.checkOnEachPublicOperation(); - return CompiledReplicatedMapIterationContext.this.valueSize(); - } - - public void closeEntryValueBytesDataSizeDependants() { - this.closeEntryValueBytesDataInnerGetUsingDependants(); - } - - private V innerGetUsing(V usingValue) { - CompiledReplicatedMapIterationContext.this.entryBytes.position(CompiledReplicatedMapIterationContext.this.valueOffset()); - return CompiledReplicatedMapIterationContext.this.valueReader.read(CompiledReplicatedMapIterationContext.this.entryBytes, size(), usingValue); - } - - public void closeEntryValueBytesDataInnerGetUsingDependants() { - this.closeCachedEntryValue(); - } - - @Override - public V getUsing(V usingValue) { - CompiledReplicatedMapIterationContext.this.checkOnEachPublicOperation(); - return innerGetUsing(usingValue); - } - - private V cachedEntryValue; - - private boolean cachedEntryValueRead = false; - - public boolean cachedEntryValueInit() { - return (this.cachedEntryValueRead) != false; - } - - private void initCachedEntryValue() { - cachedEntryValue = innerGetUsing(cachedEntryValue); - cachedEntryValueRead = true; - } - - public V cachedEntryValue() { - if (!(this.cachedEntryValueInit())) - this.initCachedEntryValue(); - - return this.cachedEntryValue; - } - - public void closeCachedEntryValue() { - if (!(this.cachedEntryValueInit())) - return ; - - this.cachedEntryValueRead = false; - } - - @Override - public V get() { - CompiledReplicatedMapIterationContext.this.checkOnEachPublicOperation(); - return cachedEntryValue(); - } - } - - public class ReadLock implements InterProcessLock { - @Override - public void lockInterruptibly() throws InterruptedException { - if ((CompiledReplicatedMapIterationContext.this.localLockState()) == (LocalLockState.UNLOCKED)) { - CompiledReplicatedMapIterationContext.this.segmentHeader().readLockInterruptibly(CompiledReplicatedMapIterationContext.this.segmentHeaderAddress()); - CompiledReplicatedMapIterationContext.this.setLocalLockStateGuarded(LocalLockState.READ_LOCKED); - } - } - - @Override - public void lock() { - if ((CompiledReplicatedMapIterationContext.this.localLockState()) == (LocalLockState.UNLOCKED)) { - CompiledReplicatedMapIterationContext.this.segmentHeader().readLock(CompiledReplicatedMapIterationContext.this.segmentHeaderAddress()); - CompiledReplicatedMapIterationContext.this.setLocalLockStateGuarded(LocalLockState.READ_LOCKED); - } - } - - @Override - public boolean isHeldByCurrentThread() { - return CompiledReplicatedMapIterationContext.this.localLockState().read; - } - - @Override - public void unlock() { - switch (CompiledReplicatedMapIterationContext.this.localLockState()) { - case UNLOCKED : - return ; - case READ_LOCKED : - CompiledReplicatedMapIterationContext.this.segmentHeader().readUnlock(CompiledReplicatedMapIterationContext.this.segmentHeaderAddress()); - break; - case UPDATE_LOCKED : - CompiledReplicatedMapIterationContext.this.segmentHeader().updateUnlock(CompiledReplicatedMapIterationContext.this.segmentHeaderAddress()); - break; - case WRITE_LOCKED : - CompiledReplicatedMapIterationContext.this.segmentHeader().writeUnlock(CompiledReplicatedMapIterationContext.this.segmentHeaderAddress()); - } - CompiledReplicatedMapIterationContext.this.setLocalLockStateGuarded(LocalLockState.UNLOCKED); - CompiledReplicatedMapIterationContext.this.closeHashLookupPos(); - CompiledReplicatedMapIterationContext.this.closePos(); - } - - @Override - public boolean tryLock(long time, @NotNull - TimeUnit unit) throws InterruptedException { - if ((CompiledReplicatedMapIterationContext.this.localLockState()) == (LocalLockState.UNLOCKED)) { - if (CompiledReplicatedMapIterationContext.this.segmentHeader().tryReadLock(CompiledReplicatedMapIterationContext.this.segmentHeaderAddress(), time, unit)) { - CompiledReplicatedMapIterationContext.this.setLocalLockStateGuarded(LocalLockState.READ_LOCKED); - return true; - } else { - return false; - } - } else { - return true; - } - } - - @Override - public boolean tryLock() { - if ((CompiledReplicatedMapIterationContext.this.localLockState()) == (LocalLockState.UNLOCKED)) { - if (CompiledReplicatedMapIterationContext.this.segmentHeader().tryReadLock(CompiledReplicatedMapIterationContext.this.segmentHeaderAddress())) { - CompiledReplicatedMapIterationContext.this.setLocalLockStateGuarded(LocalLockState.READ_LOCKED); - return true; - } else { - return false; - } - } else { - return true; - } - } - } - - public class UpdateLock implements InterProcessLock { - @NotNull - private IllegalMonitorStateException forbiddenUpgrade() { - return new IllegalMonitorStateException("Cannot upgrade from read to update lock"); - } - - @Override - public void lockInterruptibly() throws InterruptedException { - switch (CompiledReplicatedMapIterationContext.this.localLockState()) { - case UNLOCKED : - CompiledReplicatedMapIterationContext.this.segmentHeader().updateLockInterruptibly(CompiledReplicatedMapIterationContext.this.segmentHeaderAddress()); - CompiledReplicatedMapIterationContext.this.setLocalLockStateGuarded(LocalLockState.UPDATE_LOCKED); - return ; - case READ_LOCKED : - throw forbiddenUpgrade(); - case UPDATE_LOCKED : - case WRITE_LOCKED : - } - } - - @Override - public boolean isHeldByCurrentThread() { - return CompiledReplicatedMapIterationContext.this.localLockState().update; - } - - @Override - public void unlock() { - switch (CompiledReplicatedMapIterationContext.this.localLockState()) { - case UNLOCKED : - case READ_LOCKED : - return ; - case UPDATE_LOCKED : - CompiledReplicatedMapIterationContext.this.segmentHeader().downgradeUpdateToReadLock(CompiledReplicatedMapIterationContext.this.segmentHeaderAddress()); - break; - case WRITE_LOCKED : - CompiledReplicatedMapIterationContext.this.segmentHeader().downgradeWriteToReadLock(CompiledReplicatedMapIterationContext.this.segmentHeaderAddress()); - } - CompiledReplicatedMapIterationContext.this.setLocalLockStateGuarded(LocalLockState.READ_LOCKED); - } - - @Override - public void lock() { - switch (CompiledReplicatedMapIterationContext.this.localLockState()) { - case UNLOCKED : - CompiledReplicatedMapIterationContext.this.segmentHeader().updateLock(CompiledReplicatedMapIterationContext.this.segmentHeaderAddress()); - CompiledReplicatedMapIterationContext.this.setLocalLockStateGuarded(LocalLockState.UPDATE_LOCKED); - return ; - case READ_LOCKED : - throw forbiddenUpgrade(); - case UPDATE_LOCKED : - case WRITE_LOCKED : - } - } - - @Override - public boolean tryLock(long time, @NotNull - TimeUnit unit) throws InterruptedException { - switch (CompiledReplicatedMapIterationContext.this.localLockState()) { - case UNLOCKED : - if (CompiledReplicatedMapIterationContext.this.segmentHeader().tryUpdateLock(CompiledReplicatedMapIterationContext.this.segmentHeaderAddress(), time, unit)) { - CompiledReplicatedMapIterationContext.this.setLocalLockStateGuarded(LocalLockState.UPDATE_LOCKED); - return true; - } else { - return false; - } - case READ_LOCKED : - throw forbiddenUpgrade(); - case UPDATE_LOCKED : - case WRITE_LOCKED : - return true; - } - throw new AssertionError(); - } - - @Override - public boolean tryLock() { - switch (CompiledReplicatedMapIterationContext.this.localLockState()) { - case UNLOCKED : - if (CompiledReplicatedMapIterationContext.this.segmentHeader().tryUpdateLock(CompiledReplicatedMapIterationContext.this.segmentHeaderAddress())) { - CompiledReplicatedMapIterationContext.this.setLocalLockStateGuarded(LocalLockState.UPDATE_LOCKED); - return true; - } else { - return false; - } - case READ_LOCKED : - throw forbiddenUpgrade(); - case UPDATE_LOCKED : - case WRITE_LOCKED : - return true; - } - throw new AssertionError(); - } - } - - public class WrappedValueInstanceData extends CopyingInstanceData { - public WrappedValueInstanceData getUnusedWrappedValueGuarded() { - assert this.nextInit() : "Next should be init"; - return getUnusedWrappedValue(); - } - - public WrappedValueInstanceData getUnusedWrappedValue() { - if (!(valueInit())) - return this; - - if ((next) == null) - next = new WrappedValueInstanceData(); - - return next.getUnusedWrappedValue(); - } - - private WrappedValueInstanceData next; - - boolean nextInit() { - return true; - } - - void closeNext() { - if (!(this.nextInit())) - return ; - - } - - private V value; - - public boolean valueInit() { - return (value) != null; - } - - public void initValue(V value) { - CompiledReplicatedMapIterationContext.this.m().checkValue(value); - this.value = value; - this.closeValueDependants(); - } - - public V value() { - assert this.valueInit() : "Value should be init"; - return this.value; - } - - public void closeValue() { - if (!(this.valueInit())) - return ; - - this.closeValueDependants(); - value = null; - if ((next) != null) - next.closeValue(); - - } - - public void closeValueDependants() { - this.closeBuffer(); - } - - @Override - public V instance() { - return value(); - } - - private boolean marshalled = false; - - private DirectBytes buf; - - public boolean bufferInit() { - return (this.marshalled) != false; - } - - private void initBuffer() { - MVI mvi = CompiledReplicatedMapIterationContext.this.valueMetaInterop(value()); - long size = mvi.size(CompiledReplicatedMapIterationContext.this.valueInterop, value()); - buf = getBuffer(this.buf, size); - mvi.write(CompiledReplicatedMapIterationContext.this.valueInterop, buf, value()); - buf.flip(); - marshalled = true; - } - - public DirectBytes buf() { - if (!(this.bufferInit())) - this.initBuffer(); - - return this.buf; - } - - public void closeBuffer() { - if (!(this.bufferInit())) - return ; - - this.marshalled = false; - } - - @Override - public V getUsing(V usingValue) { - buf().position(0); - return CompiledReplicatedMapIterationContext.this.valueReader.read(buf(), buf().limit(), usingValue); - } - - @Override - public DirectBytes buffer() { - return buf(); - } - } - - public class WriteLock implements InterProcessLock { - @NotNull - private IllegalMonitorStateException forbiddenUpgrade() { - return new IllegalMonitorStateException("Cannot upgrade from read to write lock"); - } - - @Override - public boolean tryLock(long time, @NotNull - TimeUnit unit) throws InterruptedException { - switch (CompiledReplicatedMapIterationContext.this.localLockState()) { - case UNLOCKED : - if (CompiledReplicatedMapIterationContext.this.segmentHeader().tryWriteLock(CompiledReplicatedMapIterationContext.this.segmentHeaderAddress(), time, unit)) { - CompiledReplicatedMapIterationContext.this.setLocalLockStateGuarded(LocalLockState.WRITE_LOCKED); - return true; - } else { - return false; - } - case READ_LOCKED : - throw forbiddenUpgrade(); - case UPDATE_LOCKED : - if (CompiledReplicatedMapIterationContext.this.segmentHeader().tryUpgradeUpdateToWriteLock(CompiledReplicatedMapIterationContext.this.segmentHeaderAddress(), time, unit)) { - CompiledReplicatedMapIterationContext.this.setLocalLockStateGuarded(LocalLockState.WRITE_LOCKED); - return true; - } else { - return false; - } - case WRITE_LOCKED : - return true; - } - throw new AssertionError(); - } - - @Override - public boolean tryLock() { - switch (CompiledReplicatedMapIterationContext.this.localLockState()) { - case UNLOCKED : - if (CompiledReplicatedMapIterationContext.this.segmentHeader().tryWriteLock(CompiledReplicatedMapIterationContext.this.segmentHeaderAddress())) { - CompiledReplicatedMapIterationContext.this.setLocalLockStateGuarded(LocalLockState.WRITE_LOCKED); - return true; - } else { - return false; - } - case READ_LOCKED : - throw forbiddenUpgrade(); - case UPDATE_LOCKED : - if (CompiledReplicatedMapIterationContext.this.segmentHeader().tryUpgradeUpdateToWriteLock(CompiledReplicatedMapIterationContext.this.segmentHeaderAddress())) { - CompiledReplicatedMapIterationContext.this.setLocalLockStateGuarded(LocalLockState.WRITE_LOCKED); - return true; - } else { - return false; - } - case WRITE_LOCKED : - return true; - } - throw new AssertionError(); - } - - @Override - public void lockInterruptibly() throws InterruptedException { - switch (CompiledReplicatedMapIterationContext.this.localLockState()) { - case UNLOCKED : - CompiledReplicatedMapIterationContext.this.segmentHeader().writeLockInterruptibly(CompiledReplicatedMapIterationContext.this.segmentHeaderAddress()); - CompiledReplicatedMapIterationContext.this.setLocalLockStateGuarded(LocalLockState.WRITE_LOCKED); - return ; - case READ_LOCKED : - throw forbiddenUpgrade(); - case UPDATE_LOCKED : - CompiledReplicatedMapIterationContext.this.segmentHeader().upgradeUpdateToWriteLockInterruptibly(CompiledReplicatedMapIterationContext.this.segmentHeaderAddress()); - CompiledReplicatedMapIterationContext.this.setLocalLockStateGuarded(LocalLockState.WRITE_LOCKED); - case WRITE_LOCKED : - } - } - - @Override - public void unlock() { - switch (CompiledReplicatedMapIterationContext.this.localLockState()) { - case UNLOCKED : - case READ_LOCKED : - case UPDATE_LOCKED : - return ; - case WRITE_LOCKED : - CompiledReplicatedMapIterationContext.this.segmentHeader().downgradeWriteToUpdateLock(CompiledReplicatedMapIterationContext.this.segmentHeaderAddress()); - } - CompiledReplicatedMapIterationContext.this.setLocalLockStateGuarded(LocalLockState.UPDATE_LOCKED); - } - - @Override - public boolean isHeldByCurrentThread() { - return CompiledReplicatedMapIterationContext.this.localLockState().write; - } - - @Override - public void lock() { - switch (CompiledReplicatedMapIterationContext.this.localLockState()) { - case UNLOCKED : - CompiledReplicatedMapIterationContext.this.segmentHeader().writeLock(CompiledReplicatedMapIterationContext.this.segmentHeaderAddress()); - CompiledReplicatedMapIterationContext.this.setLocalLockStateGuarded(LocalLockState.WRITE_LOCKED); - return ; - case READ_LOCKED : - throw forbiddenUpgrade(); - case UPDATE_LOCKED : - CompiledReplicatedMapIterationContext.this.segmentHeader().upgradeUpdateToWriteLock(CompiledReplicatedMapIterationContext.this.segmentHeaderAddress()); - CompiledReplicatedMapIterationContext.this.setLocalLockStateGuarded(LocalLockState.WRITE_LOCKED); - case WRITE_LOCKED : - } - } - } - - private void _CheckOnEachPublicOperation_checkOnEachPublicOperation() { - this.checkAccessingFromOwnerThread(); - } - - private void _MapEntryStages_putValueDeletedEntry(Data newValue) { - assert this.innerUpdateLock.isHeldByCurrentThread(); - int newSizeInChunks; - long entryStartOffset = keySizeOffset(); - long newSizeOfEverythingBeforeValue = -1; - boolean newValueSizeIsDifferent = (newValue.size()) != (valueSize()); - if (newValueSizeIsDifferent) { - newSizeOfEverythingBeforeValue = newSizeOfEverythingBeforeValue(newValue); - long newValueOffset = this.m().alignment.alignAddr((entryStartOffset + newSizeOfEverythingBeforeValue)); - long newEntrySize = (newValueOffset + (newValue.size())) - entryStartOffset; - newSizeInChunks = this.m().inChunks(newEntrySize); - } else { - newSizeInChunks = entrySizeInChunks(); - } - if ((((pos()) + newSizeInChunks) < (this.freeList().size())) && (this.freeList().allClear(pos(), ((pos()) + newSizeInChunks)))) { - this.freeList().set(pos(), ((pos()) + newSizeInChunks)); - this.innerWriteLock.lock(); - this.incrementSegmentEntriesIfNeeded(); - if (newValueSizeIsDifferent) { - initValue(newValue); - } else { - writeValue(newValue); - } - } else { - if (newValueSizeIsDifferent) { - assert newSizeOfEverythingBeforeValue >= 0; - } else { - newSizeOfEverythingBeforeValue = newSizeOfEverythingBeforeValue(newValue); - } - long entrySize = innerEntrySize(newSizeOfEverythingBeforeValue, newValue.size()); - if (newValueSizeIsDifferent) { - this.initEntryAndKeyCopying(entrySize, ((valueSizeOffset()) - entryStartOffset)); - initValue(newValue); - } else { - long oldValueSizeOffset = valueSizeOffset(); - long oldValueSize = valueSize(); - long oldValueOffset = valueOffset(); - this.initEntryAndKeyCopying(entrySize, ((valueOffset()) - entryStartOffset)); - initValueWithoutSize(newValue, oldValueSizeOffset, oldValueSize, oldValueOffset); - } - freeExtraAllocatedChunks(); - } - this.putValueVolatile(this.hashLookupPos(), pos()); - } - - private void _MapSegmentIteration_doRemove() { - this.checkOnEachPublicOperation(); - initEntryRemovedOnThisIteration(true); - this.innerWriteLock.lock(); - try { - if ((this.remove(this.hashLookupPos())) != (this.hashLookupPos())) { - this.setHashLookupPosGuarded(this.stepBack(this.hashLookupPos())); - } - this.innerRemoveEntryExceptHashLookupUpdate(); - } finally { - this.innerWriteLock.unlock(); - } - } - - private void _MapSegmentIteration_doReplaceValue(Data newValue) { - this.checkOnEachPublicOperation(); - try { - this.innerDefaultReplaceValue(newValue); - } finally { - this.innerWriteLock.unlock(); - } - } - - public void incrementModCount() { - contextModCount = rootContextOnThisSegment.latestSameThreadSegmentModCount = (rootContextOnThisSegment.latestSameThreadSegmentModCount) + 1; - } - - public void setHashLookupPos(long hashLookupPos) { - this.hashLookupPos = hashLookupPos; - } - - public void setLocalLockState(LocalLockState newState) { - localLockState = newState; - } - - final Thread owner; - - public Thread owner() { - return this.owner; - } - - private void closeNestedLocks() { - unlinkFromSegmentContextsChain(); - switch (localLockState) { - case UNLOCKED : - break; - case READ_LOCKED : - int newTotalReadLockCount = this.rootContextOnThisSegment.totalReadLockCount -= 1; - if (newTotalReadLockCount == 0) { - if (((this.rootContextOnThisSegment.totalUpdateLockCount) == 0) && ((this.rootContextOnThisSegment.totalWriteLockCount) == 0)) { - segmentHeader().readUnlock(segmentHeaderAddress()); - } - } else if (newTotalReadLockCount < 0) { - throw new IllegalStateException("read underflow"); - } - break; - case UPDATE_LOCKED : - int newTotalUpdateLockCount = this.rootContextOnThisSegment.totalUpdateLockCount -= 1; - if (newTotalUpdateLockCount == 0) { - if ((this.rootContextOnThisSegment.totalWriteLockCount) == 0) { - if ((this.rootContextOnThisSegment.totalReadLockCount) == 0) { - segmentHeader().updateUnlock(segmentHeaderAddress()); - } else { - segmentHeader().downgradeUpdateToReadLock(segmentHeaderAddress()); - } - } - } else if (newTotalUpdateLockCount < 0) { - throw new IllegalStateException("update underflow"); - } - break; - case WRITE_LOCKED : - int newTotalWriteLockCount = this.rootContextOnThisSegment.totalWriteLockCount -= 1; - if (newTotalWriteLockCount == 0) { - if ((this.rootContextOnThisSegment.totalUpdateLockCount) > 0) { - segmentHeader().downgradeWriteToUpdateLock(segmentHeaderAddress()); - } else { - if ((this.rootContextOnThisSegment.totalReadLockCount) > 0) { - segmentHeader().downgradeWriteToReadLock(segmentHeaderAddress()); - } else { - segmentHeader().writeUnlock(segmentHeaderAddress()); - } - } - } - break; - } - } - - private void closeRootLocks() { - assert (nextNode) == null; - switch (localLockState) { - case UNLOCKED : - return ; - case READ_LOCKED : - segmentHeader().readUnlock(segmentHeaderAddress()); - return ; - case UPDATE_LOCKED : - segmentHeader().updateUnlock(segmentHeaderAddress()); - return ; - case WRITE_LOCKED : - segmentHeader().writeUnlock(segmentHeaderAddress()); - } - } - - private void innerInitSegmentHashLookup(long address, long capacity, int entrySize, int keyBits, int valueBits) { - this.address = address; - this.capacityMask = capacity - 1L; - this.hashLookupEntrySize = entrySize; - this.capacityMask2 = (capacityMask) * entrySize; - this.keyBits = keyBits; - this.keyMask = CompiledReplicatedMapIterationContext.mask(keyBits); - this.valueMask = CompiledReplicatedMapIterationContext.mask(valueBits); - this.entryMask = CompiledReplicatedMapIterationContext.mask((keyBits + valueBits)); - } - - private void unlinkFromSegmentContextsChain() { - CompiledReplicatedMapIterationContext prevContext = this.rootContextOnThisSegment; - while (true) { - assert (prevContext.nextNode) != null; - if ((prevContext.nextNode) == (this)) - break; - - prevContext = prevContext.nextNode; - } - assert (nextNode) == null; - prevContext.nextNode = null; - } - - private boolean _MapSegmentIteration_entryIsPresent() { - return true; - } - - private long _HashEntryStages_entryEnd() { - return keyEnd(); - } - - private void _MapEntryStages_relocation(Data newValue, long newSizeOfEverythingBeforeValue) { - this.free(pos(), entrySizeInChunks()); - long entrySize = innerEntrySize(newSizeOfEverythingBeforeValue, newValue.size()); - this.initEntryAndKeyCopying(entrySize, ((valueSizeOffset()) - (keySizeOffset()))); - writeValueAndPutPos(newValue); - } - - private CompiledReplicatedMapIterationContext _Chaining_createChaining() { - return new CompiledReplicatedMapIterationContext(this); - } - - public final int indexInContextChain; - - public int indexInContextChain() { - return this.indexInContextChain; - } - - public static int entrySize(int keyBits, int valueBits) { - return ((int)(MemoryUnit.BYTES.alignAndConvert(((long)(keyBits + valueBits)), MemoryUnit.BITS))); - } - - public static int keyBits(long entriesPerSegment, int valueBits) { - int minKeyBits = 64 - (Long.numberOfLeadingZeros((entriesPerSegment - 1L))); - minKeyBits += 3; - int actualEntryBits = ((int)(MemoryUnit.BYTES.align(((long)(minKeyBits + valueBits)), MemoryUnit.BITS))); - return actualEntryBits - valueBits; - } - - public static int valueBits(long actualChunksPerSegment) { - return 64 - (Long.numberOfLeadingZeros((actualChunksPerSegment - 1L))); - } - - public final Bytes entryBytes; - - public Bytes entryBytes() { - return this.entryBytes; - } - - public static long capacityFor(long entriesPerSegment) { - if (entriesPerSegment < 0L) - throw new IllegalArgumentException("entriesPerSegment should be positive"); - - long capacity = Maths.nextPower2(entriesPerSegment, 64L); - if ((((double)(entriesPerSegment)) / ((double)(capacity))) > (2.0 / 3.0)) { - capacity <<= 1L; - } - return capacity; - } - - public static long mask(int bits) { - return (1L << bits) - 1L; - } - - public static final int MAX_SEGMENT_CHUNKS = 1 << 30; - - public static final int MAX_SEGMENT_ENTRIES = 1 << 29; - - public int MAX_SEGMENT_ENTRIES() { - return this.MAX_SEGMENT_ENTRIES; - } - - public int MAX_SEGMENT_CHUNKS() { - return this.MAX_SEGMENT_CHUNKS; - } - - public static final long UNSET_KEY = 0L; - - public static final long UNSET_ENTRY = 0L; - - public long UNSET_ENTRY() { - return this.UNSET_ENTRY; - } - - public long UNSET_KEY() { - return this.UNSET_KEY; - } - - public final ReadLock innerReadLock; - - public ReadLock innerReadLock() { - return this.innerReadLock; - } - - public final WriteLock innerWriteLock; - - public WriteLock innerWriteLock() { - return this.innerWriteLock; - } - - public final List contextChain; - - public final UpdateLock innerUpdateLock; - - public UpdateLock innerUpdateLock() { - return this.innerUpdateLock; - } - - public List contextChain() { - return this.contextChain; - } - - public final ThreadLocalCopies copies; - - final EntryKeyBytesData entryKey; - - public EntryKeyBytesData entryKey() { - return this.entryKey; - } - - public ThreadLocalCopies copies() { - return this.copies; - } - - private void countValueOffset() { - this.m().alignment.alignPositionAddr(entryBytes); - valueOffset = entryBytes.position(); - } - - final DummyValueZeroData dummyValue; - - public DummyValueZeroData dummyValue() { - return this.dummyValue; - } - - public final EntryValueBytesData entryValue; - - public EntryValueBytesData entryValue() { - return this.entryValue; - } - - final WrappedValueInstanceData wrappedValueInstanceValue; - - public WrappedValueInstanceData wrappedValueInstanceValue() { - return this.wrappedValueInstanceValue; - } - - public final DeprecatedMapKeyContextOnIteration deprecatedMapKeyContextOnIteration; - - public DeprecatedMapKeyContextOnIteration deprecatedMapKeyContextOnIteration() { - return this.deprecatedMapKeyContextOnIteration; - } - - private final ReplicatedChronicleMap m; - - public final VI valueInterop; - - public VI valueInterop() { - return this.valueInterop; - } - - public final BytesStore entryBS; - - public BytesStore entryBS() { - return this.entryBS; - } - - public final BytesReader valueReader; - - public BytesReader valueReader() { - return this.valueReader; - } - - public final KI keyInterop; - - public KI keyInterop() { - return this.keyInterop; - } - - public final BytesReader keyReader; - - public BytesReader keyReader() { - return this.keyReader; - } - - @Override - public ReplicatedChronicleMap m() { - return m; - } - - @Override - public ChronicleMap map() { - return m(); - } - - public void checkEntryNotRemovedOnThisIteration() { - if (entryRemovedOnThisIterationInit()) - throw new IllegalStateException("Entry was already removed on this iteration"); - - } - - public void closeReplicatedMapSegmentIterationCheckEntryNotRemovedOnThisIterationDependants() { - this.closeIterationCheckOnEachPublicOperationCheckOnEachPublicOperationDependants(); - } - - long sizeOfEverythingBeforeValue(long keySize, long valueSize) { - return (_MapEntryStages_sizeOfEverythingBeforeValue(keySize, valueSize)) + (ReplicatedChronicleMap.ADDITIONAL_ENTRY_BYTES); - } - - @NotNull - @Override - public MapContext context() { - return this; - } - - public MVI valueMetaInterop(V value) { - return this.m().metaValueInteropProvider.get(this.copies, this.m().originalMetaValueInterop, valueInterop, value); - } - - public void closeValueBytesInteropValueMetaInteropDependants() { - this.wrappedValueInstanceValue.closeBuffer(); - } - - public long innerEntrySize(long sizeOfEverythingBeforeValue, long valueSize) { - if (this.m().constantlySizedEntry) { - return this.m().alignment.alignAddr((sizeOfEverythingBeforeValue + valueSize)); - } else if (this.m().couldNotDetermineAlignmentBeforeAllocation) { - return (sizeOfEverythingBeforeValue + (this.m().worstAlignment)) + valueSize; - } else { - return (this.m().alignment.alignAddr(sizeOfEverythingBeforeValue)) + valueSize; - } - } - - public final long entrySize(long keySize, long valueSize) { - long sizeOfEverythingBeforeValue = sizeOfEverythingBeforeValue(keySize, valueSize); - return innerEntrySize(sizeOfEverythingBeforeValue, valueSize); - } - - public void checkAccessingFromOwnerThread() { - if ((owner) != (Thread.currentThread())) { - throw new ConcurrentModificationException("Context shouldn\'t be accessed from multiple threads"); - } - } - - public void closeOwnerThreadHolderCheckAccessingFromOwnerThreadDependants() { - this.closeIterationCheckOnEachPublicOperationCheckOnEachPublicOperationDependants(); - } - - public void checkOnEachPublicOperation() { - _CheckOnEachPublicOperation_checkOnEachPublicOperation(); - this.checkEntryNotRemovedOnThisIteration(); - } - - public void closeIterationCheckOnEachPublicOperationCheckOnEachPublicOperationDependants() { - this.entryValue.closeEntryValueBytesDataSizeDependants(); - this.entryKey.closeEntryKeyBytesDataSizeDependants(); - } - - @NotNull - @Override - public InterProcessLock updateLock() { - this.checkOnEachPublicOperation(); - return this.innerUpdateLock; - } - - @Override - public R replaceValue(@NotNull - MapEntry entry, Data newValue) { - this.checkOnEachPublicOperation(); - return this.m().entryOperations.replaceValue(entry, newValue); - } - - @Override - public Data wrapValueAsValue(V value) { - this.checkOnEachPublicOperation(); - WrappedValueInstanceData wrapped = this.wrappedValueInstanceValue; - wrapped = wrapped.getUnusedWrappedValueGuarded(); - wrapped.initValue(value); - return wrapped; - } - - @NotNull - @Override - public InterProcessLock writeLock() { - this.checkOnEachPublicOperation(); - return this.innerWriteLock; - } - - @NotNull - @Override - public Data value() { - this.checkOnEachPublicOperation(); - return this.entryValue; - } - - @NotNull - @Override - public Data key() { - this.checkOnEachPublicOperation(); - return this.entryKey; - } - - @Override - public Data defaultValue(@NotNull - MapAbsentEntry absentEntry) { - this.checkOnEachPublicOperation(); - return this.m().entryOperations.defaultValue(absentEntry); - } - - @Override - public R remove(@NotNull - MapEntry entry) { - this.checkOnEachPublicOperation(); - return this.m().entryOperations.remove(entry); - } - - @NotNull - @Override - public InterProcessLock readLock() { - this.checkOnEachPublicOperation(); - return this.innerReadLock; - } - - @Override - public R insert(@NotNull - MapAbsentEntry absentEntry, Data value) { - this.checkOnEachPublicOperation(); - return this.m().entryOperations.insert(absentEntry, value); - } - - public CompiledReplicatedMapIterationContext createChaining() { - return new CompiledReplicatedMapIterationContext(this); - } - - public T getContext() { - for (CompiledReplicatedMapIterationContext context : contextChain) { - if (!(context.usedInit())) { - return ((T)(context)); - } - } - int maxNestedContexts = 1 << 16; - if ((contextChain.size()) > maxNestedContexts) { - throw new IllegalStateException((((((("More than " + maxNestedContexts) + " nested ChronicleHash contexts are not supported. Very probable that ") + "you simply forgot to close context somewhere (recommended to use ") + "try-with-resources statement). ") + "Otherwise this is a bug, please report with this ") + "stack trace on https://github.com/OpenHFT/Chronicle-Map/issues")); - } - return ((T)(createChaining())); - } - - public void incrementSegmentEntriesIfNeeded() { - } - - public T contextAtIndexInChain(int index) { - return ((T)(contextChain.get(index))); - } - - public void closeReplicatedChronicleMapHolderImplContextAtIndexInChainDependants() { - this.closeSegmentStagesTryFindInitLocksOfThisSegmentDependants(); - } - - public MKI keyMetaInterop(K key) { - return this.h().metaKeyInteropProvider.get(this.copies, this.h().originalMetaKeyInterop, keyInterop, key); - } - - public long keyOffset = -1; - - public boolean keyOffsetInit() { - return (this.keyOffset) >= 0; - } - - public void initKeyOffset(long keyOffset) { - this.keyOffset = keyOffset; - this.closeKeyOffsetDependants(); - } - - public long keyOffset() { - assert this.keyOffsetInit() : "KeyOffset should be init"; - return this.keyOffset; - } - - public void closeKeyOffset() { - if (!(this.keyOffsetInit())) - return ; - - this.closeKeyOffsetDependants(); - this.keyOffset = -1; - } - - public void closeKeyOffsetDependants() { - this.closeReplicatedMapEntryStagesKeyEndDependants(); - this.entryKey.closeEntryKeyBytesDataInnerGetUsingDependants(); - } - - public long hashLookupPos = -1; - - public boolean hashLookupPosInit() { - return (this.hashLookupPos) >= 0; - } - - public void initHashLookupPos(long hashLookupPos) { - this.hashLookupPos = hashLookupPos; - } - - public long hashLookupPos() { - assert this.hashLookupPosInit() : "HashLookupPos should be init"; - return this.hashLookupPos; - } - - public void closeHashLookupPos() { - if (!(this.hashLookupPosInit())) - return ; - - this.hashLookupPos = -1; - } - - public int allocatedChunks = 0; - - public boolean allocatedChunksInit() { - return (this.allocatedChunks) != 0; - } - - public void initAllocatedChunks(int allocatedChunks) { - this.allocatedChunks = allocatedChunks; - } - - public int allocatedChunks() { - assert this.allocatedChunksInit() : "AllocatedChunks should be init"; - return this.allocatedChunks; - } - - public void closeAllocatedChunks() { - if (!(this.allocatedChunksInit())) - return ; - - this.allocatedChunks = 0; - } - - public long innerRemoteTimestamp; - - public byte innerRemoteIdentifier = ((byte)(0)); - - public boolean replicationUpdateInit() { - return (this.innerRemoteIdentifier) != ((byte)(0)); - } - - public void initReplicationUpdate(long timestamp, byte identifier) { - innerRemoteTimestamp = timestamp; - if (identifier == 0) - throw new IllegalStateException("identifier can\'t be 0"); - - innerRemoteIdentifier = identifier; - } - - public byte innerRemoteIdentifier() { - assert this.replicationUpdateInit() : "ReplicationUpdate should be init"; - return this.innerRemoteIdentifier; - } - - public long innerRemoteTimestamp() { - assert this.replicationUpdateInit() : "ReplicationUpdate should be init"; - return this.innerRemoteTimestamp; - } - - public void closeReplicationUpdate() { - if (!(this.replicationUpdateInit())) - return ; - - this.innerRemoteIdentifier = ((byte)(0)); - } - - @Override - public long remoteTimestamp() { - this.checkOnEachPublicOperation(); - return innerRemoteTimestamp(); - } - - @Override - public byte remoteIdentifier() { - this.checkOnEachPublicOperation(); - return innerRemoteIdentifier(); - } - - public long pos = -1; - - public boolean posInit() { - return (this.pos) >= 0; - } - - public void initPos(long pos) { - this.pos = pos; - this.closePosDependants(); - } - - public long pos() { - assert this.posInit() : "Pos should be init"; - return this.pos; - } - - public void closePos() { - if (!(this.posInit())) - return ; - - this.closePosDependants(); - this.pos = -1; - } - - public void closePosDependants() { - this.closeEntryOffset(); - } - - public long keySize = -1; - - public boolean keySizeInit() { - return (this.keySize) >= 0; - } - - public void initKeySize(long keySize) { - this.keySize = keySize; - this.closeKeySizeDependants(); - } - - public long keySize() { - assert this.keySizeInit() : "KeySize should be init"; - return this.keySize; - } - - public void closeKeySize() { - if (!(this.keySizeInit())) - return ; - - this.closeKeySizeDependants(); - this.keySize = -1; - } - - public void closeKeySizeDependants() { - this.closeReplicatedMapEntryStagesKeyEndDependants(); - this.entryKey.closeEntryKeyBytesDataSizeDependants(); - } - - public long keyEnd() { - return (keyOffset()) + (keySize()); - } - - public void closeReplicatedMapEntryStagesKeyEndDependants() { - this.closeReplicatedMapEntryStagesCountValueSizeOffsetDependants(); - this.closeReplicationState(); - this.closeReplicatedMapEntryStagesEntryEndDependants(); - } - - long countValueSizeOffset() { - return (_MapEntryStages_countValueSizeOffset()) + (ReplicatedChronicleMap.ADDITIONAL_ENTRY_BYTES); - } - - public void closeReplicatedMapEntryStagesCountValueSizeOffsetDependants() { - this.closeValueSizeOffset(); - } - - public long valueSizeOffset = -1; - - public boolean valueSizeOffsetInit() { - return (this.valueSizeOffset) >= 0; - } - - void initValueSizeOffset() { - valueSizeOffset = countValueSizeOffset(); - this.closeValueSizeOffsetDependants(); - } - - public long valueSizeOffset() { - if (!(this.valueSizeOffsetInit())) - this.initValueSizeOffset(); - - return this.valueSizeOffset; - } - - public void closeValueSizeOffset() { - if (!(this.valueSizeOffsetInit())) - return ; - - this.closeValueSizeOffsetDependants(); - this.valueSizeOffset = -1; - } - - public void closeValueSizeOffsetDependants() { - this.closeValSize(); - } - - public long valueSize = -1; - - public long valueOffset; - - public boolean valSizeInit() { - return (this.valueSize) >= 0; - } - - void initValSize() { - entryBytes.position(valueSizeOffset()); - valueSize = this.m().readValueSize(entryBytes); - countValueOffset(); - this.closeValSizeDependants(); - } - - void initValSize(long valueSize) { - this.valueSize = valueSize; - entryBytes.position(valueSizeOffset()); - this.m().valueSizeMarshaller.writeSize(entryBytes, valueSize); - countValueOffset(); - this.closeValSizeDependants(); - } - - void initValSizeEqualToOld(long oldValueSizeOffset, long oldValueSize, long oldValueOffset) { - valueSize = oldValueSize; - valueOffset = (valueSizeOffset()) + (oldValueOffset - oldValueSizeOffset); - this.closeValSizeDependants(); - } - - public long valueOffset() { - if (!(this.valSizeInit())) - this.initValSize(); - - return this.valueOffset; - } - - public long valueSize() { - if (!(this.valSizeInit())) - this.initValSize(); - - return this.valueSize; - } - - public void closeValSize() { - if (!(this.valSizeInit())) - return ; - - this.closeValSizeDependants(); - this.valueSize = -1; - } - - public void closeValSizeDependants() { - this.closeReplicatedMapEntryStagesEntryEndDependants(); - this.entryValue.closeEntryValueBytesDataSizeDependants(); - this.entryValue.closeEntryValueBytesDataInnerGetUsingDependants(); - } - - public void writeValue(Data value) { - value.writeTo(entryBS, valueOffset()); - } - - public void initValueWithoutSize(Data value, long oldValueSizeOffset, long oldValueSize, long oldValueOffset) { - assert oldValueSize == (value.size()); - initValSizeEqualToOld(oldValueSizeOffset, oldValueSize, oldValueOffset); - writeValue(value); - } - - public void initValue(Data value) { - entryBytes.position(valueSizeOffset()); - initValSize(value.size()); - writeValue(value); - } - - long replicationBytesOffset = -1; - - public boolean replicationStateInit() { - return (this.replicationBytesOffset) >= 0; - } - - void initReplicationState() { - replicationBytesOffset = keyEnd(); - } - - public long replicationBytesOffset() { - if (!(this.replicationStateInit())) - this.initReplicationState(); - - return this.replicationBytesOffset; - } - - public void closeReplicationState() { - if (!(this.replicationStateInit())) - return ; - - this.replicationBytesOffset = -1; - } - - void updateReplicationState(long timestamp, byte identifier) { - entryBytes.position(replicationBytesOffset()); - entryBytes.writeLong(timestamp); - entryBytes.writeByte(identifier); - } - - private long entryDeletedOffset() { - return (replicationBytesOffset()) + 9L; - } - - public void writeEntryDeleted() { - entryBS.writeBoolean(entryDeletedOffset(), true); - } - - public void writeEntryPresent() { - entryBS.writeBoolean(entryDeletedOffset(), false); - } - - public boolean entryDeleted() { - return entryBS.readBoolean(entryDeletedOffset()); - } - - public boolean entryIsPresent() { - return !(this.entryDeleted()); - } - - public long timestamp() { - return entryBS.readLong(replicationBytesOffset()); - } - - @Override - public long originTimestamp() { - this.checkOnEachPublicOperation(); - return timestamp(); - } - - private boolean testTimeStampInSensibleRange() { - if ((this.m().timeProvider) == (TimeProvider.SYSTEM)) { - long currentTime = TimeProvider.SYSTEM.currentTime(); - assert (Math.abs((currentTime - (timestamp())))) <= 100000000 : "unrealistic timestamp: " + (timestamp()); - assert (Math.abs((currentTime - (this.innerRemoteTimestamp())))) <= 100000000 : "unrealistic innerRemoteTimestamp: " + (this.innerRemoteTimestamp()); - } - return true; - } - - private long timestampOffset() { - return replicationBytesOffset(); - } - - private long identifierOffset() { - return (replicationBytesOffset()) + 8L; - } - - byte identifier() { - return entryBS.readByte(identifierOffset()); - } - - @Override - public byte originIdentifier() { - this.checkOnEachPublicOperation(); - return identifier(); - } - - protected long entryEnd() { - return (valueOffset()) + (valueSize()); - } - - public void closeReplicatedMapEntryStagesEntryEndDependants() { - this.closeReplicatedMapEntryStagesEntrySizeDependants(); - } - - boolean used; - - public boolean usedInit() { - return used; - } - - public void initUsed(boolean used) { - this.used = used; - } - - void closeUsed() { - if (!(this.usedInit())) - return ; - - used = false; - } - - public boolean entryRemovedOnThisIteration = false; - - boolean entryRemovedOnThisIterationInit() { - return (this.entryRemovedOnThisIteration) != false; - } - - protected void initEntryRemovedOnThisIteration(boolean entryRemovedOnThisIteration) { - this.entryRemovedOnThisIteration = entryRemovedOnThisIteration; - } - - public void closeEntryRemovedOnThisIteration() { - if (!(this.entryRemovedOnThisIterationInit())) - return ; - - this.entryRemovedOnThisIteration = false; - } - - public int segmentIndex = -1; - - public boolean theSegmentIndexInit() { - return (this.segmentIndex) >= 0; - } - - public void initTheSegmentIndex(int segmentIndex) { - this.segmentIndex = segmentIndex; - this.closeTheSegmentIndexDependants(); - } - - public int segmentIndex() { - assert this.theSegmentIndexInit() : "TheSegmentIndex should be init"; - return this.segmentIndex; - } - - public void closeTheSegmentIndex() { - if (!(this.theSegmentIndexInit())) - return ; - - this.closeTheSegmentIndexDependants(); - this.segmentIndex = -1; - } - - public void closeTheSegmentIndexDependants() { - this.closeSegment(); - this.closeSegmentHashLookup(); - this.closeSegHeader(); - } - - public void dropChange() { - this.m().dropChange(this.segmentIndex(), this.pos()); - } - - long entrySpaceOffset = 0; - - MultiStoreBytes freeListBytes = new MultiStoreBytes(); - - public SingleThreadedDirectBitSet freeList = new SingleThreadedDirectBitSet(); - - boolean segmentInit() { - return (entrySpaceOffset) > 0; - } - - void initSegment() { - VanillaChronicleHash h = this.h(); - long hashLookupOffset = h.segmentOffset(segmentIndex()); - long freeListOffset = hashLookupOffset + (h.segmentHashLookupOuterSize); - freeListBytes.storePositionAndSize(h.ms, freeListOffset, h.segmentFreeListInnerSize); - freeList.reuse(freeListBytes); - entrySpaceOffset = (freeListOffset + (h.segmentFreeListOuterSize)) + (h.segmentEntrySpaceInnerOffset); - this.closeSegmentDependants(); - } - - public long entrySpaceOffset() { - if (!(this.segmentInit())) - this.initSegment(); - - return this.entrySpaceOffset; - } - - public SingleThreadedDirectBitSet freeList() { - if (!(this.segmentInit())) - this.initSegment(); - - return this.freeList; - } - - void closeSegment() { - if (!(this.segmentInit())) - return ; - - this.closeSegmentDependants(); - entrySpaceOffset = 0; - } - - public void closeSegmentDependants() { - this.closeEntryOffset(); - } - - public long keySizeOffset = -1; - - public boolean entryOffsetInit() { - return (this.keySizeOffset) >= 0; - } - - public void initEntryOffset() { - keySizeOffset = (this.entrySpaceOffset()) + ((pos()) * (this.h().chunkSize)); - entryBytes.limit(entryBytes.capacity()); - this.closeEntryOffsetDependants(); - } - - public long keySizeOffset() { - if (!(this.entryOffsetInit())) - this.initEntryOffset(); - - return this.keySizeOffset; - } - - public void closeEntryOffset() { - if (!(this.entryOffsetInit())) - return ; - - this.closeEntryOffsetDependants(); - this.keySizeOffset = -1; - } - - public void closeEntryOffsetDependants() { - this.closeReplicatedMapEntryStagesEntrySizeDependants(); - } - - long entrySize() { - return (entryEnd()) - (keySizeOffset()); - } - - public void closeReplicatedMapEntryStagesEntrySizeDependants() { - this.closeTheEntrySizeInChunks(); - } - - public int entrySizeInChunks = 0; - - public boolean theEntrySizeInChunksInit() { - return (this.entrySizeInChunks) != 0; - } - - void initTheEntrySizeInChunks() { - entrySizeInChunks = this.h().inChunks(entrySize()); - } - - public void initTheEntrySizeInChunks(int actuallyUsedChunks) { - entrySizeInChunks = actuallyUsedChunks; - } - - public int entrySizeInChunks() { - if (!(this.theEntrySizeInChunksInit())) - this.initTheEntrySizeInChunks(); - - return this.entrySizeInChunks; - } - - public void closeTheEntrySizeInChunks() { - if (!(this.theEntrySizeInChunksInit())) - return ; - - this.entrySizeInChunks = 0; - } - - public void writeNewEntry(long pos, Data key) { - initPos(pos); - initKeySize(key.size()); - entryBytes.position(keySizeOffset()); - this.h().keySizeMarshaller.writeSize(entryBytes, keySize()); - initKeyOffset(entryBytes.position()); - key.writeTo(entryBS, keyOffset()); - } - - public void copyExistingEntry(long newPos, long bytesToCopy) { - long oldKeySizeOffset = keySizeOffset(); - long oldKeyOffset = keyOffset(); - initPos(newPos); - initKeyOffset(((keySizeOffset()) + (oldKeyOffset - oldKeySizeOffset))); - entryBS.write(keySizeOffset(), entryBS, oldKeySizeOffset, bytesToCopy); - } - - public void readExistingEntry(long pos) { - initPos(pos); - entryBytes.position(keySizeOffset()); - initKeySize(this.h().keySizeMarshaller.readSize(entryBytes)); - initKeyOffset(entryBytes.position()); - } - - public long newSizeOfEverythingBeforeValue(Data newValue) { - return ((valueSizeOffset()) + (this.m().valueSizeMarshaller.sizeEncodingSize(newValue.size()))) - (keySizeOffset()); - } - - public void raiseChange() { - this.m().raiseChange(this.segmentIndex(), this.pos()); - } - - public void updateChange() { - if (!(replicationUpdateInit())) { - raiseChange(); - } - } - - int hashLookupEntrySize; - - int keyBits; - - long address = -1; - - long capacityMask; - - long capacityMask2; - - long keyMask; - - long valueMask; - - long entryMask; - - public boolean segmentHashLookupInit() { - return (this.address) >= 0; - } - - public void initSegmentHashLookup() { - long hashLookupOffset = this.h().segmentOffset(this.segmentIndex()); - innerInitSegmentHashLookup(((this.h().ms.address()) + hashLookupOffset), this.h().segmentHashLookupCapacity, this.h().segmentHashLookupEntrySize, this.h().segmentHashLookupKeyBits, this.h().segmentHashLookupValueBits); - } - - public void initSegmentHashLookup(long address, long capacity, int entrySize, int keyBits, int valueBits) { - innerInitSegmentHashLookup(address, capacity, entrySize, keyBits, valueBits); - } - - public int hashLookupEntrySize() { - if (!(this.segmentHashLookupInit())) - this.initSegmentHashLookup(); - - return this.hashLookupEntrySize; - } - - public int keyBits() { - if (!(this.segmentHashLookupInit())) - this.initSegmentHashLookup(); - - return this.keyBits; - } - - public long address() { - if (!(this.segmentHashLookupInit())) - this.initSegmentHashLookup(); - - return this.address; - } - - public long capacityMask() { - if (!(this.segmentHashLookupInit())) - this.initSegmentHashLookup(); - - return this.capacityMask; - } - - public long capacityMask2() { - if (!(this.segmentHashLookupInit())) - this.initSegmentHashLookup(); - - return this.capacityMask2; - } - - public long entryMask() { - if (!(this.segmentHashLookupInit())) - this.initSegmentHashLookup(); - - return this.entryMask; - } - - public long keyMask() { - if (!(this.segmentHashLookupInit())) - this.initSegmentHashLookup(); - - return this.keyMask; - } - - public long valueMask() { - if (!(this.segmentHashLookupInit())) - this.initSegmentHashLookup(); - - return this.valueMask; - } - - public void closeSegmentHashLookup() { - if (!(this.segmentHashLookupInit())) - return ; - - this.address = -1; - } - - public long readEntry(long pos) { - return NativeBytes.UNSAFE.getLong(((address()) + pos)); - } - - public long step(long pos) { - return (pos += hashLookupEntrySize()) <= (capacityMask2()) ? pos : 0L; - } - - public long stepBack(long pos) { - return (pos -= hashLookupEntrySize()) >= 0 ? pos : capacityMask2(); - } - - long indexToPos(long index) { - return index * (hashLookupEntrySize()); - } - - public long maskUnsetKey(long key) { - return (key &= keyMask()) != (UNSET_KEY) ? key : keyMask(); - } - - long entry(long key, long value) { - return key | (value << (keyBits())); - } - - public void writeEntryVolatile(long pos, long prevEntry, long key, long value) { - long entry = (prevEntry & (~(entryMask()))) | (entry(key, value)); - NativeBytes.UNSAFE.putLongVolatile(null, ((address()) + pos), entry); - } - - public void clearHashLookup() { - NativeBytes.UNSAFE.setMemory(address(), ((capacityMask2()) + (hashLookupEntrySize())), ((byte)(0))); - } - - public long key(long entry) { - return entry & (keyMask()); - } - - public void writeEntry(long pos, long prevEntry, long key, long value) { - long entry = (prevEntry & (~(entryMask()))) | (entry(key, value)); - NativeBytes.UNSAFE.putLong(((address()) + pos), entry); - } - - void writeEntry(long pos, long prevEntry, long anotherEntry) { - long entry = (prevEntry & (~(entryMask()))) | (anotherEntry & (entryMask())); - NativeBytes.UNSAFE.putLong(((address()) + pos), entry); - } - - public long value(long entry) { - return (entry >>> (keyBits())) & (valueMask()); - } - - public long hlPos(long key) { - return indexToPos((key & (capacityMask()))); - } - - public void checkValueForPut(long value) { - assert (value & (~(valueMask()))) == 0L : "Value out of range, was " + value; - } - - public void putValueVolatile(long pos, long value) { - checkValueForPut(value); - long currentEntry = readEntry(pos); - writeEntryVolatile(pos, currentEntry, key(currentEntry), value); - } - - void clearEntry(long pos, long prevEntry) { - long entry = prevEntry & (~(entryMask())); - NativeBytes.UNSAFE.putLong(((address()) + pos), entry); - } - - public boolean empty(long entry) { - return (entry & (entryMask())) == (UNSET_ENTRY); - } - - public long remove(long posToRemove) { - long entryToRemove = readEntry(posToRemove); - long posToShift = posToRemove; - while (true) { - posToShift = step(posToShift); - long entryToShift = readEntry(posToShift); - if (empty(entryToShift)) - break; - - long insertPos = hlPos(key(entryToShift)); - boolean cond1 = insertPos <= posToRemove; - boolean cond2 = posToRemove <= posToShift; - if ((cond1 && cond2) || ((posToShift < insertPos) && (cond1 || cond2))) { - writeEntry(posToRemove, entryToRemove, entryToShift); - posToRemove = posToShift; - entryToRemove = entryToShift; - } - } - clearEntry(posToRemove, entryToRemove); - return posToRemove; - } - - void forEach(EntryConsumer action) { - for (long pos = 0L ; pos <= (capacityMask2()) ; pos += hashLookupEntrySize()) { - long entry = readEntry(pos); - if (!(empty(entry))) - action.accept(key(entry), value(entry)); - - } - } - - String hashLookupToString() { - final StringBuilder sb = new StringBuilder("{"); - forEach((long key,long value) -> sb.append(key).append('=').append(value).append(',')); - sb.append('}'); - return sb.toString(); - } - - public void moveChange(long oldPos, long newPos) { - this.m().moveChange(this.segmentIndex(), oldPos, newPos); - } - - long segmentHeaderAddress; - - SegmentHeader segmentHeader = null; - - public boolean segHeaderInit() { - return (this.segmentHeader) != null; - } - - private void initSegHeader() { - segmentHeaderAddress = (this.h().ms.address()) + (this.h().segmentHeaderOffset(segmentIndex())); - segmentHeader = BigSegmentHeader.INSTANCE; - this.closeSegHeaderDependants(); - } - - public long segmentHeaderAddress() { - if (!(this.segHeaderInit())) - this.initSegHeader(); - - return this.segmentHeaderAddress; - } - - public SegmentHeader segmentHeader() { - if (!(this.segHeaderInit())) - this.initSegHeader(); - - return this.segmentHeader; - } - - public void closeSegHeader() { - if (!(this.segHeaderInit())) - return ; - - this.closeSegHeaderDependants(); - this.segmentHeader = null; - } - - public void closeSegHeaderDependants() { - this.closeSegmentStagesTryFindInitLocksOfThisSegmentDependants(); - this.closeLocks(); - } - - public void nextPosToSearchFrom(long nextPosToSearchFrom) { - segmentHeader().nextPosToSearchFrom(segmentHeaderAddress(), nextPosToSearchFrom); - } - - public void updateNextPosToSearchFrom(long allocated, int chunks) { - long nextPosToSearchFrom = allocated + chunks; - if (nextPosToSearchFrom >= (this.h().actualChunksPerSegment)) - nextPosToSearchFrom = 0L; - - nextPosToSearchFrom(nextPosToSearchFrom); - } - - long nextPosToSearchFrom() { - return segmentHeader().nextPosToSearchFrom(segmentHeaderAddress()); - } - - public long alloc(int chunks) { - VanillaChronicleHash h = this.h(); - if (chunks > (h.maxChunksPerEntry)) - throw new IllegalArgumentException((((("Entry is too large: requires " + chunks) + " entry size chucks, ") + (h.maxChunksPerEntry)) + " is maximum.")); - - long ret = freeList().setNextNContinuousClearBits(nextPosToSearchFrom(), chunks); - if ((ret == (DirectBitSet.NOT_FOUND)) || ((ret + chunks) > (h.actualChunksPerSegment))) { - if (((ret != (DirectBitSet.NOT_FOUND)) && ((ret + chunks) > (h.actualChunksPerSegment))) && (ret < (h.actualChunksPerSegment))) - freeList().clear(ret, h.actualChunksPerSegment); - - ret = freeList().setNextNContinuousClearBits(0L, chunks); - if ((ret == (DirectBitSet.NOT_FOUND)) || ((ret + chunks) > (h.actualChunksPerSegment))) { - if (((ret != (DirectBitSet.NOT_FOUND)) && ((ret + chunks) > (h.actualChunksPerSegment))) && (ret < (h.actualChunksPerSegment))) - freeList().clear(ret, h.actualChunksPerSegment); - - if (chunks == 1) { - throw new IllegalStateException("Segment is full, no free entries found"); - } else { - throw new IllegalStateException((("Segment is full or has no ranges of " + chunks) + " continuous free chunks")); - } - } - updateNextPosToSearchFrom(ret, chunks); - } else { - if ((chunks == 1) || (freeList().isSet(nextPosToSearchFrom()))) { - updateNextPosToSearchFrom(ret, chunks); - } - } - return ret; - } - - public void initEntryAndKeyCopying(long entrySize, long bytesToCopy) { - initAllocatedChunks(this.h().inChunks(entrySize)); - this.copyExistingEntry(this.alloc(allocatedChunks()), bytesToCopy); - incrementSegmentEntriesIfNeeded(); - } - - public void free(long fromPos, int chunks) { - freeList().clear(fromPos, (fromPos + chunks)); - if (fromPos < (nextPosToSearchFrom())) - nextPosToSearchFrom(fromPos); - - } - - public final void freeExtraAllocatedChunks() { - if (((!(this.m().constantlySizedEntry)) && (this.m().couldNotDetermineAlignmentBeforeAllocation)) && ((entrySizeInChunks()) < (this.allocatedChunks()))) { - this.free(((pos()) + (entrySizeInChunks())), ((this.allocatedChunks()) - (entrySizeInChunks()))); - } else { - initTheEntrySizeInChunks(this.allocatedChunks()); - } - } - - public void writeValueAndPutPos(Data value) { - initValue(value); - freeExtraAllocatedChunks(); - this.putValueVolatile(this.hashLookupPos(), pos()); - } - - protected void relocation(Data newValue, long newSizeOfEverythingBeforeValue) { - long oldPos = pos(); - _MapEntryStages_relocation(newValue, newSizeOfEverythingBeforeValue); - this.moveChange(oldPos, pos()); - } - - boolean tryFindInitLocksOfThisSegment(Object thisContext, int index) { - CompiledReplicatedMapIterationContext c = this.contextAtIndexInChain(index); - if ((((c.segmentHeader()) != null) && ((c.segmentHeaderAddress()) == (segmentHeaderAddress()))) && ((c.rootContextOnThisSegment()) != null)) { - throw new IllegalStateException("Nested context not implemented yet"); - } else { - return false; - } - } - - public void closeSegmentStagesTryFindInitLocksOfThisSegmentDependants() { - this.closeLocks(); - } - - public void deleted(long deleted) { - segmentHeader().deleted(segmentHeaderAddress(), deleted); - } - - public long deleted() { - return segmentHeader().deleted(segmentHeaderAddress()); - } - - public void entries(long size) { - segmentHeader().size(segmentHeaderAddress(), size); - } - - public long entries() { - return segmentHeader().size(segmentHeaderAddress()); - } - - public long size() { - return (entries()) - (deleted()); - } - - int totalReadLockCount; - - int totalUpdateLockCount; - - int totalWriteLockCount; - - public int latestSameThreadSegmentModCount; - - public int contextModCount; - - CompiledReplicatedMapIterationContext nextNode; - - public boolean concurrentSameThreadContexts; - - LocalLockState localLockState; - - public CompiledReplicatedMapIterationContext rootContextOnThisSegment = null; - - public boolean locksInit() { - return (this.rootContextOnThisSegment) != null; - } - - void initLocks() { - localLockState = LocalLockState.UNLOCKED; - int indexOfThisContext = this.indexInContextChain; - for (int i = indexOfThisContext - 1 ; i >= 0 ; i--) { - if (tryFindInitLocksOfThisSegment(this, i)) - return ; - - } - for (int i = indexOfThisContext + 1, size = this.contextChain.size() ; i < size ; i++) { - if (tryFindInitLocksOfThisSegment(this, i)) - return ; - - } - rootContextOnThisSegment = this; - concurrentSameThreadContexts = false; - latestSameThreadSegmentModCount = 0; - contextModCount = 0; - nextNode = null; - totalReadLockCount = 0; - totalUpdateLockCount = 0; - totalWriteLockCount = 0; - } - - public LocalLockState localLockState() { - if (!(this.locksInit())) - this.initLocks(); - - return this.localLockState; - } - - public CompiledReplicatedMapIterationContext rootContextOnThisSegment() { - if (!(this.locksInit())) - this.initLocks(); - - return this.rootContextOnThisSegment; - } - - void closeLocks() { - if (!(this.locksInit())) - return ; - - if ((rootContextOnThisSegment) == (this)) { - closeRootLocks(); - } else { - closeNestedLocks(); - } - localLockState = null; - rootContextOnThisSegment = null; - } - - @Override - public void dropChanged() { - this.checkOnEachPublicOperation(); - this.innerUpdateLock.lock(); - this.dropChange(); - } - - public boolean forEachRemoving(Predicate> action) { - this.innerUpdateLock.lock(); - try { - long size = this.size(); - if (size == 0) - return true; - - boolean interrupted = false; - long startPos = 0L; - while (!(this.empty(this.readEntry(startPos)))) { - startPos = this.step(startPos); - } - this.initHashLookupPos(startPos); - do { - this.setHashLookupPosGuarded(this.step(this.hashLookupPos())); - long entry = this.readEntry(this.hashLookupPos()); - if (!(this.empty(entry))) { - this.readExistingEntry(this.value(entry)); - if (entryIsPresent()) { - initEntryRemovedOnThisIteration(false); - if (!(action.test(((MapEntry)(this))))) { - interrupted = true; - break; - } else { - if ((--size) == 0) - break; - - } - } - } - } while ((this.hashLookupPos()) != startPos ); - return !interrupted; - } finally { - this.innerReadLock.unlock(); - initEntryRemovedOnThisIteration(false); - } - } - - @Override - public void forEachReplicableEntry(Consumer action) { - this.innerUpdateLock.lock(); - try { - long entries = this.entries(); - if (entries == 0) - return ; - - long startPos = 0L; - while (!(this.empty(this.readEntry(startPos)))) { - startPos = this.step(startPos); - } - this.initHashLookupPos(startPos); - do { - this.setHashLookupPosGuarded(this.step(this.hashLookupPos())); - long entry = this.readEntry(this.hashLookupPos()); - if (!(this.empty(entry))) { - this.readExistingEntry(this.value(entry)); - action.accept(this); - if ((--entries) == 0) - break; - - } - } while ((this.hashLookupPos()) != startPos ); - } finally { - this.innerReadLock.unlock(); - } - } - - @Override - public void raiseChanged() { - this.checkOnEachPublicOperation(); - this.innerUpdateLock.lock(); - this.raiseChange(); - } - - public void innerRemoveEntryExceptHashLookupUpdate() { - this.free(pos(), entrySizeInChunks()); - this.entries(((this.entries()) - 1L)); - this.incrementModCountGuarded(); - } - - public void clearSegment() { - this.innerWriteLock.lock(); - this.clearHashLookup(); - freeList().clear(); - nextPosToSearchFrom(0L); - entries(0L); - } - - public void clear() { - clearSegment(); - } - - public void putValueDeletedEntry(Data newValue) { - throw new AssertionError("Replicated Map doesn\'t remove entries truly, yet"); - } - - public void updatedReplicationStateOnAbsentEntry() { - if (!(this.replicationUpdateInit())) { - this.innerWriteLock.lock(); - updateReplicationState(this.m().timeProvider.currentTime(), this.m().identifier()); - } - } - - public void innerDefaultReplaceValue(Data newValue) { - assert this.innerUpdateLock.isHeldByCurrentThread(); - boolean newValueSizeIsDifferent = (newValue.size()) != (this.valueSize()); - if (newValueSizeIsDifferent) { - long newSizeOfEverythingBeforeValue = newSizeOfEverythingBeforeValue(newValue); - long entryStartOffset = keySizeOffset(); - VanillaChronicleMap m = this.m(); - long newValueOffset = m.alignment.alignAddr((entryStartOffset + newSizeOfEverythingBeforeValue)); - long newEntrySize = (newValueOffset + (newValue.size())) - entryStartOffset; - int newSizeInChunks = m.inChunks(newEntrySize); - newValueDoesNotFit : if (newSizeInChunks > (entrySizeInChunks())) { - if (newSizeInChunks > (m.maxChunksPerEntry)) { - throw new IllegalArgumentException(((((("Value too large: " + "entry takes ") + newSizeInChunks) + " chunks, ") + (m.maxChunksPerEntry)) + " is maximum.")); - } - if (this.freeList().allClear(((pos()) + (entrySizeInChunks())), ((pos()) + newSizeInChunks))) { - this.freeList().set(((pos()) + (entrySizeInChunks())), ((pos()) + newSizeInChunks)); - break newValueDoesNotFit; - } - relocation(newValue, newSizeOfEverythingBeforeValue); - return ; - } else if (newSizeInChunks < (entrySizeInChunks())) { - this.freeList().clear(((pos()) + newSizeInChunks), ((pos()) + (entrySizeInChunks()))); - } - } else { - } - this.innerWriteLock.lock(); - if (newValueSizeIsDifferent) { - initValue(newValue); - } else { - writeValue(newValue); - } - this.putValueVolatile(this.hashLookupPos(), pos()); - } - - public void updatedReplicationStateOnPresentEntry() { - if (!(this.replicationUpdateInit())) { - this.innerWriteLock.lock(); - long timestamp; - if ((identifier()) != (this.m().identifier())) { - timestamp = Math.max(((timestamp()) + 1), this.m().timeProvider.currentTime()); - } else { - timestamp = this.m().timeProvider.currentTime(); - } - updateReplicationState(timestamp, this.m().identifier()); - } - } - - @Override - public void doReplaceValue(Data newValue) { - this.checkOnEachPublicOperation(); - try { - this.innerDefaultReplaceValue(newValue); - this.updateChange(); - this.updatedReplicationStateOnPresentEntry(); - } finally { - this.innerWriteLock.unlock(); - } - } - - @Override - public void updateOrigin(byte newIdentifier, long newTimestamp) { - this.checkOnEachPublicOperation(); - this.innerWriteLock.lock(); - updateReplicationState(newTimestamp, newIdentifier); - } - - @Override - public void doRemove() { - this.checkOnEachPublicOperation(); - initEntryRemovedOnThisIteration(true); - try { - if ((this.valueSize()) > (this.dummyValue.size())) - this.innerDefaultReplaceValue(this.dummyValue); - - this.updatedReplicationStateOnPresentEntry(); - this.writeEntryDeleted(); - this.updateChange(); - this.deleted(((this.deleted()) + 1)); - } finally { - this.innerWriteLock.unlock(); - } - } -} diff --git a/src/main/java/net/openhft/chronicle/map/impl/CompiledReplicatedMapQueryContext.java b/src/main/java/net/openhft/chronicle/map/impl/CompiledReplicatedMapQueryContext.java deleted file mode 100644 index dd8b16bb0..000000000 --- a/src/main/java/net/openhft/chronicle/map/impl/CompiledReplicatedMapQueryContext.java +++ /dev/null @@ -1,4187 +0,0 @@ -package net.openhft.chronicle.map.impl; - -import net.openhft.chronicle.bytes.*; -import net.openhft.chronicle.hash.AbstractData; -import net.openhft.chronicle.hash.Data; -import net.openhft.chronicle.hash.HashEntry; -import net.openhft.chronicle.hash.impl.*; -import net.openhft.chronicle.hash.impl.hashlookup.EntryConsumer; -import net.openhft.chronicle.hash.impl.value.instance.KeyInitableData; -import net.openhft.chronicle.hash.locks.InterProcessLock; -import net.openhft.chronicle.hash.locks.InterProcessReadWriteUpdateLock; -import net.openhft.chronicle.hash.replication.RemoteOperationContext; -import net.openhft.chronicle.hash.replication.TimeProvider; -import net.openhft.chronicle.hash.serialization.BytesReader; -import net.openhft.chronicle.hash.serialization.internal.MetaBytesInterop; -import net.openhft.chronicle.map.*; -import net.openhft.chronicle.map.impl.data.instance.ValueInitableData; -import net.openhft.chronicle.map.impl.ret.InstanceReturnValue; -import net.openhft.chronicle.map.impl.ret.UsableReturnValue; -import net.openhft.chronicle.map.replication.MapRemoteQueryContext; -import net.openhft.chronicle.map.replication.MapReplicableEntry; -import net.openhft.lang.Maths; -import net.openhft.lang.MemoryUnit; -import net.openhft.lang.collection.DirectBitSet; -import net.openhft.lang.collection.SingleThreadedDirectBitSet; -import net.openhft.lang.io.Bytes; -import net.openhft.lang.io.DirectBytes; -import net.openhft.lang.io.MultiStoreBytes; -import net.openhft.lang.io.NativeBytes; -import net.openhft.lang.threadlocal.ThreadLocalCopies; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.util.ArrayList; -import java.util.ConcurrentModificationException; -import java.util.List; -import java.util.concurrent.TimeUnit; - -public class CompiledReplicatedMapQueryContext, V, VI, MVI extends MetaBytesInterop, R, T> implements AutoCloseable , HashEntry , InterProcessReadWriteUpdateLock , RemoteOperationContext , ExternalMapQueryContext , MapAbsentEntry , MapContext , MapEntry , MapAbsentEntryHolder , QueryContextInterface , ReplicatedChronicleMapHolder , MapRemoteQueryContext , MapReplicableEntry { - public void close() { - this.bytesReturnValue.closeOutput(); - this.wrappedValueInstanceValue.closeValue(); - this.inputValueInstanceValue.closeValue(); - this.closeInputBytes(); - this.closeReplicationInput(); - this.closeUsed(); - this.closeAllocatedChunks(); - this.closeReplicationUpdate(); - this.wrappedValueInstanceValue.closeNext(); - this.usingReturnValue.closeUsingReturnValue(); - this.defaultReturnValue.closeDefaultReturnedValue(); - this.closeKeySize(); - this.inputKeyInstanceValue.closeKey(); - this.closeReplicatedInputBytes(); - this.closePos(); - this.closeInputKey(); - this.closeKeyOffset(); - this.closeKeyBytesInteropKeyMetaInteropDependants(); - this.closeReplicatedChronicleMapHolderImplContextAtIndexInChainDependants(); - this.closeOwnerThreadHolderCheckAccessingFromOwnerThreadDependants(); - this.closeValueBytesInteropValueMetaInteropDependants(); - } - - public void incrementModCountGuarded() { - if (!(this.locksInit())) - this.initLocks(); - - incrementModCount(); - } - - public void setHashLookupPosGuarded(long hashLookupPos) { - if (!(this.hashLookupPosInit())) - this.initHashLookupPos(); - - setHashLookupPos(hashLookupPos); - } - - public void setLocalLockStateGuarded(LocalLockState newState) { - if (!(this.locksInit())) - this.initLocks(); - - setLocalLockState(newState); - } - - public void setSearchStateGuarded(CompiledReplicatedMapQueryContext.SearchState newSearchState) { - if (!(this.keySearchInit())) - this.initKeySearch(); - - setSearchState(newSearchState); - } - - private long _MapEntryStages_countValueSizeOffset() { - return keyEnd(); - } - - private long _MapEntryStages_sizeOfEverythingBeforeValue(long keySize, long valueSize) { - return (((this.m().metaDataBytes) + (this.m().keySizeMarshaller.sizeEncodingSize(keySize))) + keySize) + (this.m().valueSizeMarshaller.sizeEncodingSize(valueSize)); - } - - void keyFound() { - searchState = CompiledReplicatedMapQueryContext.SearchState.PRESENT; - } - - public CompiledReplicatedMapQueryContext(ReplicatedChronicleMap m) { - contextChain = new ArrayList(); - contextChain.add(this); - indexInContextChain = 0; - this.m = m; - this.inputKeyBytesValue = new InputKeyBytesData(); - this.defaultReturnValue = new DefaultReturnValue(); - this.inputValueInstanceValue = new InputValueInstanceData(); - this.copies = ThreadLocalCopies.get(); - this.valueInterop = this.m().valueInteropProvider.get(this.copies, this.m().originalValueInterop); - this.valueReader = this.m().valueReaderProvider.get(this.copies, this.m().originalValueReader); - this.keyInterop = this.h().keyInteropProvider.get(this.copies, this.h().originalKeyInterop); - this.keyReader = this.h().keyReaderProvider.get(this.copies, this.h().originalKeyReader); - this.absentDelegating = new ReplicatedMapAbsentDelegating(); - this.deprecatedMapAcquireContext = new DeprecatedMapAcquireContextOnQuery(); - this.usingReturnValue = new UsingReturnValue(); - this.entryKey = new EntryKeyBytesData(); - this.innerUpdateLock = new UpdateLock(); - this.innerReadLock = new ReadLock(); - this.inputStore = new JavaLangBytesReusableBytesStore(); - this.deprecatedMapKeyContext = new DeprecatedMapKeyContextOnQuery(); - this.replicatedInputKeyBytesValue = new ReplicatedInputKeyBytesData(); - this.entryValue = new EntryValueBytesData(); - this.innerWriteLock = new WriteLock(); - this.bytesReturnValue = new BytesReturnValue(); - this.entryBytes = this.h().ms.bytes(); - this.entryBS = new NativeBytesStore(entryBytes.address() , entryBytes.capacity() , null , false); - this.owner = Thread.currentThread(); - this.replicatedInputStore = new JavaLangBytesReusableBytesStore(); - this.dummyValue = new DummyValueZeroData(); - this.inputFirstValueBytesValue = new InputFirstValueBytesData(); - this.inputKeyInstanceValue = new InputKeyInstanceData(); - this.replicatedInputValueBytesValue = new ReplicatedInputValueBytesData(); - this.wrappedValueInstanceValue = new WrappedValueInstanceData(); - this.inputSecondValueBytesValue = new InputSecondValueBytesData(); - } - - public CompiledReplicatedMapQueryContext(CompiledReplicatedMapQueryContext c) { - contextChain = c.contextChain; - indexInContextChain = contextChain.size(); - contextChain.add(this); - this.m = ((ReplicatedChronicleMap)(c.m)); - this.inputKeyBytesValue = new InputKeyBytesData(); - this.defaultReturnValue = new DefaultReturnValue(); - this.inputValueInstanceValue = new InputValueInstanceData(); - this.copies = ThreadLocalCopies.get(); - this.valueInterop = this.m().valueInteropProvider.get(this.copies, this.m().originalValueInterop); - this.valueReader = this.m().valueReaderProvider.get(this.copies, this.m().originalValueReader); - this.keyInterop = this.h().keyInteropProvider.get(this.copies, this.h().originalKeyInterop); - this.keyReader = this.h().keyReaderProvider.get(this.copies, this.h().originalKeyReader); - this.absentDelegating = new ReplicatedMapAbsentDelegating(); - this.deprecatedMapAcquireContext = new DeprecatedMapAcquireContextOnQuery(); - this.usingReturnValue = new UsingReturnValue(); - this.entryKey = new EntryKeyBytesData(); - this.innerUpdateLock = new UpdateLock(); - this.innerReadLock = new ReadLock(); - this.inputStore = new JavaLangBytesReusableBytesStore(); - this.deprecatedMapKeyContext = new DeprecatedMapKeyContextOnQuery(); - this.replicatedInputKeyBytesValue = new ReplicatedInputKeyBytesData(); - this.entryValue = new EntryValueBytesData(); - this.innerWriteLock = new WriteLock(); - this.bytesReturnValue = new BytesReturnValue(); - this.entryBytes = this.h().ms.bytes(); - this.entryBS = new NativeBytesStore(entryBytes.address() , entryBytes.capacity() , null , false); - this.owner = Thread.currentThread(); - this.replicatedInputStore = new JavaLangBytesReusableBytesStore(); - this.dummyValue = new DummyValueZeroData(); - this.inputFirstValueBytesValue = new InputFirstValueBytesData(); - this.inputKeyInstanceValue = new InputKeyInstanceData(); - this.replicatedInputValueBytesValue = new ReplicatedInputValueBytesData(); - this.wrappedValueInstanceValue = new WrappedValueInstanceData(); - this.inputSecondValueBytesValue = new InputSecondValueBytesData(); - } - - public class BytesReturnValue implements AutoCloseable , ReturnValue { - public BytesReturnValue() { - this.outputStore = new JavaLangBytesReusableBytesStore(); - } - - private final JavaLangBytesReusableBytesStore outputStore; - - public JavaLangBytesReusableBytesStore outputStore() { - return this.outputStore; - } - - long startOutputPos; - - TcpReplicator.TcpSocketChannelEntryWriter output = null; - - public boolean outputInit() { - return (this.output) != null; - } - - public void initOutput(TcpReplicator.TcpSocketChannelEntryWriter output) { - this.output = output; - startOutputPos = output.in().position(); - } - - public long startOutputPos() { - assert this.outputInit() : "Output should be init"; - return this.startOutputPos; - } - - public TcpReplicator.TcpSocketChannelEntryWriter output() { - assert this.outputInit() : "Output should be init"; - return this.output; - } - - public void closeOutput() { - if (!(this.outputInit())) - return ; - - this.output = null; - } - - @Override - public void returnValue(@NotNull - Data value) { - long valueSize = value.size(); - long totalSize = (1L + (CompiledReplicatedMapQueryContext.this.m().valueSizeMarshaller.sizeEncodingSize(valueSize))) + valueSize; - output().ensureBufferSize(totalSize); - Bytes out = output().in(); - out.writeBoolean(false); - CompiledReplicatedMapQueryContext.this.m().valueSizeMarshaller.writeSize(out, valueSize); - long outPosition = out.position(); - out.skip(valueSize); - outputStore.setBytes(out); - value.writeTo(outputStore, outPosition); - } - - @Override - public void close() { - if ((output().in().position()) == (startOutputPos())) { - output().ensureBufferSize(1L); - output().in().writeBoolean(true); - } - } - } - - public class DeprecatedMapAcquireContextOnQuery implements MapKeyContext { - @NotNull - @Override - public InterProcessLock writeLock() { - return CompiledReplicatedMapQueryContext.this.writeLock(); - } - - @NotNull - @Override - public InterProcessLock readLock() { - return CompiledReplicatedMapQueryContext.this.readLock(); - } - - @NotNull - @Override - public InterProcessLock updateLock() { - return CompiledReplicatedMapQueryContext.this.updateLock(); - } - - @NotNull - @Override - public K key() { - CompiledReplicatedMapQueryContext.this.checkOnEachPublicOperation(); - return CompiledReplicatedMapQueryContext.this.queriedKey().get(); - } - - @Override - public long valueOffset() { - CompiledReplicatedMapQueryContext.this.checkOnEachPublicOperation(); - return CompiledReplicatedMapQueryContext.this.valueOffset(); - } - - @Override - public long keyOffset() { - CompiledReplicatedMapQueryContext.this.checkOnEachPublicOperation(); - return CompiledReplicatedMapQueryContext.this.keyOffset(); - } - - @NotNull - @Override - public Bytes entry() { - CompiledReplicatedMapQueryContext.this.checkOnEachPublicOperation(); - return CompiledReplicatedMapQueryContext.this.entryBytes; - } - - @Override - public long keySize() { - CompiledReplicatedMapQueryContext.this.checkOnEachPublicOperation(); - return CompiledReplicatedMapQueryContext.this.keySize(); - } - - @Override - public long valueSize() { - CompiledReplicatedMapQueryContext.this.checkOnEachPublicOperation(); - return CompiledReplicatedMapQueryContext.this.valueSize(); - } - - @Override - public boolean valueEqualTo(V value) { - CompiledReplicatedMapQueryContext.this.checkOnEachPublicOperation(); - return Data.bytesEquivalent(CompiledReplicatedMapQueryContext.this.entryValue, CompiledReplicatedMapQueryContext.this.wrapValueAsValue(value)); - } - - @Override - public boolean put(V newValue) { - CompiledReplicatedMapQueryContext.this.checkOnEachPublicOperation(); - updateLock().lock(); - MapEntry entry = CompiledReplicatedMapQueryContext.this.entry(); - if (entry != null) { - CompiledReplicatedMapQueryContext.this.replaceValue(entry, CompiledReplicatedMapQueryContext.this.wrapValueAsValue(newValue)); - } else { - CompiledReplicatedMapQueryContext.this.insert(CompiledReplicatedMapQueryContext.this.absentEntry(), CompiledReplicatedMapQueryContext.this.wrapValueAsValue(newValue)); - } - return true; - } - - @Override - public boolean remove() { - CompiledReplicatedMapQueryContext.this.checkOnEachPublicOperation(); - updateLock().lock(); - MapEntry entry = CompiledReplicatedMapQueryContext.this.entry(); - if (entry != null) { - CompiledReplicatedMapQueryContext.this.remove(entry); - return true; - } else { - return false; - } - } - - @Override - public boolean containsKey() { - CompiledReplicatedMapQueryContext.this.checkOnEachPublicOperation(); - return (CompiledReplicatedMapQueryContext.this.entry()) != null; - } - - @Override - public V getUsing(V usingValue) { - return containsKey() ? CompiledReplicatedMapQueryContext.this.value().getUsing(usingValue) : null; - } - - @Override - public V get() { - assert containsKey(); - return CompiledReplicatedMapQueryContext.this.usingReturnValue.returnValue(); - } - - @Override - public void close() { - CompiledReplicatedMapQueryContext.this.checkOnEachPublicOperation(); - put(CompiledReplicatedMapQueryContext.this.usingReturnValue.returnValue()); - CompiledReplicatedMapQueryContext.this.close(); - } - } - - public class DeprecatedMapKeyContextOnQuery implements MapKeyContext { - @NotNull - @Override - public InterProcessLock writeLock() { - return CompiledReplicatedMapQueryContext.this.writeLock(); - } - - @NotNull - @Override - public InterProcessLock readLock() { - return CompiledReplicatedMapQueryContext.this.readLock(); - } - - @NotNull - @Override - public InterProcessLock updateLock() { - return CompiledReplicatedMapQueryContext.this.updateLock(); - } - - @Override - public long valueSize() { - CompiledReplicatedMapQueryContext.this.checkOnEachPublicOperation(); - return CompiledReplicatedMapQueryContext.this.valueSize(); - } - - @Override - public void close() { - CompiledReplicatedMapQueryContext.this.checkOnEachPublicOperation(); - CompiledReplicatedMapQueryContext.this.close(); - } - - @NotNull - @Override - public K key() { - CompiledReplicatedMapQueryContext.this.checkOnEachPublicOperation(); - return CompiledReplicatedMapQueryContext.this.queriedKey().get(); - } - - @Override - public boolean valueEqualTo(V value) { - CompiledReplicatedMapQueryContext.this.checkOnEachPublicOperation(); - return Data.bytesEquivalent(CompiledReplicatedMapQueryContext.this.entryValue, CompiledReplicatedMapQueryContext.this.wrapValueAsValue(value)); - } - - @Override - public long valueOffset() { - CompiledReplicatedMapQueryContext.this.checkOnEachPublicOperation(); - return CompiledReplicatedMapQueryContext.this.valueOffset(); - } - - @NotNull - @Override - public Bytes entry() { - CompiledReplicatedMapQueryContext.this.checkOnEachPublicOperation(); - return CompiledReplicatedMapQueryContext.this.entryBytes; - } - - @Override - public long keyOffset() { - CompiledReplicatedMapQueryContext.this.checkOnEachPublicOperation(); - return CompiledReplicatedMapQueryContext.this.keyOffset(); - } - - @Override - public boolean remove() { - CompiledReplicatedMapQueryContext.this.checkOnEachPublicOperation(); - updateLock().lock(); - MapEntry entry = CompiledReplicatedMapQueryContext.this.entry(); - if (entry != null) { - CompiledReplicatedMapQueryContext.this.remove(entry); - return true; - } else { - return false; - } - } - - @Override - public boolean put(V newValue) { - CompiledReplicatedMapQueryContext.this.checkOnEachPublicOperation(); - updateLock().lock(); - MapEntry entry = CompiledReplicatedMapQueryContext.this.entry(); - if (entry != null) { - CompiledReplicatedMapQueryContext.this.replaceValue(entry, CompiledReplicatedMapQueryContext.this.wrapValueAsValue(newValue)); - } else { - CompiledReplicatedMapQueryContext.this.insert(CompiledReplicatedMapQueryContext.this.absentEntry(), CompiledReplicatedMapQueryContext.this.wrapValueAsValue(newValue)); - } - return true; - } - - @Override - public boolean containsKey() { - CompiledReplicatedMapQueryContext.this.checkOnEachPublicOperation(); - return (CompiledReplicatedMapQueryContext.this.entry()) != null; - } - - @Override - public V getUsing(V usingValue) { - return containsKey() ? CompiledReplicatedMapQueryContext.this.value().getUsing(usingValue) : null; - } - - @Override - public V get() { - return containsKey() ? CompiledReplicatedMapQueryContext.this.value().get() : null; - } - - @Override - public long keySize() { - CompiledReplicatedMapQueryContext.this.checkOnEachPublicOperation(); - return CompiledReplicatedMapQueryContext.this.keySize(); - } - } - - public class DummyValueZeroData extends AbstractData { - @Override - public long size() { - return CompiledReplicatedMapQueryContext.this.m().valueSizeMarshaller.minEncodableSize(); - } - - @Override - public RandomDataInput bytes() { - return ZeroRandomDataInput.INSTANCE; - } - - @Override - public V get() { - throw new UnsupportedOperationException(); - } - - @Override - public V getUsing(V usingInstance) { - throw new UnsupportedOperationException(); - } - - @Override - public long offset() { - return 0; - } - } - - public class EntryKeyBytesData extends AbstractData { - @Override - public long offset() { - CompiledReplicatedMapQueryContext.this.checkOnEachPublicOperation(); - return CompiledReplicatedMapQueryContext.this.keyOffset(); - } - - @Override - public RandomDataInput bytes() { - CompiledReplicatedMapQueryContext.this.checkOnEachPublicOperation(); - return CompiledReplicatedMapQueryContext.this.entryBS; - } - - @Override - public long size() { - CompiledReplicatedMapQueryContext.this.checkOnEachPublicOperation(); - return CompiledReplicatedMapQueryContext.this.keySize(); - } - - public void closeEntryKeyBytesDataSizeDependants() { - this.closeEntryKeyBytesDataInnerGetUsingDependants(); - } - - private K innerGetUsing(K usingKey) { - CompiledReplicatedMapQueryContext.this.entryBytes.position(CompiledReplicatedMapQueryContext.this.keyOffset()); - return CompiledReplicatedMapQueryContext.this.keyReader.read(CompiledReplicatedMapQueryContext.this.entryBytes, size(), usingKey); - } - - public void closeEntryKeyBytesDataInnerGetUsingDependants() { - this.closeCachedEntryKey(); - } - - private K cachedEntryKey; - - private boolean cachedEntryKeyRead = false; - - public boolean cachedEntryKeyInit() { - return (this.cachedEntryKeyRead) != false; - } - - private void initCachedEntryKey() { - cachedEntryKey = innerGetUsing(cachedEntryKey); - cachedEntryKeyRead = true; - } - - public K cachedEntryKey() { - if (!(this.cachedEntryKeyInit())) - this.initCachedEntryKey(); - - return this.cachedEntryKey; - } - - public void closeCachedEntryKey() { - if (!(this.cachedEntryKeyInit())) - return ; - - this.cachedEntryKeyRead = false; - } - - @Override - public K get() { - CompiledReplicatedMapQueryContext.this.checkOnEachPublicOperation(); - return cachedEntryKey(); - } - - @Override - public K getUsing(K usingKey) { - CompiledReplicatedMapQueryContext.this.checkOnEachPublicOperation(); - return innerGetUsing(usingKey); - } - } - - public class EntryValueBytesData extends AbstractData { - @Override - public long offset() { - CompiledReplicatedMapQueryContext.this.checkOnEachPublicOperation(); - return CompiledReplicatedMapQueryContext.this.valueOffset(); - } - - @Override - public long size() { - CompiledReplicatedMapQueryContext.this.checkOnEachPublicOperation(); - return CompiledReplicatedMapQueryContext.this.valueSize(); - } - - public void closeEntryValueBytesDataSizeDependants() { - this.closeEntryValueBytesDataInnerGetUsingDependants(); - } - - private V innerGetUsing(V usingValue) { - CompiledReplicatedMapQueryContext.this.entryBytes.position(CompiledReplicatedMapQueryContext.this.valueOffset()); - return CompiledReplicatedMapQueryContext.this.valueReader.read(CompiledReplicatedMapQueryContext.this.entryBytes, size(), usingValue); - } - - public void closeEntryValueBytesDataInnerGetUsingDependants() { - this.closeCachedEntryValue(); - } - - private V cachedEntryValue; - - private boolean cachedEntryValueRead = false; - - public boolean cachedEntryValueInit() { - return (this.cachedEntryValueRead) != false; - } - - private void initCachedEntryValue() { - cachedEntryValue = innerGetUsing(cachedEntryValue); - cachedEntryValueRead = true; - } - - public V cachedEntryValue() { - if (!(this.cachedEntryValueInit())) - this.initCachedEntryValue(); - - return this.cachedEntryValue; - } - - public void closeCachedEntryValue() { - if (!(this.cachedEntryValueInit())) - return ; - - this.cachedEntryValueRead = false; - } - - @Override - public V get() { - CompiledReplicatedMapQueryContext.this.checkOnEachPublicOperation(); - return cachedEntryValue(); - } - - @Override - public V getUsing(V usingValue) { - CompiledReplicatedMapQueryContext.this.checkOnEachPublicOperation(); - return innerGetUsing(usingValue); - } - - @Override - public RandomDataInput bytes() { - CompiledReplicatedMapQueryContext.this.checkOnEachPublicOperation(); - return CompiledReplicatedMapQueryContext.this.entryBS; - } - } - - public class InputFirstValueBytesData extends AbstractData { - @Override - public RandomDataInput bytes() { - return CompiledReplicatedMapQueryContext.this.inputStore; - } - - @Override - public long offset() { - return CompiledReplicatedMapQueryContext.this.firstInputValueOffset(); - } - - @Override - public long size() { - return CompiledReplicatedMapQueryContext.this.firstInputValueSize(); - } - - public void closeInputFirstValueBytesDataSizeDependants() { - this.closeInputFirstValueBytesDataGetUsingDependants(); - } - - @Override - public V getUsing(V usingValue) { - CompiledReplicatedMapQueryContext.this.inputBytes().position(CompiledReplicatedMapQueryContext.this.firstInputValueOffset()); - return CompiledReplicatedMapQueryContext.this.valueReader.read(CompiledReplicatedMapQueryContext.this.inputBytes(), size(), usingValue); - } - - public void closeInputFirstValueBytesDataGetUsingDependants() { - this.closeCachedBytesInputFirstValue(); - } - - private V cachedBytesInputFirstValue; - - private boolean cachedBytesInputFirstValueRead = false; - - public boolean cachedBytesInputFirstValueInit() { - return (this.cachedBytesInputFirstValueRead) != false; - } - - private void initCachedBytesInputFirstValue() { - cachedBytesInputFirstValue = getUsing(cachedBytesInputFirstValue); - cachedBytesInputFirstValueRead = true; - } - - public V cachedBytesInputFirstValue() { - if (!(this.cachedBytesInputFirstValueInit())) - this.initCachedBytesInputFirstValue(); - - return this.cachedBytesInputFirstValue; - } - - public void closeCachedBytesInputFirstValue() { - if (!(this.cachedBytesInputFirstValueInit())) - return ; - - this.cachedBytesInputFirstValueRead = false; - } - - @Override - public V get() { - return cachedBytesInputFirstValue(); - } - } - - public class InputKeyBytesData extends AbstractData { - @Override - public RandomDataInput bytes() { - return CompiledReplicatedMapQueryContext.this.inputStore; - } - - @Override - public long offset() { - return CompiledReplicatedMapQueryContext.this.inputKeyOffset(); - } - - @Override - public long size() { - return CompiledReplicatedMapQueryContext.this.inputKeySize(); - } - - public void closeInputKeyBytesDataSizeDependants() { - this.closeInputKeyBytesDataGetUsingDependants(); - } - - @Override - public K getUsing(K usingKey) { - Bytes inputBytes = CompiledReplicatedMapQueryContext.this.inputBytes(); - inputBytes.position(CompiledReplicatedMapQueryContext.this.inputKeyOffset()); - return CompiledReplicatedMapQueryContext.this.keyReader.read(inputBytes, size(), usingKey); - } - - public void closeInputKeyBytesDataGetUsingDependants() { - this.closeCachedBytesInputKey(); - } - - private K cachedBytesInputKey; - - private boolean cachedBytesInputKeyRead = false; - - public boolean cachedBytesInputKeyInit() { - return (this.cachedBytesInputKeyRead) != false; - } - - private void initCachedBytesInputKey() { - cachedBytesInputKey = getUsing(cachedBytesInputKey); - cachedBytesInputKeyRead = true; - } - - public K cachedBytesInputKey() { - if (!(this.cachedBytesInputKeyInit())) - this.initCachedBytesInputKey(); - - return this.cachedBytesInputKey; - } - - public void closeCachedBytesInputKey() { - if (!(this.cachedBytesInputKeyInit())) - return ; - - this.cachedBytesInputKeyRead = false; - } - - @Override - public K get() { - return cachedBytesInputKey(); - } - } - - public class InputSecondValueBytesData extends AbstractData { - @Override - public RandomDataInput bytes() { - return CompiledReplicatedMapQueryContext.this.inputStore; - } - - @Override - public long offset() { - return CompiledReplicatedMapQueryContext.this.secondInputValueOffset(); - } - - @Override - public long size() { - return CompiledReplicatedMapQueryContext.this.secondInputValueSize(); - } - - public void closeInputSecondValueBytesDataSizeDependants() { - this.closeInputSecondValueBytesDataGetUsingDependants(); - } - - @Override - public V getUsing(V usingValue) { - CompiledReplicatedMapQueryContext.this.inputBytes().position(CompiledReplicatedMapQueryContext.this.secondInputValueOffset()); - return CompiledReplicatedMapQueryContext.this.valueReader.read(CompiledReplicatedMapQueryContext.this.inputBytes(), size(), usingValue); - } - - public void closeInputSecondValueBytesDataGetUsingDependants() { - this.closeCachedBytesInputSecondValue(); - } - - private V cachedBytesInputSecondValue; - - private boolean cachedBytesInputSecondValueRead = false; - - public boolean cachedBytesInputSecondValueInit() { - return (this.cachedBytesInputSecondValueRead) != false; - } - - private void initCachedBytesInputSecondValue() { - cachedBytesInputSecondValue = getUsing(cachedBytesInputSecondValue); - cachedBytesInputSecondValueRead = true; - } - - public V cachedBytesInputSecondValue() { - if (!(this.cachedBytesInputSecondValueInit())) - this.initCachedBytesInputSecondValue(); - - return this.cachedBytesInputSecondValue; - } - - public void closeCachedBytesInputSecondValue() { - if (!(this.cachedBytesInputSecondValueInit())) - return ; - - this.cachedBytesInputSecondValueRead = false; - } - - @Override - public V get() { - return cachedBytesInputSecondValue(); - } - } - - public class ReadLock implements InterProcessLock { - @Override - public void lockInterruptibly() throws InterruptedException { - if ((CompiledReplicatedMapQueryContext.this.localLockState()) == (LocalLockState.UNLOCKED)) { - CompiledReplicatedMapQueryContext.this.segmentHeader().readLockInterruptibly(CompiledReplicatedMapQueryContext.this.segmentHeaderAddress()); - CompiledReplicatedMapQueryContext.this.setLocalLockStateGuarded(LocalLockState.READ_LOCKED); - } - } - - @Override - public void lock() { - if ((CompiledReplicatedMapQueryContext.this.localLockState()) == (LocalLockState.UNLOCKED)) { - CompiledReplicatedMapQueryContext.this.segmentHeader().readLock(CompiledReplicatedMapQueryContext.this.segmentHeaderAddress()); - CompiledReplicatedMapQueryContext.this.setLocalLockStateGuarded(LocalLockState.READ_LOCKED); - } - } - - public void closeReadLockLockDependants() { - CompiledReplicatedMapQueryContext.this.closeHashLookupPos(); - } - - @Override - public boolean isHeldByCurrentThread() { - return CompiledReplicatedMapQueryContext.this.localLockState().read; - } - - @Override - public void unlock() { - switch (CompiledReplicatedMapQueryContext.this.localLockState()) { - case UNLOCKED : - return ; - case READ_LOCKED : - CompiledReplicatedMapQueryContext.this.segmentHeader().readUnlock(CompiledReplicatedMapQueryContext.this.segmentHeaderAddress()); - break; - case UPDATE_LOCKED : - CompiledReplicatedMapQueryContext.this.segmentHeader().updateUnlock(CompiledReplicatedMapQueryContext.this.segmentHeaderAddress()); - break; - case WRITE_LOCKED : - CompiledReplicatedMapQueryContext.this.segmentHeader().writeUnlock(CompiledReplicatedMapQueryContext.this.segmentHeaderAddress()); - } - CompiledReplicatedMapQueryContext.this.setLocalLockStateGuarded(LocalLockState.UNLOCKED); - CompiledReplicatedMapQueryContext.this.closeHashLookupPos(); - CompiledReplicatedMapQueryContext.this.closePos(); - } - - @Override - public boolean tryLock(long time, @NotNull - TimeUnit unit) throws InterruptedException { - if ((CompiledReplicatedMapQueryContext.this.localLockState()) == (LocalLockState.UNLOCKED)) { - if (CompiledReplicatedMapQueryContext.this.segmentHeader().tryReadLock(CompiledReplicatedMapQueryContext.this.segmentHeaderAddress(), time, unit)) { - CompiledReplicatedMapQueryContext.this.setLocalLockStateGuarded(LocalLockState.READ_LOCKED); - return true; - } else { - return false; - } - } else { - return true; - } - } - - @Override - public boolean tryLock() { - if ((CompiledReplicatedMapQueryContext.this.localLockState()) == (LocalLockState.UNLOCKED)) { - if (CompiledReplicatedMapQueryContext.this.segmentHeader().tryReadLock(CompiledReplicatedMapQueryContext.this.segmentHeaderAddress())) { - CompiledReplicatedMapQueryContext.this.setLocalLockStateGuarded(LocalLockState.READ_LOCKED); - return true; - } else { - return false; - } - } else { - return true; - } - } - } - - public class ReplicatedInputKeyBytesData extends AbstractData { - @Override - public RandomDataInput bytes() { - return CompiledReplicatedMapQueryContext.this.replicatedInputStore; - } - - @Override - public long offset() { - return CompiledReplicatedMapQueryContext.this.riKeyOffset(); - } - - @Override - public long size() { - return CompiledReplicatedMapQueryContext.this.riKeySize(); - } - - public void closeReplicatedInputKeyBytesDataSizeDependants() { - this.closeReplicatedInputKeyBytesDataGetUsingDependants(); - } - - @Override - public K getUsing(K usingKey) { - Bytes inputBytes = CompiledReplicatedMapQueryContext.this.replicatedInputBytes(); - inputBytes.position(CompiledReplicatedMapQueryContext.this.riKeyOffset()); - return CompiledReplicatedMapQueryContext.this.keyReader.read(inputBytes, size(), usingKey); - } - - public void closeReplicatedInputKeyBytesDataGetUsingDependants() { - this.closeCachedBytesReplicatedInputKey(); - } - - private K cachedBytesReplicatedInputKey; - - private boolean cachedBytesReplicatedInputKeyRead = false; - - public boolean cachedBytesReplicatedInputKeyInit() { - return (this.cachedBytesReplicatedInputKeyRead) != false; - } - - private void initCachedBytesReplicatedInputKey() { - cachedBytesReplicatedInputKey = getUsing(cachedBytesReplicatedInputKey); - cachedBytesReplicatedInputKeyRead = true; - } - - public K cachedBytesReplicatedInputKey() { - if (!(this.cachedBytesReplicatedInputKeyInit())) - this.initCachedBytesReplicatedInputKey(); - - return this.cachedBytesReplicatedInputKey; - } - - public void closeCachedBytesReplicatedInputKey() { - if (!(this.cachedBytesReplicatedInputKeyInit())) - return ; - - this.cachedBytesReplicatedInputKeyRead = false; - } - - @Override - public K get() { - return cachedBytesReplicatedInputKey(); - } - } - - public class ReplicatedInputValueBytesData extends AbstractData { - @Override - public RandomDataInput bytes() { - return CompiledReplicatedMapQueryContext.this.replicatedInputStore; - } - - @Override - public long size() { - return CompiledReplicatedMapQueryContext.this.riValueSize(); - } - - public void closeReplicatedInputValueBytesDataSizeDependants() { - this.closeReplicatedInputValueBytesDataGetUsingDependants(); - } - - @Override - public V getUsing(V usingValue) { - Bytes inputBytes = CompiledReplicatedMapQueryContext.this.replicatedInputBytes(); - inputBytes.position(CompiledReplicatedMapQueryContext.this.riValueOffset()); - return CompiledReplicatedMapQueryContext.this.valueReader.read(inputBytes, size(), usingValue); - } - - public void closeReplicatedInputValueBytesDataGetUsingDependants() { - this.closeCachedBytesReplicatedInputValue(); - } - - private V cachedBytesReplicatedInputValue; - - private boolean cachedBytesReplicatedInputValueRead = false; - - public boolean cachedBytesReplicatedInputValueInit() { - return (this.cachedBytesReplicatedInputValueRead) != false; - } - - private void initCachedBytesReplicatedInputValue() { - cachedBytesReplicatedInputValue = getUsing(cachedBytesReplicatedInputValue); - cachedBytesReplicatedInputValueRead = true; - } - - public V cachedBytesReplicatedInputValue() { - if (!(this.cachedBytesReplicatedInputValueInit())) - this.initCachedBytesReplicatedInputValue(); - - return this.cachedBytesReplicatedInputValue; - } - - public void closeCachedBytesReplicatedInputValue() { - if (!(this.cachedBytesReplicatedInputValueInit())) - return ; - - this.cachedBytesReplicatedInputValueRead = false; - } - - @Override - public V get() { - return cachedBytesReplicatedInputValue(); - } - - @Override - public long offset() { - return CompiledReplicatedMapQueryContext.this.riValueOffset(); - } - } - - public class ReplicatedMapAbsentDelegating implements MapAbsentEntry { - @NotNull - @Override - public Data absentKey() { - return CompiledReplicatedMapQueryContext.this.absentKey(); - } - - @NotNull - @Override - public Data defaultValue() { - return CompiledReplicatedMapQueryContext.this.defaultValue(); - } - - @NotNull - @Override - public MapContext context() { - return CompiledReplicatedMapQueryContext.this.context(); - } - - @Override - public void doInsert(Data value) { - CompiledReplicatedMapQueryContext.this.doInsert(value); - } - } - - public class UpdateLock implements InterProcessLock { - @NotNull - private IllegalMonitorStateException forbiddenUpgrade() { - return new IllegalMonitorStateException("Cannot upgrade from read to update lock"); - } - - @Override - public void lockInterruptibly() throws InterruptedException { - switch (CompiledReplicatedMapQueryContext.this.localLockState()) { - case UNLOCKED : - CompiledReplicatedMapQueryContext.this.segmentHeader().updateLockInterruptibly(CompiledReplicatedMapQueryContext.this.segmentHeaderAddress()); - CompiledReplicatedMapQueryContext.this.setLocalLockStateGuarded(LocalLockState.UPDATE_LOCKED); - return ; - case READ_LOCKED : - throw forbiddenUpgrade(); - case UPDATE_LOCKED : - case WRITE_LOCKED : - } - } - - @Override - public boolean isHeldByCurrentThread() { - return CompiledReplicatedMapQueryContext.this.localLockState().update; - } - - @Override - public void unlock() { - switch (CompiledReplicatedMapQueryContext.this.localLockState()) { - case UNLOCKED : - case READ_LOCKED : - return ; - case UPDATE_LOCKED : - CompiledReplicatedMapQueryContext.this.segmentHeader().downgradeUpdateToReadLock(CompiledReplicatedMapQueryContext.this.segmentHeaderAddress()); - break; - case WRITE_LOCKED : - CompiledReplicatedMapQueryContext.this.segmentHeader().downgradeWriteToReadLock(CompiledReplicatedMapQueryContext.this.segmentHeaderAddress()); - } - CompiledReplicatedMapQueryContext.this.setLocalLockStateGuarded(LocalLockState.READ_LOCKED); - } - - @Override - public void lock() { - switch (CompiledReplicatedMapQueryContext.this.localLockState()) { - case UNLOCKED : - CompiledReplicatedMapQueryContext.this.segmentHeader().updateLock(CompiledReplicatedMapQueryContext.this.segmentHeaderAddress()); - CompiledReplicatedMapQueryContext.this.setLocalLockStateGuarded(LocalLockState.UPDATE_LOCKED); - return ; - case READ_LOCKED : - throw forbiddenUpgrade(); - case UPDATE_LOCKED : - case WRITE_LOCKED : - } - } - - @Override - public boolean tryLock(long time, @NotNull - TimeUnit unit) throws InterruptedException { - switch (CompiledReplicatedMapQueryContext.this.localLockState()) { - case UNLOCKED : - if (CompiledReplicatedMapQueryContext.this.segmentHeader().tryUpdateLock(CompiledReplicatedMapQueryContext.this.segmentHeaderAddress(), time, unit)) { - CompiledReplicatedMapQueryContext.this.setLocalLockStateGuarded(LocalLockState.UPDATE_LOCKED); - return true; - } else { - return false; - } - case READ_LOCKED : - throw forbiddenUpgrade(); - case UPDATE_LOCKED : - case WRITE_LOCKED : - return true; - } - throw new AssertionError(); - } - - @Override - public boolean tryLock() { - switch (CompiledReplicatedMapQueryContext.this.localLockState()) { - case UNLOCKED : - if (CompiledReplicatedMapQueryContext.this.segmentHeader().tryUpdateLock(CompiledReplicatedMapQueryContext.this.segmentHeaderAddress())) { - CompiledReplicatedMapQueryContext.this.setLocalLockStateGuarded(LocalLockState.UPDATE_LOCKED); - return true; - } else { - return false; - } - case READ_LOCKED : - throw forbiddenUpgrade(); - case UPDATE_LOCKED : - case WRITE_LOCKED : - return true; - } - throw new AssertionError(); - } - } - - public class WrappedValueInstanceData extends CopyingInstanceData { - public WrappedValueInstanceData getUnusedWrappedValueGuarded() { - assert this.nextInit() : "Next should be init"; - return getUnusedWrappedValue(); - } - - public WrappedValueInstanceData getUnusedWrappedValue() { - if (!(valueInit())) - return this; - - if ((next) == null) - next = new WrappedValueInstanceData(); - - return next.getUnusedWrappedValue(); - } - - private WrappedValueInstanceData next; - - boolean nextInit() { - return true; - } - - void closeNext() { - if (!(this.nextInit())) - return ; - - } - - private V value; - - public boolean valueInit() { - return (value) != null; - } - - public void initValue(V value) { - CompiledReplicatedMapQueryContext.this.m().checkValue(value); - this.value = value; - this.closeValueDependants(); - } - - public V value() { - assert this.valueInit() : "Value should be init"; - return this.value; - } - - public void closeValue() { - if (!(this.valueInit())) - return ; - - this.closeValueDependants(); - value = null; - if ((next) != null) - next.closeValue(); - - } - - public void closeValueDependants() { - this.closeBuffer(); - } - - @Override - public V instance() { - return value(); - } - - private boolean marshalled = false; - - private DirectBytes buf; - - public boolean bufferInit() { - return (this.marshalled) != false; - } - - private void initBuffer() { - MVI mvi = CompiledReplicatedMapQueryContext.this.valueMetaInterop(value()); - long size = mvi.size(CompiledReplicatedMapQueryContext.this.valueInterop, value()); - buf = getBuffer(this.buf, size); - mvi.write(CompiledReplicatedMapQueryContext.this.valueInterop, buf, value()); - buf.flip(); - marshalled = true; - } - - public DirectBytes buf() { - if (!(this.bufferInit())) - this.initBuffer(); - - return this.buf; - } - - public void closeBuffer() { - if (!(this.bufferInit())) - return ; - - this.marshalled = false; - } - - @Override - public V getUsing(V usingValue) { - buf().position(0); - return CompiledReplicatedMapQueryContext.this.valueReader.read(buf(), buf().limit(), usingValue); - } - - @Override - public DirectBytes buffer() { - return buf(); - } - } - - public class WriteLock implements InterProcessLock { - @NotNull - private IllegalMonitorStateException forbiddenUpgrade() { - return new IllegalMonitorStateException("Cannot upgrade from read to write lock"); - } - - @Override - public boolean tryLock(long time, @NotNull - TimeUnit unit) throws InterruptedException { - switch (CompiledReplicatedMapQueryContext.this.localLockState()) { - case UNLOCKED : - if (CompiledReplicatedMapQueryContext.this.segmentHeader().tryWriteLock(CompiledReplicatedMapQueryContext.this.segmentHeaderAddress(), time, unit)) { - CompiledReplicatedMapQueryContext.this.setLocalLockStateGuarded(LocalLockState.WRITE_LOCKED); - return true; - } else { - return false; - } - case READ_LOCKED : - throw forbiddenUpgrade(); - case UPDATE_LOCKED : - if (CompiledReplicatedMapQueryContext.this.segmentHeader().tryUpgradeUpdateToWriteLock(CompiledReplicatedMapQueryContext.this.segmentHeaderAddress(), time, unit)) { - CompiledReplicatedMapQueryContext.this.setLocalLockStateGuarded(LocalLockState.WRITE_LOCKED); - return true; - } else { - return false; - } - case WRITE_LOCKED : - return true; - } - throw new AssertionError(); - } - - @Override - public boolean tryLock() { - switch (CompiledReplicatedMapQueryContext.this.localLockState()) { - case UNLOCKED : - if (CompiledReplicatedMapQueryContext.this.segmentHeader().tryWriteLock(CompiledReplicatedMapQueryContext.this.segmentHeaderAddress())) { - CompiledReplicatedMapQueryContext.this.setLocalLockStateGuarded(LocalLockState.WRITE_LOCKED); - return true; - } else { - return false; - } - case READ_LOCKED : - throw forbiddenUpgrade(); - case UPDATE_LOCKED : - if (CompiledReplicatedMapQueryContext.this.segmentHeader().tryUpgradeUpdateToWriteLock(CompiledReplicatedMapQueryContext.this.segmentHeaderAddress())) { - CompiledReplicatedMapQueryContext.this.setLocalLockStateGuarded(LocalLockState.WRITE_LOCKED); - return true; - } else { - return false; - } - case WRITE_LOCKED : - return true; - } - throw new AssertionError(); - } - - @Override - public void lockInterruptibly() throws InterruptedException { - switch (CompiledReplicatedMapQueryContext.this.localLockState()) { - case UNLOCKED : - CompiledReplicatedMapQueryContext.this.segmentHeader().writeLockInterruptibly(CompiledReplicatedMapQueryContext.this.segmentHeaderAddress()); - CompiledReplicatedMapQueryContext.this.setLocalLockStateGuarded(LocalLockState.WRITE_LOCKED); - return ; - case READ_LOCKED : - throw forbiddenUpgrade(); - case UPDATE_LOCKED : - CompiledReplicatedMapQueryContext.this.segmentHeader().upgradeUpdateToWriteLockInterruptibly(CompiledReplicatedMapQueryContext.this.segmentHeaderAddress()); - CompiledReplicatedMapQueryContext.this.setLocalLockStateGuarded(LocalLockState.WRITE_LOCKED); - case WRITE_LOCKED : - } - } - - @Override - public void unlock() { - switch (CompiledReplicatedMapQueryContext.this.localLockState()) { - case UNLOCKED : - case READ_LOCKED : - case UPDATE_LOCKED : - return ; - case WRITE_LOCKED : - CompiledReplicatedMapQueryContext.this.segmentHeader().downgradeWriteToUpdateLock(CompiledReplicatedMapQueryContext.this.segmentHeaderAddress()); - } - CompiledReplicatedMapQueryContext.this.setLocalLockStateGuarded(LocalLockState.UPDATE_LOCKED); - } - - @Override - public boolean isHeldByCurrentThread() { - return CompiledReplicatedMapQueryContext.this.localLockState().write; - } - - @Override - public void lock() { - switch (CompiledReplicatedMapQueryContext.this.localLockState()) { - case UNLOCKED : - CompiledReplicatedMapQueryContext.this.segmentHeader().writeLock(CompiledReplicatedMapQueryContext.this.segmentHeaderAddress()); - CompiledReplicatedMapQueryContext.this.setLocalLockStateGuarded(LocalLockState.WRITE_LOCKED); - return ; - case READ_LOCKED : - throw forbiddenUpgrade(); - case UPDATE_LOCKED : - CompiledReplicatedMapQueryContext.this.segmentHeader().upgradeUpdateToWriteLock(CompiledReplicatedMapQueryContext.this.segmentHeaderAddress()); - CompiledReplicatedMapQueryContext.this.setLocalLockStateGuarded(LocalLockState.WRITE_LOCKED); - case WRITE_LOCKED : - } - } - } - - public enum SearchState { - PRESENT, DELETED, ABSENT; } - - private void _AllocatedChunks_incrementSegmentEntriesIfNeeded() { - } - - private void _CheckOnEachPublicOperation_checkOnEachPublicOperation() { - this.checkAccessingFromOwnerThread(); - } - - private void _MapAbsent_doInsert(Data value) { - this.putPrefix(); - if (!(this.searchStatePresent())) { - if (this.searchStateDeleted()) { - this.putValueDeletedEntry(value); - } else { - putEntry(value); - } - this.incrementModCountGuarded(); - this.setSearchStateGuarded(CompiledReplicatedMapQueryContext.SearchState.PRESENT); - } else { - throw new IllegalStateException("Entry is present in the map when doInsert() is called"); - } - } - - private void _MapEntryStages_putValueDeletedEntry(Data newValue) { - assert this.innerUpdateLock.isHeldByCurrentThread(); - int newSizeInChunks; - long entryStartOffset = keySizeOffset(); - long newSizeOfEverythingBeforeValue = -1; - boolean newValueSizeIsDifferent = (newValue.size()) != (valueSize()); - if (newValueSizeIsDifferent) { - newSizeOfEverythingBeforeValue = newSizeOfEverythingBeforeValue(newValue); - long newValueOffset = this.m().alignment.alignAddr((entryStartOffset + newSizeOfEverythingBeforeValue)); - long newEntrySize = (newValueOffset + (newValue.size())) - entryStartOffset; - newSizeInChunks = this.m().inChunks(newEntrySize); - } else { - newSizeInChunks = entrySizeInChunks(); - } - if ((((pos()) + newSizeInChunks) < (this.freeList().size())) && (this.freeList().allClear(pos(), ((pos()) + newSizeInChunks)))) { - this.freeList().set(pos(), ((pos()) + newSizeInChunks)); - this.innerWriteLock.lock(); - this.incrementSegmentEntriesIfNeeded(); - if (newValueSizeIsDifferent) { - initValue(newValue); - } else { - writeValue(newValue); - } - } else { - if (newValueSizeIsDifferent) { - assert newSizeOfEverythingBeforeValue >= 0; - } else { - newSizeOfEverythingBeforeValue = newSizeOfEverythingBeforeValue(newValue); - } - long entrySize = innerEntrySize(newSizeOfEverythingBeforeValue, newValue.size()); - if (newValueSizeIsDifferent) { - this.initEntryAndKeyCopying(entrySize, ((valueSizeOffset()) - entryStartOffset)); - initValue(newValue); - } else { - long oldValueSizeOffset = valueSizeOffset(); - long oldValueSize = valueSize(); - long oldValueOffset = valueOffset(); - this.initEntryAndKeyCopying(entrySize, ((valueOffset()) - entryStartOffset)); - initValueWithoutSize(newValue, oldValueSizeOffset, oldValueSize, oldValueOffset); - } - freeExtraAllocatedChunks(); - } - this.putValueVolatile(this.hashLookupPos(), pos()); - } - - private void _MapQuery_doRemove() { - this.checkOnEachPublicOperation(); - this.innerUpdateLock.lock(); - if (searchStatePresent()) { - this.innerWriteLock.lock(); - this.remove(); - this.innerRemoveEntryExceptHashLookupUpdate(); - setSearchStateGuarded(CompiledReplicatedMapQueryContext.SearchState.DELETED); - } else { - throw new IllegalStateException("Entry is absent when doRemove() is called"); - } - } - - private void _MapQuery_doReplaceValue(Data newValue) { - putPrefix(); - if (searchStatePresent()) { - this.innerDefaultReplaceValue(newValue); - this.incrementModCountGuarded(); - setSearchStateGuarded(CompiledReplicatedMapQueryContext.SearchState.PRESENT); - } else { - throw new IllegalStateException("Entry is absent in the map when doReplaceValue() is called"); - } - } - - public void incrementModCount() { - contextModCount = rootContextOnThisSegment.latestSameThreadSegmentModCount = (rootContextOnThisSegment.latestSameThreadSegmentModCount) + 1; - } - - public void setHashLookupPos(long hashLookupPos) { - this.hashLookupPos = hashLookupPos; - } - - public void setLocalLockState(LocalLockState newState) { - localLockState = newState; - } - - public void setSearchState(CompiledReplicatedMapQueryContext.SearchState newSearchState) { - this.searchState = newSearchState; - } - - final Thread owner; - - public Thread owner() { - return this.owner; - } - - private void closeNestedLocks() { - unlinkFromSegmentContextsChain(); - switch (localLockState) { - case UNLOCKED : - break; - case READ_LOCKED : - int newTotalReadLockCount = this.rootContextOnThisSegment.totalReadLockCount -= 1; - if (newTotalReadLockCount == 0) { - if (((this.rootContextOnThisSegment.totalUpdateLockCount) == 0) && ((this.rootContextOnThisSegment.totalWriteLockCount) == 0)) { - segmentHeader().readUnlock(segmentHeaderAddress()); - } - } else if (newTotalReadLockCount < 0) { - throw new IllegalStateException("read underflow"); - } - break; - case UPDATE_LOCKED : - int newTotalUpdateLockCount = this.rootContextOnThisSegment.totalUpdateLockCount -= 1; - if (newTotalUpdateLockCount == 0) { - if ((this.rootContextOnThisSegment.totalWriteLockCount) == 0) { - if ((this.rootContextOnThisSegment.totalReadLockCount) == 0) { - segmentHeader().updateUnlock(segmentHeaderAddress()); - } else { - segmentHeader().downgradeUpdateToReadLock(segmentHeaderAddress()); - } - } - } else if (newTotalUpdateLockCount < 0) { - throw new IllegalStateException("update underflow"); - } - break; - case WRITE_LOCKED : - int newTotalWriteLockCount = this.rootContextOnThisSegment.totalWriteLockCount -= 1; - if (newTotalWriteLockCount == 0) { - if ((this.rootContextOnThisSegment.totalUpdateLockCount) > 0) { - segmentHeader().downgradeWriteToUpdateLock(segmentHeaderAddress()); - } else { - if ((this.rootContextOnThisSegment.totalReadLockCount) > 0) { - segmentHeader().downgradeWriteToReadLock(segmentHeaderAddress()); - } else { - segmentHeader().writeUnlock(segmentHeaderAddress()); - } - } - } - break; - } - } - - private void closeRootLocks() { - assert (nextNode) == null; - switch (localLockState) { - case UNLOCKED : - return ; - case READ_LOCKED : - segmentHeader().readUnlock(segmentHeaderAddress()); - return ; - case UPDATE_LOCKED : - segmentHeader().updateUnlock(segmentHeaderAddress()); - return ; - case WRITE_LOCKED : - segmentHeader().writeUnlock(segmentHeaderAddress()); - } - } - - private void innerInitSegmentHashLookup(long address, long capacity, int entrySize, int keyBits, int valueBits) { - this.address = address; - this.capacityMask = capacity - 1L; - this.hashLookupEntrySize = entrySize; - this.capacityMask2 = (capacityMask) * entrySize; - this.keyBits = keyBits; - this.keyMask = CompiledReplicatedMapQueryContext.mask(keyBits); - this.valueMask = CompiledReplicatedMapQueryContext.mask(valueBits); - this.entryMask = CompiledReplicatedMapQueryContext.mask((keyBits + valueBits)); - } - - private void unlinkFromSegmentContextsChain() { - CompiledReplicatedMapQueryContext prevContext = this.rootContextOnThisSegment; - while (true) { - assert (prevContext.nextNode) != null; - if ((prevContext.nextNode) == (this)) - break; - - prevContext = prevContext.nextNode; - } - assert (nextNode) == null; - prevContext.nextNode = null; - } - - private boolean _MapQuery_entryPresent() { - return searchStatePresent(); - } - - private long _HashEntryStages_entryEnd() { - return keyEnd(); - } - - private void _MapEntryStages_relocation(Data newValue, long newSizeOfEverythingBeforeValue) { - this.free(pos(), entrySizeInChunks()); - long entrySize = innerEntrySize(newSizeOfEverythingBeforeValue, newValue.size()); - this.initEntryAndKeyCopying(entrySize, ((valueSizeOffset()) - (keySizeOffset()))); - writeValueAndPutPos(newValue); - } - - private CompiledReplicatedMapQueryContext _Chaining_createChaining() { - return new CompiledReplicatedMapQueryContext(this); - } - - public final int indexInContextChain; - - public int indexInContextChain() { - return this.indexInContextChain; - } - - public class DefaultReturnValue implements InstanceReturnValue { - @Override - public void returnValue(@NotNull - Data value) { - initDefaultReturnedValue(value); - } - - private V defaultReturnedValue = null; - - boolean defaultReturnedValueInit() { - return (this.defaultReturnedValue) != null; - } - - private void initDefaultReturnedValue(@NotNull - Data value) { - defaultReturnedValue = value.getUsing(null); - } - - public V defaultReturnedValue() { - assert this.defaultReturnedValueInit() : "DefaultReturnedValue should be init"; - return this.defaultReturnedValue; - } - - public void closeDefaultReturnedValue() { - if (!(this.defaultReturnedValueInit())) - return ; - - this.defaultReturnedValue = null; - } - - @Override - public V returnValue() { - if (defaultReturnedValueInit()) { - return defaultReturnedValue(); - } else { - return null; - } - } - } - - public class InputKeyInstanceData extends CopyingInstanceData implements KeyInitableData { - private K key = null; - - public boolean keyInit() { - return (this.key) != null; - } - - @Override - public void initKey(K key) { - this.key = key; - this.closeKeyDependants(); - } - - public K key() { - assert this.keyInit() : "Key should be init"; - return this.key; - } - - public void closeKey() { - if (!(this.keyInit())) - return ; - - this.closeKeyDependants(); - this.key = null; - } - - public void closeKeyDependants() { - this.closeBuffer(); - } - - @Override - public K instance() { - return key(); - } - - private boolean marshalled = false; - - private DirectBytes buffer; - - public boolean bufferInit() { - return (this.marshalled) != false; - } - - private void initBuffer() { - MKI mki = CompiledReplicatedMapQueryContext.this.keyMetaInterop(key()); - long size = mki.size(CompiledReplicatedMapQueryContext.this.keyInterop, key()); - buffer = getBuffer(this.buffer, size); - mki.write(CompiledReplicatedMapQueryContext.this.keyInterop, buffer, key()); - buffer.flip(); - marshalled = true; - } - - public DirectBytes buffer() { - if (!(this.bufferInit())) - this.initBuffer(); - - return this.buffer; - } - - public void closeBuffer() { - if (!(this.bufferInit())) - return ; - - this.marshalled = false; - } - - @Override - public K getUsing(K usingKey) { - buffer().position(0); - return CompiledReplicatedMapQueryContext.this.keyReader.read(buffer(), buffer().limit(), usingKey); - } - } - - public class InputValueInstanceData extends CopyingInstanceData implements ValueInitableData { - private V value = null; - - public boolean valueInit() { - return (this.value) != null; - } - - @Override - public void initValue(V value) { - this.value = value; - this.closeValueDependants(); - } - - public V value() { - assert this.valueInit() : "Value should be init"; - return this.value; - } - - public void closeValue() { - if (!(this.valueInit())) - return ; - - this.closeValueDependants(); - this.value = null; - } - - public void closeValueDependants() { - this.closeBuffer(); - } - - @Override - public V instance() { - return value(); - } - - private boolean marshalled = false; - - private DirectBytes buffer; - - public boolean bufferInit() { - return (this.marshalled) != false; - } - - private void initBuffer() { - MVI mvi = CompiledReplicatedMapQueryContext.this.valueMetaInterop(value()); - long size = mvi.size(CompiledReplicatedMapQueryContext.this.valueInterop, value()); - buffer = getBuffer(this.buffer, size); - mvi.write(CompiledReplicatedMapQueryContext.this.valueInterop, buffer, value()); - buffer.flip(); - marshalled = true; - } - - public DirectBytes buffer() { - if (!(this.bufferInit())) - this.initBuffer(); - - return this.buffer; - } - - public void closeBuffer() { - if (!(this.bufferInit())) - return ; - - this.marshalled = false; - } - - @Override - public V getUsing(V usingValue) { - buffer().position(0); - return CompiledReplicatedMapQueryContext.this.valueReader.read(buffer(), buffer().limit(), usingValue); - } - } - - public class UsingReturnValue implements UsableReturnValue { - @Override - public void returnValue(@NotNull - Data value) { - initReturnedValue(value); - } - - private V usingReturnValue = ((V)(UsableReturnValue.USING_RETURN_VALUE_UNINT)); - - public boolean usingReturnValueInit() { - return (this.usingReturnValue) != ((V)(UsableReturnValue.USING_RETURN_VALUE_UNINT)); - } - - @Override - public void initUsingReturnValue(V usingReturnValue) { - this.usingReturnValue = usingReturnValue; - this.closeUsingReturnValueDependants(); - } - - public V usingReturnValue() { - assert this.usingReturnValueInit() : "UsingReturnValue should be init"; - return this.usingReturnValue; - } - - public void closeUsingReturnValue() { - if (!(this.usingReturnValueInit())) - return ; - - this.closeUsingReturnValueDependants(); - this.usingReturnValue = ((V)(UsableReturnValue.USING_RETURN_VALUE_UNINT)); - } - - public void closeUsingReturnValueDependants() { - this.closeReturnedValue(); - } - - private V returnedValue = null; - - boolean returnedValueInit() { - return (this.returnedValue) != null; - } - - private void initReturnedValue(@NotNull - Data value) { - returnedValue = value.getUsing(usingReturnValue()); - } - - public V returnedValue() { - assert this.returnedValueInit() : "ReturnedValue should be init"; - return this.returnedValue; - } - - public void closeReturnedValue() { - if (!(this.returnedValueInit())) - return ; - - this.returnedValue = null; - } - - @Override - public V returnValue() { - if (returnedValueInit()) { - return returnedValue(); - } else { - return null; - } - } - } - - public static int entrySize(int keyBits, int valueBits) { - return ((int)(MemoryUnit.BYTES.alignAndConvert(((long)(keyBits + valueBits)), MemoryUnit.BITS))); - } - - public static int keyBits(long entriesPerSegment, int valueBits) { - int minKeyBits = 64 - (Long.numberOfLeadingZeros((entriesPerSegment - 1L))); - minKeyBits += 3; - int actualEntryBits = ((int)(MemoryUnit.BYTES.align(((long)(minKeyBits + valueBits)), MemoryUnit.BITS))); - return actualEntryBits - valueBits; - } - - public static int valueBits(long actualChunksPerSegment) { - return 64 - (Long.numberOfLeadingZeros((actualChunksPerSegment - 1L))); - } - - public final Bytes entryBytes; - - public Bytes entryBytes() { - return this.entryBytes; - } - - public static long capacityFor(long entriesPerSegment) { - if (entriesPerSegment < 0L) - throw new IllegalArgumentException("entriesPerSegment should be positive"); - - long capacity = Maths.nextPower2(entriesPerSegment, 64L); - if ((((double)(entriesPerSegment)) / ((double)(capacity))) > (2.0 / 3.0)) { - capacity <<= 1L; - } - return capacity; - } - - public static long mask(int bits) { - return (1L << bits) - 1L; - } - - private MapEntry _MapQuery_entry() { - this.checkOnEachPublicOperation(); - return entryPresent() ? this : null; - } - - public static final int MAX_SEGMENT_CHUNKS = 1 << 30; - - public static final int MAX_SEGMENT_ENTRIES = 1 << 29; - - public int MAX_SEGMENT_ENTRIES() { - return this.MAX_SEGMENT_ENTRIES; - } - - public int MAX_SEGMENT_CHUNKS() { - return this.MAX_SEGMENT_CHUNKS; - } - - public static final long UNSET_KEY = 0L; - - public static final long UNSET_ENTRY = 0L; - - public long UNSET_ENTRY() { - return this.UNSET_ENTRY; - } - - public long UNSET_KEY() { - return this.UNSET_KEY; - } - - public final ReadLock innerReadLock; - - public ReadLock innerReadLock() { - return this.innerReadLock; - } - - public static final Logger LOG = LoggerFactory.getLogger(CompiledReplicatedMapQueryContext.class); - - public final WriteLock innerWriteLock; - - public WriteLock innerWriteLock() { - return this.innerWriteLock; - } - - public Logger LOG() { - return this.LOG; - } - - public final List contextChain; - - public final UpdateLock innerUpdateLock; - - public UpdateLock innerUpdateLock() { - return this.innerUpdateLock; - } - - public List contextChain() { - return this.contextChain; - } - - @Nullable - private MapAbsentEntry _MapQuery_absentEntry() { - this.checkOnEachPublicOperation(); - return entryPresent() ? null : this.absent(); - } - - final BytesReturnValue bytesReturnValue; - - public BytesReturnValue bytesReturnValue() { - return this.bytesReturnValue; - } - - public final ThreadLocalCopies copies; - - final EntryKeyBytesData entryKey; - - public EntryKeyBytesData entryKey() { - return this.entryKey; - } - - public ThreadLocalCopies copies() { - return this.copies; - } - - private void countValueOffset() { - this.m().alignment.alignPositionAddr(entryBytes); - valueOffset = entryBytes.position(); - } - - final DummyValueZeroData dummyValue; - - public DummyValueZeroData dummyValue() { - return this.dummyValue; - } - - public final UsingReturnValue usingReturnValue; - - public UsingReturnValue usingReturnValue() { - return this.usingReturnValue; - } - - public final InputKeyBytesData inputKeyBytesValue; - - public InputKeyBytesData inputKeyBytesValue() { - return this.inputKeyBytesValue; - } - - public final DefaultReturnValue defaultReturnValue; - - public DefaultReturnValue defaultReturnValue() { - return this.defaultReturnValue; - } - - public final EntryValueBytesData entryValue; - - public EntryValueBytesData entryValue() { - return this.entryValue; - } - - final ReplicatedInputKeyBytesData replicatedInputKeyBytesValue; - - public ReplicatedInputKeyBytesData replicatedInputKeyBytesValue() { - return this.replicatedInputKeyBytesValue; - } - - final ReplicatedInputValueBytesData replicatedInputValueBytesValue; - - public ReplicatedInputValueBytesData replicatedInputValueBytesValue() { - return this.replicatedInputValueBytesValue; - } - - final WrappedValueInstanceData wrappedValueInstanceValue; - - public WrappedValueInstanceData wrappedValueInstanceValue() { - return this.wrappedValueInstanceValue; - } - - public final InputFirstValueBytesData inputFirstValueBytesValue; - - public final JavaLangBytesReusableBytesStore replicatedInputStore; - - public final JavaLangBytesReusableBytesStore inputStore; - - public JavaLangBytesReusableBytesStore inputStore() { - return this.inputStore; - } - - public JavaLangBytesReusableBytesStore replicatedInputStore() { - return this.replicatedInputStore; - } - - public InputFirstValueBytesData inputFirstValueBytesValue() { - return this.inputFirstValueBytesValue; - } - - final ReplicatedMapAbsentDelegating absentDelegating; - - public final InputSecondValueBytesData inputSecondValueBytesValue; - - public InputSecondValueBytesData inputSecondValueBytesValue() { - return this.inputSecondValueBytesValue; - } - - public ReplicatedMapAbsentDelegating absentDelegating() { - return this.absentDelegating; - } - - public final InputKeyInstanceData inputKeyInstanceValue; - - public InputKeyInstanceData inputKeyInstanceValue() { - return this.inputKeyInstanceValue; - } - - public final InputValueInstanceData inputValueInstanceValue; - - public InputValueInstanceData inputValueInstanceValue() { - return this.inputValueInstanceValue; - } - - public final DeprecatedMapKeyContextOnQuery deprecatedMapKeyContext; - - public DeprecatedMapKeyContextOnQuery deprecatedMapKeyContext() { - return this.deprecatedMapKeyContext; - } - - public final DeprecatedMapAcquireContextOnQuery deprecatedMapAcquireContext; - - public DeprecatedMapAcquireContextOnQuery deprecatedMapAcquireContext() { - return this.deprecatedMapAcquireContext; - } - - private final ReplicatedChronicleMap m; - - public final VI valueInterop; - - public VI valueInterop() { - return this.valueInterop; - } - - public final BytesStore entryBS; - - public BytesStore entryBS() { - return this.entryBS; - } - - public final BytesReader valueReader; - - public BytesReader valueReader() { - return this.valueReader; - } - - public final KI keyInterop; - - public KI keyInterop() { - return this.keyInterop; - } - - public final BytesReader keyReader; - - public BytesReader keyReader() { - return this.keyReader; - } - - @Override - public MapAbsentEntry absent() { - return this; - } - - @Override - public Data dummyZeroValue() { - return this.dummyValue; - } - - @Override - public ReplicatedChronicleMap m() { - return m; - } - - @Override - public ChronicleMap map() { - return m(); - } - - long sizeOfEverythingBeforeValue(long keySize, long valueSize) { - return (_MapEntryStages_sizeOfEverythingBeforeValue(keySize, valueSize)) + (ReplicatedChronicleMap.ADDITIONAL_ENTRY_BYTES); - } - - public MVI valueMetaInterop(V value) { - return this.m().metaValueInteropProvider.get(this.copies, this.m().originalMetaValueInterop, valueInterop, value); - } - - public void closeValueBytesInteropValueMetaInteropDependants() { - this.wrappedValueInstanceValue.closeBuffer(); - this.inputValueInstanceValue.closeBuffer(); - } - - public long innerEntrySize(long sizeOfEverythingBeforeValue, long valueSize) { - if (this.m().constantlySizedEntry) { - return this.m().alignment.alignAddr((sizeOfEverythingBeforeValue + valueSize)); - } else if (this.m().couldNotDetermineAlignmentBeforeAllocation) { - return (sizeOfEverythingBeforeValue + (this.m().worstAlignment)) + valueSize; - } else { - return (this.m().alignment.alignAddr(sizeOfEverythingBeforeValue)) + valueSize; - } - } - - public final long entrySize(long keySize, long valueSize) { - long sizeOfEverythingBeforeValue = sizeOfEverythingBeforeValue(keySize, valueSize); - return innerEntrySize(sizeOfEverythingBeforeValue, valueSize); - } - - public void checkAccessingFromOwnerThread() { - if ((owner) != (Thread.currentThread())) { - throw new ConcurrentModificationException("Context shouldn\'t be accessed from multiple threads"); - } - } - - public void closeOwnerThreadHolderCheckAccessingFromOwnerThreadDependants() { - this.closeQueryCheckOnEachPublicOperationCheckOnEachPublicOperationDependants(); - } - - public CompiledReplicatedMapQueryContext createChaining() { - return new CompiledReplicatedMapQueryContext(this); - } - - public T getContext() { - for (CompiledReplicatedMapQueryContext context : contextChain) { - if (!(context.usedInit())) { - return ((T)(context)); - } - } - int maxNestedContexts = 1 << 16; - if ((contextChain.size()) > maxNestedContexts) { - throw new IllegalStateException((((((("More than " + maxNestedContexts) + " nested ChronicleHash contexts are not supported. Very probable that ") + "you simply forgot to close context somewhere (recommended to use ") + "try-with-resources statement). ") + "Otherwise this is a bug, please report with this ") + "stack trace on https://github.com/OpenHFT/Chronicle-Map/issues")); - } - return ((T)(createChaining())); - } - - public T contextAtIndexInChain(int index) { - return ((T)(contextChain.get(index))); - } - - public void closeReplicatedChronicleMapHolderImplContextAtIndexInChainDependants() { - this.closeQuerySegmentStagesTryFindInitLocksOfThisSegmentDependants(); - } - - public MKI keyMetaInterop(K key) { - return this.h().metaKeyInteropProvider.get(this.copies, this.h().originalMetaKeyInterop, keyInterop, key); - } - - public void closeKeyBytesInteropKeyMetaInteropDependants() { - this.inputKeyInstanceValue.closeBuffer(); - } - - public long keyOffset = -1; - - public boolean keyOffsetInit() { - return (this.keyOffset) >= 0; - } - - public void initKeyOffset(long keyOffset) { - this.keyOffset = keyOffset; - this.closeKeyOffsetDependants(); - } - - public long keyOffset() { - assert this.keyOffsetInit() : "KeyOffset should be init"; - return this.keyOffset; - } - - public void closeKeyOffset() { - if (!(this.keyOffsetInit())) - return ; - - this.closeKeyOffsetDependants(); - this.keyOffset = -1; - } - - public void closeKeyOffsetDependants() { - this.closeReplicatedMapEntryStagesKeyEndDependants(); - this.closeReplicatedMapQueryKeyEqualsDependants(); - this.entryKey.closeEntryKeyBytesDataInnerGetUsingDependants(); - } - - public Data inputKey = null; - - public boolean inputKeyInit() { - return (this.inputKey) != null; - } - - public void initInputKey(Data inputKey) { - this.inputKey = inputKey; - this.closeInputKeyDependants(); - } - - public Data inputKey() { - assert this.inputKeyInit() : "InputKey should be init"; - return this.inputKey; - } - - public void closeInputKey() { - if (!(this.inputKeyInit())) - return ; - - this.closeInputKeyDependants(); - this.inputKey = null; - } - - public void closeInputKeyDependants() { - this.closeReplicatedMapQueryKeyEqualsDependants(); - this.closeHashOfKey(); - } - - public long hashOfKey = 0; - - public boolean hashOfKeyInit() { - return (this.hashOfKey) != 0; - } - - void initHashOfKey() { - hashOfKey = inputKey().hash(net.openhft.chronicle.algo.hashing.LongHashFunction.city_1_1()); - this.closeHashOfKeyDependants(); - } - - public long hashOfKey() { - if (!(this.hashOfKeyInit())) - this.initHashOfKey(); - - return this.hashOfKey; - } - - public void closeHashOfKey() { - if (!(this.hashOfKeyInit())) - return ; - - this.closeHashOfKeyDependants(); - this.hashOfKey = 0; - } - - public void closeHashOfKeyDependants() { - this.closeTheSegmentIndex(); - this.closeSearchKey(); - } - - public int segmentIndex = -1; - - public boolean theSegmentIndexInit() { - return (this.segmentIndex) >= 0; - } - - void initTheSegmentIndex() { - segmentIndex = this.h().hashSplitting.segmentIndex(this.hashOfKey()); - this.closeTheSegmentIndexDependants(); - } - - public void initTheSegmentIndex(int segmentIndex) { - this.segmentIndex = segmentIndex; - this.closeTheSegmentIndexDependants(); - } - - public int segmentIndex() { - if (!(this.theSegmentIndexInit())) - this.initTheSegmentIndex(); - - return this.segmentIndex; - } - - public void closeTheSegmentIndex() { - if (!(this.theSegmentIndexInit())) - return ; - - this.closeTheSegmentIndexDependants(); - this.segmentIndex = -1; - } - - public void closeTheSegmentIndexDependants() { - this.closeSegment(); - this.closeSegmentHashLookup(); - this.closeSegHeader(); - } - - long entrySpaceOffset = 0; - - MultiStoreBytes freeListBytes = new MultiStoreBytes(); - - public SingleThreadedDirectBitSet freeList = new SingleThreadedDirectBitSet(); - - boolean segmentInit() { - return (entrySpaceOffset) > 0; - } - - void initSegment() { - VanillaChronicleHash h = this.h(); - long hashLookupOffset = h.segmentOffset(segmentIndex()); - long freeListOffset = hashLookupOffset + (h.segmentHashLookupOuterSize); - freeListBytes.storePositionAndSize(h.ms, freeListOffset, h.segmentFreeListInnerSize); - freeList.reuse(freeListBytes); - entrySpaceOffset = (freeListOffset + (h.segmentFreeListOuterSize)) + (h.segmentEntrySpaceInnerOffset); - this.closeSegmentDependants(); - } - - public long entrySpaceOffset() { - if (!(this.segmentInit())) - this.initSegment(); - - return this.entrySpaceOffset; - } - - public SingleThreadedDirectBitSet freeList() { - if (!(this.segmentInit())) - this.initSegment(); - - return this.freeList; - } - - void closeSegment() { - if (!(this.segmentInit())) - return ; - - this.closeSegmentDependants(); - entrySpaceOffset = 0; - } - - public void closeSegmentDependants() { - this.closeEntryOffset(); - } - - int hashLookupEntrySize; - - int keyBits; - - long address = -1; - - long capacityMask; - - long capacityMask2; - - long keyMask; - - long valueMask; - - long entryMask; - - public boolean segmentHashLookupInit() { - return (this.address) >= 0; - } - - public void initSegmentHashLookup() { - long hashLookupOffset = this.h().segmentOffset(this.segmentIndex()); - innerInitSegmentHashLookup(((this.h().ms.address()) + hashLookupOffset), this.h().segmentHashLookupCapacity, this.h().segmentHashLookupEntrySize, this.h().segmentHashLookupKeyBits, this.h().segmentHashLookupValueBits); - this.closeSegmentHashLookupDependants(); - } - - public void initSegmentHashLookup(long address, long capacity, int entrySize, int keyBits, int valueBits) { - innerInitSegmentHashLookup(address, capacity, entrySize, keyBits, valueBits); - this.closeSegmentHashLookupDependants(); - } - - public int hashLookupEntrySize() { - if (!(this.segmentHashLookupInit())) - this.initSegmentHashLookup(); - - return this.hashLookupEntrySize; - } - - public int keyBits() { - if (!(this.segmentHashLookupInit())) - this.initSegmentHashLookup(); - - return this.keyBits; - } - - public long address() { - if (!(this.segmentHashLookupInit())) - this.initSegmentHashLookup(); - - return this.address; - } - - public long capacityMask() { - if (!(this.segmentHashLookupInit())) - this.initSegmentHashLookup(); - - return this.capacityMask; - } - - public long capacityMask2() { - if (!(this.segmentHashLookupInit())) - this.initSegmentHashLookup(); - - return this.capacityMask2; - } - - public long entryMask() { - if (!(this.segmentHashLookupInit())) - this.initSegmentHashLookup(); - - return this.entryMask; - } - - public long keyMask() { - if (!(this.segmentHashLookupInit())) - this.initSegmentHashLookup(); - - return this.keyMask; - } - - public long valueMask() { - if (!(this.segmentHashLookupInit())) - this.initSegmentHashLookup(); - - return this.valueMask; - } - - public void closeSegmentHashLookup() { - if (!(this.segmentHashLookupInit())) - return ; - - this.closeSegmentHashLookupDependants(); - this.address = -1; - } - - public void closeSegmentHashLookupDependants() { - this.closeHashLookupReadEntryDependants(); - this.closeHashLookupStepDependants(); - this.closeHashLookupStepBackDependants(); - this.closeHashLookupIndexToPosDependants(); - this.closeHashLookupMaskUnsetKeyDependants(); - this.closeHashLookupKeyDependants(); - this.closeHashLookupValueDependants(); - this.closeHashLookupHlPosDependants(); - this.closeHashLookupEmptyDependants(); - } - - public long readEntry(long pos) { - return NativeBytes.UNSAFE.getLong(((address()) + pos)); - } - - public void closeHashLookupReadEntryDependants() { - this.closeHashLookupSearchNextPosDependants(); - this.closeHashLookupSearchCheckSlotContainsExpectedKeyAndValueDependants(); - } - - public long step(long pos) { - return (pos += hashLookupEntrySize()) <= (capacityMask2()) ? pos : 0L; - } - - public void closeHashLookupStepDependants() { - this.closeHashLookupSearchNextPosDependants(); - } - - public long stepBack(long pos) { - return (pos -= hashLookupEntrySize()) >= 0 ? pos : capacityMask2(); - } - - public void closeHashLookupStepBackDependants() { - this.closeHashLookupSearchFoundDependants(); - } - - long indexToPos(long index) { - return index * (hashLookupEntrySize()); - } - - public void closeHashLookupIndexToPosDependants() { - this.closeHashLookupHlPosDependants(); - } - - public long maskUnsetKey(long key) { - return (key &= keyMask()) != (UNSET_KEY) ? key : keyMask(); - } - - public void closeHashLookupMaskUnsetKeyDependants() { - this.closeSearchKey(); - } - - long entry(long key, long value) { - return key | (value << (keyBits())); - } - - public void writeEntryVolatile(long pos, long prevEntry, long key, long value) { - long entry = (prevEntry & (~(entryMask()))) | (entry(key, value)); - NativeBytes.UNSAFE.putLongVolatile(null, ((address()) + pos), entry); - } - - public void clearHashLookup() { - NativeBytes.UNSAFE.setMemory(address(), ((capacityMask2()) + (hashLookupEntrySize())), ((byte)(0))); - } - - public long key(long entry) { - return entry & (keyMask()); - } - - public void closeHashLookupKeyDependants() { - this.closeHashLookupSearchNextPosDependants(); - this.closeHashLookupSearchCheckSlotContainsExpectedKeyAndValueDependants(); - } - - public void writeEntry(long pos, long prevEntry, long key, long value) { - long entry = (prevEntry & (~(entryMask()))) | (entry(key, value)); - NativeBytes.UNSAFE.putLong(((address()) + pos), entry); - } - - void writeEntry(long pos, long prevEntry, long anotherEntry) { - long entry = (prevEntry & (~(entryMask()))) | (anotherEntry & (entryMask())); - NativeBytes.UNSAFE.putLong(((address()) + pos), entry); - } - - public long value(long entry) { - return (entry >>> (keyBits())) & (valueMask()); - } - - public void closeHashLookupValueDependants() { - this.closeHashLookupSearchNextPosDependants(); - this.closeHashLookupSearchCheckSlotContainsExpectedKeyAndValueDependants(); - } - - public long hlPos(long key) { - return indexToPos((key & (capacityMask()))); - } - - public void closeHashLookupHlPosDependants() { - this.closeSearchKey(); - } - - public void checkValueForPut(long value) { - assert (value & (~(valueMask()))) == 0L : "Value out of range, was " + value; - } - - public void putValueVolatile(long pos, long value) { - checkValueForPut(value); - long currentEntry = readEntry(pos); - writeEntryVolatile(pos, currentEntry, key(currentEntry), value); - } - - void clearEntry(long pos, long prevEntry) { - long entry = prevEntry & (~(entryMask())); - NativeBytes.UNSAFE.putLong(((address()) + pos), entry); - } - - public boolean empty(long entry) { - return (entry & (entryMask())) == (UNSET_ENTRY); - } - - public void closeHashLookupEmptyDependants() { - this.closeHashLookupSearchNextPosDependants(); - } - - public long remove(long posToRemove) { - long entryToRemove = readEntry(posToRemove); - long posToShift = posToRemove; - while (true) { - posToShift = step(posToShift); - long entryToShift = readEntry(posToShift); - if (empty(entryToShift)) - break; - - long insertPos = hlPos(key(entryToShift)); - boolean cond1 = insertPos <= posToRemove; - boolean cond2 = posToRemove <= posToShift; - if ((cond1 && cond2) || ((posToShift < insertPos) && (cond1 || cond2))) { - writeEntry(posToRemove, entryToRemove, entryToShift); - posToRemove = posToShift; - entryToRemove = entryToShift; - } - } - clearEntry(posToRemove, entryToRemove); - return posToRemove; - } - - void forEach(EntryConsumer action) { - for (long pos = 0L ; pos <= (capacityMask2()) ; pos += hashLookupEntrySize()) { - long entry = readEntry(pos); - if (!(empty(entry))) - action.accept(key(entry), value(entry)); - - } - } - - String hashLookupToString() { - final StringBuilder sb = new StringBuilder("{"); - forEach((long key,long value) -> sb.append(key).append('=').append(value).append(',')); - sb.append('}'); - return sb.toString(); - } - - public void moveChange(long oldPos, long newPos) { - this.m().moveChange(this.segmentIndex(), oldPos, newPos); - } - - long segmentHeaderAddress; - - SegmentHeader segmentHeader = null; - - public boolean segHeaderInit() { - return (this.segmentHeader) != null; - } - - private void initSegHeader() { - segmentHeaderAddress = (this.h().ms.address()) + (this.h().segmentHeaderOffset(segmentIndex())); - segmentHeader = BigSegmentHeader.INSTANCE; - this.closeSegHeaderDependants(); - } - - public long segmentHeaderAddress() { - if (!(this.segHeaderInit())) - this.initSegHeader(); - - return this.segmentHeaderAddress; - } - - public SegmentHeader segmentHeader() { - if (!(this.segHeaderInit())) - this.initSegHeader(); - - return this.segmentHeader; - } - - public void closeSegHeader() { - if (!(this.segHeaderInit())) - return ; - - this.closeSegHeaderDependants(); - this.segmentHeader = null; - } - - public void closeSegHeaderDependants() { - this.closeQuerySegmentStagesTryFindInitLocksOfThisSegmentDependants(); - this.closeLocks(); - this.innerReadLock.closeReadLockLockDependants(); - } - - public void nextPosToSearchFrom(long nextPosToSearchFrom) { - segmentHeader().nextPosToSearchFrom(segmentHeaderAddress(), nextPosToSearchFrom); - } - - public void updateNextPosToSearchFrom(long allocated, int chunks) { - long nextPosToSearchFrom = allocated + chunks; - if (nextPosToSearchFrom >= (this.h().actualChunksPerSegment)) - nextPosToSearchFrom = 0L; - - nextPosToSearchFrom(nextPosToSearchFrom); - } - - long nextPosToSearchFrom() { - return segmentHeader().nextPosToSearchFrom(segmentHeaderAddress()); - } - - public long alloc(int chunks) { - VanillaChronicleHash h = this.h(); - if (chunks > (h.maxChunksPerEntry)) - throw new IllegalArgumentException((((("Entry is too large: requires " + chunks) + " entry size chucks, ") + (h.maxChunksPerEntry)) + " is maximum.")); - - long ret = freeList().setNextNContinuousClearBits(nextPosToSearchFrom(), chunks); - if ((ret == (DirectBitSet.NOT_FOUND)) || ((ret + chunks) > (h.actualChunksPerSegment))) { - if (((ret != (DirectBitSet.NOT_FOUND)) && ((ret + chunks) > (h.actualChunksPerSegment))) && (ret < (h.actualChunksPerSegment))) - freeList().clear(ret, h.actualChunksPerSegment); - - ret = freeList().setNextNContinuousClearBits(0L, chunks); - if ((ret == (DirectBitSet.NOT_FOUND)) || ((ret + chunks) > (h.actualChunksPerSegment))) { - if (((ret != (DirectBitSet.NOT_FOUND)) && ((ret + chunks) > (h.actualChunksPerSegment))) && (ret < (h.actualChunksPerSegment))) - freeList().clear(ret, h.actualChunksPerSegment); - - if (chunks == 1) { - throw new IllegalStateException("Segment is full, no free entries found"); - } else { - throw new IllegalStateException((("Segment is full or has no ranges of " + chunks) + " continuous free chunks")); - } - } - updateNextPosToSearchFrom(ret, chunks); - } else { - if ((chunks == 1) || (freeList().isSet(nextPosToSearchFrom()))) { - updateNextPosToSearchFrom(ret, chunks); - } - } - return ret; - } - - public void free(long fromPos, int chunks) { - freeList().clear(fromPos, (fromPos + chunks)); - if (fromPos < (nextPosToSearchFrom())) - nextPosToSearchFrom(fromPos); - - } - - boolean tryFindInitLocksOfThisSegment(Object thisContext, int index) { - CompiledReplicatedMapQueryContext c = this.contextAtIndexInChain(index); - if ((((c.segmentHeader()) != null) && ((c.segmentHeaderAddress()) == (segmentHeaderAddress()))) && ((c.rootContextOnThisSegment()) != null)) { - throw new IllegalStateException("Nested context not implemented yet"); - } else { - return false; - } - } - - public void closeQuerySegmentStagesTryFindInitLocksOfThisSegmentDependants() { - this.closeLocks(); - } - - public void entries(long size) { - segmentHeader().size(segmentHeaderAddress(), size); - } - - public long entries() { - return segmentHeader().size(segmentHeaderAddress()); - } - - public void deleted(long deleted) { - segmentHeader().deleted(segmentHeaderAddress(), deleted); - } - - public long deleted() { - return segmentHeader().deleted(segmentHeaderAddress()); - } - - public long size() { - return (entries()) - (deleted()); - } - - int totalReadLockCount; - - int totalUpdateLockCount; - - int totalWriteLockCount; - - public int latestSameThreadSegmentModCount; - - public int contextModCount; - - CompiledReplicatedMapQueryContext nextNode; - - public boolean concurrentSameThreadContexts; - - LocalLockState localLockState; - - public CompiledReplicatedMapQueryContext rootContextOnThisSegment = null; - - public boolean locksInit() { - return (this.rootContextOnThisSegment) != null; - } - - void initLocks() { - localLockState = LocalLockState.UNLOCKED; - int indexOfThisContext = this.indexInContextChain; - for (int i = indexOfThisContext - 1 ; i >= 0 ; i--) { - if (tryFindInitLocksOfThisSegment(this, i)) - return ; - - } - for (int i = indexOfThisContext + 1, size = this.contextChain.size() ; i < size ; i++) { - if (tryFindInitLocksOfThisSegment(this, i)) - return ; - - } - rootContextOnThisSegment = this; - concurrentSameThreadContexts = false; - latestSameThreadSegmentModCount = 0; - contextModCount = 0; - nextNode = null; - totalReadLockCount = 0; - totalUpdateLockCount = 0; - totalWriteLockCount = 0; - this.closeLocksDependants(); - } - - public boolean concurrentSameThreadContexts() { - if (!(this.locksInit())) - this.initLocks(); - - return this.concurrentSameThreadContexts; - } - - public int contextModCount() { - if (!(this.locksInit())) - this.initLocks(); - - return this.contextModCount; - } - - public int latestSameThreadSegmentModCount() { - if (!(this.locksInit())) - this.initLocks(); - - return this.latestSameThreadSegmentModCount; - } - - public LocalLockState localLockState() { - if (!(this.locksInit())) - this.initLocks(); - - return this.localLockState; - } - - public CompiledReplicatedMapQueryContext rootContextOnThisSegment() { - if (!(this.locksInit())) - this.initLocks(); - - return this.rootContextOnThisSegment; - } - - void closeLocks() { - if (!(this.locksInit())) - return ; - - this.closeLocksDependants(); - if ((rootContextOnThisSegment) == (this)) { - closeRootLocks(); - } else { - closeNestedLocks(); - } - localLockState = null; - rootContextOnThisSegment = null; - } - - public void closeLocksDependants() { - this.innerReadLock.closeReadLockLockDependants(); - this.closeReplicatedMapQueryDropSearchIfNestedContextsAndPresentHashLookupSlotCheckFailedDependants(); - } - - public void clearSegment() { - this.innerWriteLock.lock(); - this.clearHashLookup(); - freeList().clear(); - nextPosToSearchFrom(0L); - entries(0L); - } - - public void clear() { - clearSegment(); - } - - long searchKey = UNSET_KEY; - - long searchStartPos; - - public boolean searchKeyInit() { - return (this.searchKey) != (UNSET_KEY); - } - - void initSearchKey() { - searchKey = this.maskUnsetKey(this.h().hashSplitting.segmentHash(this.hashOfKey())); - searchStartPos = this.hlPos(searchKey); - this.closeSearchKeyDependants(); - } - - public long searchKey() { - if (!(this.searchKeyInit())) - this.initSearchKey(); - - return this.searchKey; - } - - public long searchStartPos() { - if (!(this.searchKeyInit())) - this.initSearchKey(); - - return this.searchStartPos; - } - - public void closeSearchKey() { - if (!(this.searchKeyInit())) - return ; - - this.closeSearchKeyDependants(); - this.searchKey = UNSET_KEY; - } - - public void closeSearchKeyDependants() { - this.closeHashLookupPos(); - this.closeHashLookupSearchNextPosDependants(); - this.closeHashLookupSearchCheckSlotContainsExpectedKeyAndValueDependants(); - } - - public long hashLookupPos = -1; - - public boolean hashLookupPosInit() { - return (this.hashLookupPos) >= 0; - } - - public void initHashLookupPos() { - this.innerReadLock.lock(); - this.hashLookupPos = this.searchStartPos(); - this.closeHashLookupPosDependants(); - } - - public void initHashLookupPos(long hashLookupPos) { - this.hashLookupPos = hashLookupPos; - this.closeHashLookupPosDependants(); - } - - public long hashLookupPos() { - if (!(this.hashLookupPosInit())) - this.initHashLookupPos(); - - return this.hashLookupPos; - } - - public void closeHashLookupPos() { - if (!(this.hashLookupPosInit())) - return ; - - this.closeHashLookupPosDependants(); - this.hashLookupPos = -1; - } - - public void closeHashLookupPosDependants() { - this.closeHashLookupSearchNextPosDependants(); - this.closeHashLookupSearchFoundDependants(); - this.closeHashLookupSearchCheckSlotContainsExpectedKeyAndValueDependants(); - } - - public void putVolatile(long value) { - this.checkValueForPut(value); - long currentEntry = this.readEntry(this.hashLookupPos()); - assert (this.key(currentEntry)) == (searchKey()); - this.writeEntryVolatile(this.hashLookupPos(), currentEntry, searchKey(), value); - } - - public long nextPos() { - long pos = this.hashLookupPos(); - while (true) { - long entry = this.readEntry(pos); - if (this.empty(entry)) { - this.setHashLookupPosGuarded(pos); - return -1L; - } - pos = this.step(pos); - if (pos == (searchStartPos())) - break; - - if ((this.key(entry)) == (searchKey())) { - this.setHashLookupPosGuarded(pos); - return this.value(entry); - } - } - throw new IllegalStateException(("MultiMap is full, that most likely means you " + ("misconfigured entrySize/chunkSize, and entries tend to take less chunks than " + "expected"))); - } - - public void closeHashLookupSearchNextPosDependants() { - this.closeKeySearch(); - } - - public void putNewVolatile(long value) { - this.checkValueForPut(value); - long currentEntry = this.readEntry(this.hashLookupPos()); - this.writeEntryVolatile(this.hashLookupPos(), currentEntry, searchKey(), value); - } - - void put(long value) { - this.checkValueForPut(value); - this.writeEntry(this.hashLookupPos(), this.readEntry(this.hashLookupPos()), searchKey(), value); - } - - public void found() { - this.setHashLookupPosGuarded(this.stepBack(this.hashLookupPos())); - } - - public void closeHashLookupSearchFoundDependants() { - this.closeKeySearch(); - } - - public boolean checkSlotContainsExpectedKeyAndValue(long value) { - long entry = this.readEntry(this.hashLookupPos()); - return ((this.key(entry)) == (searchKey())) && ((this.value(entry)) == value); - } - - public void closeHashLookupSearchCheckSlotContainsExpectedKeyAndValueDependants() { - this.closeReplicatedMapQueryDropSearchIfNestedContextsAndPresentHashLookupSlotCheckFailedDependants(); - } - - public void remove() { - this.setHashLookupPosGuarded(this.remove(this.hashLookupPos())); - } - - public boolean checkSlotIsEmpty() { - return this.empty(this.readEntry(this.hashLookupPos())); - } - - public long pos = -1; - - public boolean posInit() { - return (this.pos) >= 0; - } - - public void initPos(long pos) { - this.pos = pos; - this.closePosDependants(); - } - - public long pos() { - assert this.posInit() : "Pos should be init"; - return this.pos; - } - - public void closePos() { - if (!(this.posInit())) - return ; - - this.closePosDependants(); - this.pos = -1; - } - - public void closePosDependants() { - this.closeEntryOffset(); - this.closeReplicatedMapQueryDropSearchIfNestedContextsAndPresentHashLookupSlotCheckFailedDependants(); - } - - public void dropChange() { - this.m().dropChange(this.segmentIndex(), this.pos()); - } - - public long keySizeOffset = -1; - - public boolean entryOffsetInit() { - return (this.keySizeOffset) >= 0; - } - - public void initEntryOffset() { - keySizeOffset = (this.entrySpaceOffset()) + ((pos()) * (this.h().chunkSize)); - entryBytes.limit(entryBytes.capacity()); - this.closeEntryOffsetDependants(); - } - - public long keySizeOffset() { - if (!(this.entryOffsetInit())) - this.initEntryOffset(); - - return this.keySizeOffset; - } - - public void closeEntryOffset() { - if (!(this.entryOffsetInit())) - return ; - - this.closeEntryOffsetDependants(); - this.keySizeOffset = -1; - } - - public void closeEntryOffsetDependants() { - this.closeReplicatedMapEntryStagesEntrySizeDependants(); - this.closeReplicatedMapEntryStagesReadExistingEntryDependants(); - } - - public void copyExistingEntry(long newPos, long bytesToCopy) { - long oldKeySizeOffset = keySizeOffset(); - long oldKeyOffset = keyOffset(); - initPos(newPos); - initKeyOffset(((keySizeOffset()) + (oldKeyOffset - oldKeySizeOffset))); - entryBS.write(keySizeOffset(), entryBS, oldKeySizeOffset, bytesToCopy); - } - - public void readExistingEntry(long pos) { - initPos(pos); - entryBytes.position(keySizeOffset()); - initKeySize(this.h().keySizeMarshaller.readSize(entryBytes)); - initKeyOffset(entryBytes.position()); - } - - public void closeReplicatedMapEntryStagesReadExistingEntryDependants() { - this.closeKeySearch(); - } - - public void raiseChange() { - this.m().raiseChange(this.segmentIndex(), this.pos()); - } - - public void updateChange() { - if (!(replicationUpdateInit())) { - raiseChange(); - } - } - - public Bytes replicatedInputBytes = null; - - public boolean replicatedInputBytesInit() { - return (this.replicatedInputBytes) != null; - } - - public void initReplicatedInputBytes(Bytes replicatedInputBytes) { - this.replicatedInputBytes = replicatedInputBytes; - replicatedInputStore.setBytes(replicatedInputBytes); - this.closeReplicatedInputBytesDependants(); - } - - public Bytes replicatedInputBytes() { - assert this.replicatedInputBytesInit() : "ReplicatedInputBytes should be init"; - return this.replicatedInputBytes; - } - - public void closeReplicatedInputBytes() { - if (!(this.replicatedInputBytesInit())) - return ; - - this.closeReplicatedInputBytesDependants(); - this.replicatedInputBytes = null; - } - - public void closeReplicatedInputBytesDependants() { - this.replicatedInputKeyBytesValue.closeReplicatedInputKeyBytesDataGetUsingDependants(); - this.replicatedInputValueBytesValue.closeReplicatedInputValueBytesDataGetUsingDependants(); - } - - public long keySize = -1; - - public boolean keySizeInit() { - return (this.keySize) >= 0; - } - - public void initKeySize(long keySize) { - this.keySize = keySize; - this.closeKeySizeDependants(); - } - - public long keySize() { - assert this.keySizeInit() : "KeySize should be init"; - return this.keySize; - } - - public void closeKeySize() { - if (!(this.keySizeInit())) - return ; - - this.closeKeySizeDependants(); - this.keySize = -1; - } - - public void closeKeySizeDependants() { - this.closeReplicatedMapEntryStagesKeyEndDependants(); - this.closeReplicatedMapQueryKeyEqualsDependants(); - this.entryKey.closeEntryKeyBytesDataSizeDependants(); - } - - public long keyEnd() { - return (keyOffset()) + (keySize()); - } - - public void closeReplicatedMapEntryStagesKeyEndDependants() { - this.closeReplicatedMapEntryStagesCountValueSizeOffsetDependants(); - this.closeReplicationState(); - this.closeReplicatedMapEntryStagesEntryEndDependants(); - } - - long countValueSizeOffset() { - return (_MapEntryStages_countValueSizeOffset()) + (ReplicatedChronicleMap.ADDITIONAL_ENTRY_BYTES); - } - - public void closeReplicatedMapEntryStagesCountValueSizeOffsetDependants() { - this.closeValueSizeOffset(); - } - - public long valueSizeOffset = -1; - - public boolean valueSizeOffsetInit() { - return (this.valueSizeOffset) >= 0; - } - - void initValueSizeOffset() { - valueSizeOffset = countValueSizeOffset(); - this.closeValueSizeOffsetDependants(); - } - - public long valueSizeOffset() { - if (!(this.valueSizeOffsetInit())) - this.initValueSizeOffset(); - - return this.valueSizeOffset; - } - - public void closeValueSizeOffset() { - if (!(this.valueSizeOffsetInit())) - return ; - - this.closeValueSizeOffsetDependants(); - this.valueSizeOffset = -1; - } - - public void closeValueSizeOffsetDependants() { - this.closeValSize(); - } - - public long valueSize = -1; - - public long valueOffset; - - public boolean valSizeInit() { - return (this.valueSize) >= 0; - } - - void initValSize() { - entryBytes.position(valueSizeOffset()); - valueSize = this.m().readValueSize(entryBytes); - countValueOffset(); - this.closeValSizeDependants(); - } - - void initValSize(long valueSize) { - this.valueSize = valueSize; - entryBytes.position(valueSizeOffset()); - this.m().valueSizeMarshaller.writeSize(entryBytes, valueSize); - countValueOffset(); - this.closeValSizeDependants(); - } - - void initValSizeEqualToOld(long oldValueSizeOffset, long oldValueSize, long oldValueOffset) { - valueSize = oldValueSize; - valueOffset = (valueSizeOffset()) + (oldValueOffset - oldValueSizeOffset); - this.closeValSizeDependants(); - } - - public long valueOffset() { - if (!(this.valSizeInit())) - this.initValSize(); - - return this.valueOffset; - } - - public long valueSize() { - if (!(this.valSizeInit())) - this.initValSize(); - - return this.valueSize; - } - - public void closeValSize() { - if (!(this.valSizeInit())) - return ; - - this.closeValSizeDependants(); - this.valueSize = -1; - } - - public void closeValSizeDependants() { - this.closeReplicatedMapEntryStagesEntryEndDependants(); - this.entryValue.closeEntryValueBytesDataSizeDependants(); - this.entryValue.closeEntryValueBytesDataInnerGetUsingDependants(); - } - - public void writeValue(Data value) { - value.writeTo(entryBS, valueOffset()); - } - - public void initValueWithoutSize(Data value, long oldValueSizeOffset, long oldValueSize, long oldValueOffset) { - assert oldValueSize == (value.size()); - initValSizeEqualToOld(oldValueSizeOffset, oldValueSize, oldValueOffset); - writeValue(value); - } - - public long newSizeOfEverythingBeforeValue(Data newValue) { - return ((valueSizeOffset()) + (this.m().valueSizeMarshaller.sizeEncodingSize(newValue.size()))) - (keySizeOffset()); - } - - public void initValue(Data value) { - entryBytes.position(valueSizeOffset()); - initValSize(value.size()); - writeValue(value); - } - - long replicationBytesOffset = -1; - - public boolean replicationStateInit() { - return (this.replicationBytesOffset) >= 0; - } - - void initReplicationState() { - replicationBytesOffset = keyEnd(); - } - - public long replicationBytesOffset() { - if (!(this.replicationStateInit())) - this.initReplicationState(); - - return this.replicationBytesOffset; - } - - public void closeReplicationState() { - if (!(this.replicationStateInit())) - return ; - - this.replicationBytesOffset = -1; - } - - void updateReplicationState(long timestamp, byte identifier) { - entryBytes.position(replicationBytesOffset()); - entryBytes.writeLong(timestamp); - entryBytes.writeByte(identifier); - } - - public void updatedReplicationStateOnAbsentEntry() { - if (!(this.replicationUpdateInit())) { - this.innerWriteLock.lock(); - updateReplicationState(this.m().timeProvider.currentTime(), this.m().identifier()); - } - } - - private long entryDeletedOffset() { - return (replicationBytesOffset()) + 9L; - } - - public void writeEntryDeleted() { - entryBS.writeBoolean(entryDeletedOffset(), true); - } - - public void writeEntryPresent() { - entryBS.writeBoolean(entryDeletedOffset(), false); - } - - public boolean entryDeleted() { - return entryBS.readBoolean(entryDeletedOffset()); - } - - public long timestamp() { - return entryBS.readLong(replicationBytesOffset()); - } - - private long timestampOffset() { - return replicationBytesOffset(); - } - - private long identifierOffset() { - return (replicationBytesOffset()) + 8L; - } - - byte identifier() { - return entryBS.readByte(identifierOffset()); - } - - public void updatedReplicationStateOnPresentEntry() { - if (!(this.replicationUpdateInit())) { - this.innerWriteLock.lock(); - long timestamp; - if ((identifier()) != (this.m().identifier())) { - timestamp = Math.max(((timestamp()) + 1), this.m().timeProvider.currentTime()); - } else { - timestamp = this.m().timeProvider.currentTime(); - } - updateReplicationState(timestamp, this.m().identifier()); - } - } - - protected long entryEnd() { - return (valueOffset()) + (valueSize()); - } - - public void closeReplicatedMapEntryStagesEntryEndDependants() { - this.closeReplicatedMapEntryStagesEntrySizeDependants(); - } - - long entrySize() { - return (entryEnd()) - (keySizeOffset()); - } - - public void closeReplicatedMapEntryStagesEntrySizeDependants() { - this.closeTheEntrySizeInChunks(); - } - - public int entrySizeInChunks = 0; - - public boolean theEntrySizeInChunksInit() { - return (this.entrySizeInChunks) != 0; - } - - void initTheEntrySizeInChunks() { - entrySizeInChunks = this.h().inChunks(entrySize()); - } - - public void initTheEntrySizeInChunks(int actuallyUsedChunks) { - entrySizeInChunks = actuallyUsedChunks; - } - - public int entrySizeInChunks() { - if (!(this.theEntrySizeInChunksInit())) - this.initTheEntrySizeInChunks(); - - return this.entrySizeInChunks; - } - - public void closeTheEntrySizeInChunks() { - if (!(this.theEntrySizeInChunksInit())) - return ; - - this.entrySizeInChunks = 0; - } - - public void innerRemoveEntryExceptHashLookupUpdate() { - this.free(pos(), entrySizeInChunks()); - this.entries(((this.entries()) - 1L)); - this.incrementModCountGuarded(); - } - - boolean keyEquals() { - return ((inputKey().size()) == (this.keySize())) && (BytesUtil.bytesEqual(this.entryBS, this.keyOffset(), inputKey().bytes(), inputKey().offset(), this.keySize())); - } - - public void closeReplicatedMapQueryKeyEqualsDependants() { - this.closeKeySearch(); - } - - protected CompiledReplicatedMapQueryContext.SearchState searchState = null; - - boolean keySearchInit() { - return (this.searchState) != null; - } - - void initKeySearch() { - for (long pos ; (pos = this.nextPos()) >= 0L ; ) { - this.readExistingEntry(pos); - if (!(keyEquals())) - continue; - - this.found(); - keyFound(); - return ; - } - searchState = CompiledReplicatedMapQueryContext.SearchState.ABSENT; - this.closeKeySearchDependants(); - } - - public CompiledReplicatedMapQueryContext.SearchState searchState() { - if (!(this.keySearchInit())) - this.initKeySearch(); - - return this.searchState; - } - - void closeKeySearch() { - if (!(this.keySearchInit())) - return ; - - this.closeKeySearchDependants(); - this.searchState = null; - } - - public void closeKeySearchDependants() { - this.closeReplicatedMapQueryDropSearchIfNestedContextsAndPresentHashLookupSlotCheckFailedDependants(); - } - - public void incrementSegmentEntriesIfNeeded() { - if ((this.searchState()) != (CompiledReplicatedMapQueryContext.SearchState.PRESENT)) { - this.entries(((this.entries()) + 1L)); - } - } - - public void dropSearchIfNestedContextsAndPresentHashLookupSlotCheckFailed() { - if (this.locksInit()) { - if ((this.concurrentSameThreadContexts()) && ((this.rootContextOnThisSegment().latestSameThreadSegmentModCount()) != (this.contextModCount()))) { - if (keySearchInit()) { - if ((searchState()) == (CompiledReplicatedMapQueryContext.SearchState.PRESENT)) { - if (!(this.checkSlotContainsExpectedKeyAndValue(this.pos()))) - this.closeHashLookupPos(); - - } - } - } - } - } - - public void closeReplicatedMapQueryDropSearchIfNestedContextsAndPresentHashLookupSlotCheckFailedDependants() { - this.closeQueryCheckOnEachPublicOperationCheckOnEachPublicOperationDependants(); - } - - public void checkOnEachPublicOperation() { - _CheckOnEachPublicOperation_checkOnEachPublicOperation(); - this.dropSearchIfNestedContextsAndPresentHashLookupSlotCheckFailed(); - } - - public void closeQueryCheckOnEachPublicOperationCheckOnEachPublicOperationDependants() { - this.entryValue.closeEntryValueBytesDataSizeDependants(); - this.entryKey.closeEntryKeyBytesDataSizeDependants(); - } - - @Override - public R replaceValue(@NotNull - MapEntry entry, Data newValue) { - this.checkOnEachPublicOperation(); - return this.m().entryOperations.replaceValue(entry, newValue); - } - - @NotNull - @Override - public InterProcessLock updateLock() { - this.checkOnEachPublicOperation(); - return this.innerUpdateLock; - } - - @NotNull - @Override - public Data absentKey() { - this.checkOnEachPublicOperation(); - return this.inputKey(); - } - - @NotNull - @Override - public InterProcessLock readLock() { - this.checkOnEachPublicOperation(); - return this.innerReadLock; - } - - public Data queriedKey() { - this.checkOnEachPublicOperation(); - return inputKey(); - } - - @NotNull - @Override - public Data defaultValue() { - this.checkOnEachPublicOperation(); - return this.wrapValueAsValue(this.m().defaultValue(this.deprecatedMapKeyContext)); - } - - @Override - public void raiseChanged() { - this.checkOnEachPublicOperation(); - this.innerUpdateLock.lock(); - this.raiseChange(); - } - - @NotNull - @Override - public Data key() { - this.checkOnEachPublicOperation(); - return this.entryKey; - } - - @NotNull - @Override - public MapContext context() { - this.checkOnEachPublicOperation(); - return this; - } - - @Override - public R remove(@NotNull - MapEntry entry) { - this.checkOnEachPublicOperation(); - return this.m().entryOperations.remove(entry); - } - - @NotNull - @Override - public InterProcessLock writeLock() { - this.checkOnEachPublicOperation(); - return this.innerWriteLock; - } - - @Override - public void updateOrigin(byte newIdentifier, long newTimestamp) { - this.checkOnEachPublicOperation(); - this.innerWriteLock.lock(); - updateReplicationState(newTimestamp, newIdentifier); - } - - @Override - public R insert(@NotNull - MapAbsentEntry absentEntry, Data value) { - this.checkOnEachPublicOperation(); - return this.m().entryOperations.insert(absentEntry, value); - } - - @Override - public void dropChanged() { - this.checkOnEachPublicOperation(); - this.innerUpdateLock.lock(); - this.dropChange(); - } - - @Override - public Data wrapValueAsValue(V value) { - this.checkOnEachPublicOperation(); - WrappedValueInstanceData wrapped = this.wrappedValueInstanceValue; - wrapped = wrapped.getUnusedWrappedValueGuarded(); - wrapped.initValue(value); - return wrapped; - } - - @NotNull - @Override - public Data value() { - this.checkOnEachPublicOperation(); - return this.entryValue; - } - - @Override - public Data defaultValue(@NotNull - MapAbsentEntry absentEntry) { - this.checkOnEachPublicOperation(); - return this.m().entryOperations.defaultValue(absentEntry); - } - - @Override - public long originTimestamp() { - this.checkOnEachPublicOperation(); - return timestamp(); - } - - @Override - public byte originIdentifier() { - this.checkOnEachPublicOperation(); - return identifier(); - } - - public boolean searchStateDeleted() { - return (((searchState()) == (CompiledReplicatedMapQueryContext.SearchState.DELETED)) && (!(this.concurrentSameThreadContexts()))) && (this.innerUpdateLock.isHeldByCurrentThread()); - } - - public boolean searchStatePresent() { - return (searchState()) == (CompiledReplicatedMapQueryContext.SearchState.PRESENT); - } - - public boolean entryPresent() { - return (_MapQuery_entryPresent()) && (!(this.entryDeleted())); - } - - @Nullable - @Override - public MapAbsentEntry absentEntry() { - this.checkOnEachPublicOperation(); - if (entryPresent()) { - return null; - } else { - if (!(searchStatePresent())) { - return this.absentDelegating; - } else { - assert this.entryDeleted(); - return this.absent(); - } - } - } - - @Override - public MapReplicableEntry entry() { - return ((MapReplicableEntry)(_MapQuery_entry())); - } - - public boolean searchStateAbsent() { - return (!(searchStatePresent())) && (!(searchStateDeleted())); - } - - protected void putPrefix() { - this.checkOnEachPublicOperation(); - boolean underUpdatedLockIsHeld = !(this.innerUpdateLock.isHeldByCurrentThread()); - if (underUpdatedLockIsHeld) - this.innerUpdateLock.lock(); - - boolean searchResultsNotTrusted = underUpdatedLockIsHeld || (this.concurrentSameThreadContexts()); - if (((this.hashLookupPosInit()) && (searchStateAbsent())) && searchResultsNotTrusted) - this.closeHashLookupPos(); - - } - - public void writeNewEntry(long pos, Data key) { - initPos(pos); - initKeySize(key.size()); - entryBytes.position(keySizeOffset()); - this.h().keySizeMarshaller.writeSize(entryBytes, keySize()); - initKeyOffset(entryBytes.position()); - key.writeTo(entryBS, keyOffset()); - } - - public long innerRemoteTimestamp; - - public byte innerRemoteIdentifier = ((byte)(0)); - - public boolean replicationUpdateInit() { - return (this.innerRemoteIdentifier) != ((byte)(0)); - } - - public void initReplicationUpdate(long timestamp, byte identifier) { - innerRemoteTimestamp = timestamp; - if (identifier == 0) - throw new IllegalStateException("identifier can\'t be 0"); - - innerRemoteIdentifier = identifier; - } - - public byte innerRemoteIdentifier() { - assert this.replicationUpdateInit() : "ReplicationUpdate should be init"; - return this.innerRemoteIdentifier; - } - - public long innerRemoteTimestamp() { - assert this.replicationUpdateInit() : "ReplicationUpdate should be init"; - return this.innerRemoteTimestamp; - } - - public void closeReplicationUpdate() { - if (!(this.replicationUpdateInit())) - return ; - - this.innerRemoteIdentifier = ((byte)(0)); - } - - @Override - public long remoteTimestamp() { - this.checkOnEachPublicOperation(); - return innerRemoteTimestamp(); - } - - private boolean testTimeStampInSensibleRange() { - if ((this.m().timeProvider) == (TimeProvider.SYSTEM)) { - long currentTime = TimeProvider.SYSTEM.currentTime(); - assert (Math.abs((currentTime - (timestamp())))) <= 100000000 : "unrealistic timestamp: " + (timestamp()); - assert (Math.abs((currentTime - (this.innerRemoteTimestamp())))) <= 100000000 : "unrealistic innerRemoteTimestamp: " + (this.innerRemoteTimestamp()); - } - return true; - } - - @Override - public byte remoteIdentifier() { - this.checkOnEachPublicOperation(); - return innerRemoteIdentifier(); - } - - public int allocatedChunks = 0; - - public boolean allocatedChunksInit() { - return (this.allocatedChunks) != 0; - } - - public void initAllocatedChunks(int allocatedChunks) { - this.allocatedChunks = allocatedChunks; - } - - public int allocatedChunks() { - assert this.allocatedChunksInit() : "AllocatedChunks should be init"; - return this.allocatedChunks; - } - - public void closeAllocatedChunks() { - if (!(this.allocatedChunksInit())) - return ; - - this.allocatedChunks = 0; - } - - public void initEntryAndKeyCopying(long entrySize, long bytesToCopy) { - initAllocatedChunks(this.h().inChunks(entrySize)); - this.copyExistingEntry(this.alloc(allocatedChunks()), bytesToCopy); - incrementSegmentEntriesIfNeeded(); - } - - public final void freeExtraAllocatedChunks() { - if (((!(this.m().constantlySizedEntry)) && (this.m().couldNotDetermineAlignmentBeforeAllocation)) && ((entrySizeInChunks()) < (this.allocatedChunks()))) { - this.free(((pos()) + (entrySizeInChunks())), ((this.allocatedChunks()) - (entrySizeInChunks()))); - } else { - initTheEntrySizeInChunks(this.allocatedChunks()); - } - } - - public void writeValueAndPutPos(Data value) { - initValue(value); - freeExtraAllocatedChunks(); - this.putValueVolatile(this.hashLookupPos(), pos()); - } - - protected void relocation(Data newValue, long newSizeOfEverythingBeforeValue) { - long oldPos = pos(); - _MapEntryStages_relocation(newValue, newSizeOfEverythingBeforeValue); - this.moveChange(oldPos, pos()); - } - - public void innerDefaultReplaceValue(Data newValue) { - assert this.innerUpdateLock.isHeldByCurrentThread(); - boolean newValueSizeIsDifferent = (newValue.size()) != (this.valueSize()); - if (newValueSizeIsDifferent) { - long newSizeOfEverythingBeforeValue = newSizeOfEverythingBeforeValue(newValue); - long entryStartOffset = keySizeOffset(); - VanillaChronicleMap m = this.m(); - long newValueOffset = m.alignment.alignAddr((entryStartOffset + newSizeOfEverythingBeforeValue)); - long newEntrySize = (newValueOffset + (newValue.size())) - entryStartOffset; - int newSizeInChunks = m.inChunks(newEntrySize); - newValueDoesNotFit : if (newSizeInChunks > (entrySizeInChunks())) { - if (newSizeInChunks > (m.maxChunksPerEntry)) { - throw new IllegalArgumentException(((((("Value too large: " + "entry takes ") + newSizeInChunks) + " chunks, ") + (m.maxChunksPerEntry)) + " is maximum.")); - } - if (this.freeList().allClear(((pos()) + (entrySizeInChunks())), ((pos()) + newSizeInChunks))) { - this.freeList().set(((pos()) + (entrySizeInChunks())), ((pos()) + newSizeInChunks)); - break newValueDoesNotFit; - } - relocation(newValue, newSizeOfEverythingBeforeValue); - return ; - } else if (newSizeInChunks < (entrySizeInChunks())) { - this.freeList().clear(((pos()) + newSizeInChunks), ((pos()) + (entrySizeInChunks()))); - } - } else { - } - this.innerWriteLock.lock(); - if (newValueSizeIsDifferent) { - initValue(newValue); - } else { - writeValue(newValue); - } - this.putValueVolatile(this.hashLookupPos(), pos()); - } - - @Override - public void doReplaceValue(Data newValue) { - _MapQuery_doReplaceValue(newValue); - this.updateChange(); - this.updatedReplicationStateOnPresentEntry(); - } - - @Override - public void doRemove() { - this.checkOnEachPublicOperation(); - this.innerUpdateLock.lock(); - if (entryPresent()) { - if ((this.valueSize()) > (this.dummyValue.size())) - this.innerDefaultReplaceValue(this.dummyValue); - - this.updatedReplicationStateOnPresentEntry(); - this.writeEntryDeleted(); - this.updateChange(); - this.deleted(((this.deleted()) + 1)); - } else { - throw new IllegalStateException("Entry is absent in the map when doRemove() is called"); - } - } - - public void putValueDeletedEntry(Data newValue) { - throw new AssertionError("Replicated Map doesn\'t remove entries truly, yet"); - } - - public void initEntryAndKey(long entrySize) { - initAllocatedChunks(this.h().inChunks(entrySize)); - this.writeNewEntry(this.alloc(allocatedChunks()), this.inputKey()); - incrementSegmentEntriesIfNeeded(); - } - - void putEntry(Data value) { - assert this.searchStateAbsent(); - long entrySize = this.entrySize(this.inputKey().size(), value.size()); - this.initEntryAndKey(entrySize); - this.initValue(value); - this.freeExtraAllocatedChunks(); - this.putNewVolatile(this.pos()); - } - - @Override - public void doInsert(Data value) { - this.putPrefix(); - if (!(this.entryPresent())) { - if (!(this.searchStatePresent())) { - putEntry(value); - this.setSearchStateGuarded(CompiledReplicatedMapQueryContext.SearchState.PRESENT); - } else { - this.innerDefaultReplaceValue(value); - this.deleted(((this.deleted()) - 1)); - } - this.incrementModCountGuarded(); - this.writeEntryPresent(); - this.updateChange(); - this.updatedReplicationStateOnAbsentEntry(); - } else { - throw new IllegalStateException("Entry is absent in the map when doInsert() is called"); - } - } - - boolean used; - - public boolean usedInit() { - return used; - } - - public void initUsed(boolean used) { - this.used = used; - } - - void closeUsed() { - if (!(this.usedInit())) - return ; - - used = false; - } - - public long riKeySize = -1; - - public long riValueSize; - - public long riKeyOffset; - - public long riValueOffset; - - public long riTimestamp; - - public byte riId; - - public boolean isDeleted; - - public boolean replicationInputInit() { - return (this.riKeySize) >= 0; - } - - public void initReplicationInput(Bytes replicatedInputBytes) { - initReplicatedInputBytes(replicatedInputBytes); - riKeySize = this.m().keySizeMarshaller.readSize(replicatedInputBytes); - riValueSize = this.m().valueSizeMarshaller.readSize(replicatedInputBytes); - riTimestamp = replicatedInputBytes.readStopBit(); - riId = replicatedInputBytes.readByte(); - this.initReplicationUpdate(riTimestamp, riId); - isDeleted = replicatedInputBytes.readBoolean(); - riKeyOffset = replicatedInputBytes.position(); - riValueOffset = (riKeyOffset) + (riKeySize); - this.closeReplicationInputDependants(); - } - - public boolean isDeleted() { - assert this.replicationInputInit() : "ReplicationInput should be init"; - return this.isDeleted; - } - - public byte riId() { - assert this.replicationInputInit() : "ReplicationInput should be init"; - return this.riId; - } - - public long riKeyOffset() { - assert this.replicationInputInit() : "ReplicationInput should be init"; - return this.riKeyOffset; - } - - public long riKeySize() { - assert this.replicationInputInit() : "ReplicationInput should be init"; - return this.riKeySize; - } - - public long riTimestamp() { - assert this.replicationInputInit() : "ReplicationInput should be init"; - return this.riTimestamp; - } - - public long riValueOffset() { - assert this.replicationInputInit() : "ReplicationInput should be init"; - return this.riValueOffset; - } - - public long riValueSize() { - assert this.replicationInputInit() : "ReplicationInput should be init"; - return this.riValueSize; - } - - public void closeReplicationInput() { - if (!(this.replicationInputInit())) - return ; - - this.closeReplicationInputDependants(); - this.riKeySize = -1; - } - - public void closeReplicationInputDependants() { - this.replicatedInputKeyBytesValue.closeReplicatedInputKeyBytesDataSizeDependants(); - this.replicatedInputValueBytesValue.closeReplicatedInputValueBytesDataSizeDependants(); - this.replicatedInputKeyBytesValue.closeReplicatedInputKeyBytesDataGetUsingDependants(); - this.replicatedInputValueBytesValue.closeReplicatedInputValueBytesDataGetUsingDependants(); - } - - public void processReplicatedEvent() { - if ((riId()) == (this.m().identifier())) { - return ; - } - this.initInputKey(this.replicatedInputKeyBytesValue); - boolean debugEnabled = this.LOG.isDebugEnabled(); - this.innerUpdateLock.lock(); - if (isDeleted()) { - if (debugEnabled) { - this.LOG.debug("READING FROM SOURCE - into local-id={}, remote={}, remove(key={})", this.m().identifier(), riId(), this.inputKey()); - } - this.m().remoteOperations.remove(this); - this.m().setLastModificationTime(riId(), riTimestamp()); - return ; - } - String message = null; - if (debugEnabled) { - message = String.format("READING FROM SOURCE - into local-id=%d, remote-id=%d, put(key=%s,", this.m().identifier(), riId(), this.inputKey()); - } - this.m().remoteOperations.put(this, this.replicatedInputValueBytesValue); - this.m().setLastModificationTime(riId(), riTimestamp()); - if (debugEnabled) { - this.LOG.debug((((message + "value=") + (this.replicatedInputValueBytesValue)) + ")")); - } - } - - public Bytes inputBytes = null; - - public boolean inputBytesInit() { - return (this.inputBytes) != null; - } - - public void initInputBytes(Bytes inputBytes) { - this.inputBytes = inputBytes; - inputStore.setBytes(inputBytes); - this.closeInputBytesDependants(); - } - - public Bytes inputBytes() { - assert this.inputBytesInit() : "InputBytes should be init"; - return this.inputBytes; - } - - public void closeInputBytes() { - if (!(this.inputBytesInit())) - return ; - - this.closeInputBytesDependants(); - this.inputBytes = null; - } - - public void closeInputBytesDependants() { - this.closeInputKeyOffsets(); - this.closeFirstInputValueOffsets(); - this.inputFirstValueBytesValue.closeInputFirstValueBytesDataGetUsingDependants(); - this.inputKeyBytesValue.closeInputKeyBytesDataGetUsingDependants(); - this.closeSecondInputValueOffsets(); - this.inputSecondValueBytesValue.closeInputSecondValueBytesDataGetUsingDependants(); - } - - public long inputKeySize = -1; - - public long inputKeyOffset; - - public boolean inputKeyOffsetsInit() { - return (this.inputKeySize) >= 0; - } - - private void initInputKeyOffsets() { - inputKeySize = this.h().keySizeMarshaller.readSize(inputBytes()); - inputKeyOffset = inputBytes().position(); - this.closeInputKeyOffsetsDependants(); - } - - public long inputKeyOffset() { - if (!(this.inputKeyOffsetsInit())) - this.initInputKeyOffsets(); - - return this.inputKeyOffset; - } - - public long inputKeySize() { - if (!(this.inputKeyOffsetsInit())) - this.initInputKeyOffsets(); - - return this.inputKeySize; - } - - public void closeInputKeyOffsets() { - if (!(this.inputKeyOffsetsInit())) - return ; - - this.closeInputKeyOffsetsDependants(); - this.inputKeySize = -1; - } - - public void closeInputKeyOffsetsDependants() { - this.closeFirstInputValueOffsets(); - this.inputKeyBytesValue.closeInputKeyBytesDataSizeDependants(); - this.inputKeyBytesValue.closeInputKeyBytesDataGetUsingDependants(); - } - - public long firstInputValueSize = -1; - - public long firstInputValueOffset; - - public boolean firstInputValueOffsetsInit() { - return (this.firstInputValueSize) >= 0; - } - - private void initFirstInputValueOffsets() { - this.inputBytes().position(((this.inputKeyOffset()) + (this.inputKeySize()))); - firstInputValueSize = this.m().valueSizeMarshaller.readSize(this.inputBytes()); - firstInputValueOffset = this.inputBytes().position(); - this.closeFirstInputValueOffsetsDependants(); - } - - public long firstInputValueOffset() { - if (!(this.firstInputValueOffsetsInit())) - this.initFirstInputValueOffsets(); - - return this.firstInputValueOffset; - } - - public long firstInputValueSize() { - if (!(this.firstInputValueOffsetsInit())) - this.initFirstInputValueOffsets(); - - return this.firstInputValueSize; - } - - public void closeFirstInputValueOffsets() { - if (!(this.firstInputValueOffsetsInit())) - return ; - - this.closeFirstInputValueOffsetsDependants(); - this.firstInputValueSize = -1; - } - - public void closeFirstInputValueOffsetsDependants() { - this.closeSecondInputValueOffsets(); - this.inputFirstValueBytesValue.closeInputFirstValueBytesDataSizeDependants(); - this.inputFirstValueBytesValue.closeInputFirstValueBytesDataGetUsingDependants(); - } - - public long secondInputValueSize = -1; - - public long secondInputValueOffset; - - public boolean secondInputValueOffsetsInit() { - return (this.secondInputValueSize) >= 0; - } - - private void initSecondInputValueOffsets() { - this.inputBytes().position(((firstInputValueOffset()) + (firstInputValueSize()))); - secondInputValueSize = this.m().valueSizeMarshaller.readSize(this.inputBytes()); - secondInputValueOffset = this.inputBytes().position(); - this.closeSecondInputValueOffsetsDependants(); - } - - public long secondInputValueOffset() { - if (!(this.secondInputValueOffsetsInit())) - this.initSecondInputValueOffsets(); - - return this.secondInputValueOffset; - } - - public long secondInputValueSize() { - if (!(this.secondInputValueOffsetsInit())) - this.initSecondInputValueOffsets(); - - return this.secondInputValueSize; - } - - public void closeSecondInputValueOffsets() { - if (!(this.secondInputValueOffsetsInit())) - return ; - - this.closeSecondInputValueOffsetsDependants(); - this.secondInputValueSize = -1; - } - - public void closeSecondInputValueOffsetsDependants() { - this.inputSecondValueBytesValue.closeInputSecondValueBytesDataSizeDependants(); - this.inputSecondValueBytesValue.closeInputSecondValueBytesDataGetUsingDependants(); - } -} diff --git a/src/main/java/net/openhft/chronicle/map/impl/MapIterationContext.java b/src/main/java/net/openhft/chronicle/map/impl/MapIterationContext.java new file mode 100644 index 000000000..30818facf --- /dev/null +++ b/src/main/java/net/openhft/chronicle/map/impl/MapIterationContext.java @@ -0,0 +1,72 @@ +/* + * Copyright 2015 Higher Frequency Trading + * + * http://www.higherfrequencytrading.com + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package net.openhft.chronicle.map.impl; + +import net.openhft.chronicle.hash.impl.stage.data.bytes.EntryKeyBytesData; +import net.openhft.chronicle.hash.impl.stage.entry.*; +import net.openhft.chronicle.hash.impl.stage.hash.KeyBytesInterop; +import net.openhft.chronicle.hash.impl.stage.hash.OwnerThreadHolder; +import net.openhft.chronicle.hash.impl.stage.hash.ThreadLocalCopiesHolder; +import net.openhft.chronicle.map.impl.stage.data.bytes.EntryValueBytesData; +import net.openhft.chronicle.map.impl.stage.data.instance.WrappedValueInstanceData; +import net.openhft.chronicle.map.impl.stage.entry.MapEntryStages; +import net.openhft.chronicle.map.impl.stage.iter.DeprecatedMapKeyContextOnIteration; +import net.openhft.chronicle.map.impl.stage.iter.IterationCheckOnEachPublicOperation; +import net.openhft.chronicle.map.impl.stage.iter.MapSegmentIteration; +import net.openhft.chronicle.map.impl.stage.map.MapEntryOperationsDelegation; +import net.openhft.chronicle.map.impl.stage.map.ValueBytesInterop; +import net.openhft.chronicle.map.impl.stage.map.VanillaChronicleMapHolderImpl; +import net.openhft.chronicle.map.impl.stage.map.WrappedValueInstanceValueHolder; +import net.openhft.sg.Context; +import net.openhft.sg.Staged; + +@Staged +@Context(topLevel = { + CompilationAnchor.class, + OwnerThreadHolder.class, + ThreadLocalCopiesHolder.class, + VanillaChronicleMapHolderImpl.class, + + MapSegmentIteration.class, + + HashLookup.class, + KeyBytesInterop.class, + SegmentStages.class, + HashLookupPos.class, + IterationCheckOnEachPublicOperation.class, + AllocatedChunks.class, + + WrappedValueInstanceValueHolder.class, + MapEntryStages.class, + ValueBytesInterop.class, + MapEntryOperationsDelegation.class, +}, nested = { + ReadLock.class, + UpdateLock.class, + WriteLock.class, + + EntryKeyBytesData.class, + EntryValueBytesData.class, + + WrappedValueInstanceData.class, + + DeprecatedMapKeyContextOnIteration.class, +}) +public class MapIterationContext { +} diff --git a/src/main/java/net/openhft/chronicle/map/impl/MapQueryContext.java b/src/main/java/net/openhft/chronicle/map/impl/MapQueryContext.java new file mode 100644 index 000000000..3365306f5 --- /dev/null +++ b/src/main/java/net/openhft/chronicle/map/impl/MapQueryContext.java @@ -0,0 +1,104 @@ +/* + * Copyright 2015 Higher Frequency Trading + * + * http://www.higherfrequencytrading.com + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package net.openhft.chronicle.map.impl; + +import net.openhft.chronicle.hash.impl.stage.data.bytes.EntryKeyBytesData; +import net.openhft.chronicle.hash.impl.stage.data.bytes.InputKeyBytesData; +import net.openhft.chronicle.hash.impl.stage.data.instance.InputKeyInstanceData; +import net.openhft.chronicle.hash.impl.stage.entry.HashLookup; +import net.openhft.chronicle.hash.impl.stage.entry.ReadLock; +import net.openhft.chronicle.hash.impl.stage.entry.UpdateLock; +import net.openhft.chronicle.hash.impl.stage.entry.WriteLock; +import net.openhft.chronicle.hash.impl.stage.hash.KeyBytesInterop; +import net.openhft.chronicle.hash.impl.stage.hash.OwnerThreadHolder; +import net.openhft.chronicle.hash.impl.stage.hash.ThreadLocalCopiesHolder; +import net.openhft.chronicle.hash.impl.stage.input.HashInputBytes; +import net.openhft.chronicle.hash.impl.stage.query.HashLookupSearch; +import net.openhft.chronicle.hash.impl.stage.query.QueryHashLookupPos; +import net.openhft.chronicle.hash.impl.stage.query.QuerySegmentStages; +import net.openhft.chronicle.hash.impl.stage.query.SearchAllocatedChunks; +import net.openhft.chronicle.map.impl.stage.data.bytes.EntryValueBytesData; +import net.openhft.chronicle.map.impl.stage.data.bytes.InputFirstValueBytesData; +import net.openhft.chronicle.map.impl.stage.data.bytes.InputSecondValueBytesData; +import net.openhft.chronicle.map.impl.stage.data.instance.InputValueInstanceData; +import net.openhft.chronicle.map.impl.stage.data.instance.WrappedValueInstanceData; +import net.openhft.chronicle.map.impl.stage.entry.MapEntryStages; +import net.openhft.chronicle.map.impl.stage.input.MapInputBytesValues; +import net.openhft.chronicle.map.impl.stage.map.MapEntryOperationsDelegation; +import net.openhft.chronicle.map.impl.stage.map.ValueBytesInterop; +import net.openhft.chronicle.map.impl.stage.map.VanillaChronicleMapHolderImpl; +import net.openhft.chronicle.map.impl.stage.map.WrappedValueInstanceValueHolder; +import net.openhft.chronicle.map.impl.stage.query.*; +import net.openhft.chronicle.map.impl.stage.ret.DefaultReturnValue; +import net.openhft.chronicle.map.impl.stage.ret.UsingReturnValue; +import net.openhft.sg.Context; +import net.openhft.sg.Staged; + +@Staged +@Context(topLevel = { + CompilationAnchor.class, + OwnerThreadHolder.class, + ThreadLocalCopiesHolder.class, + + VanillaChronicleMapHolderImpl.class, + + HashLookup.class, + KeyBytesInterop.class, + QuerySegmentStages.class, + + HashLookupSearch.class, + QueryHashLookupPos.class, + + QueryCheckOnEachPublicOperation.class, + SearchAllocatedChunks.class, + + MapEntryStages.class, + MapEntryOperationsDelegation.class, + WrappedValueInstanceValueHolder.class, + MapQuery.class, + MapAbsent.class, + ValueBytesInterop.class, + MapAbsentHolder.class, + + HashInputBytes.class, + MapInputBytesValues.class, +}, +nested = { + ReadLock.class, + UpdateLock.class, + WriteLock.class, + + EntryKeyBytesData.class, + EntryValueBytesData.class, + + InputKeyInstanceData.class, + InputValueInstanceData.class, + + InputKeyBytesData.class, + InputFirstValueBytesData.class, + InputSecondValueBytesData.class, + + WrappedValueInstanceData.class, + DeprecatedMapKeyContextOnQuery.class, + DeprecatedMapAcquireContextOnQuery.class, + DefaultReturnValue.class, + UsingReturnValue.class, +}) +public class MapQueryContext { +} diff --git a/src/main/java/net/openhft/chronicle/map/impl/ReplicatedMapIterationContext.java b/src/main/java/net/openhft/chronicle/map/impl/ReplicatedMapIterationContext.java new file mode 100644 index 000000000..47a5c9791 --- /dev/null +++ b/src/main/java/net/openhft/chronicle/map/impl/ReplicatedMapIterationContext.java @@ -0,0 +1,78 @@ +/* + * Copyright 2015 Higher Frequency Trading + * + * http://www.higherfrequencytrading.com + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package net.openhft.chronicle.map.impl; + +import net.openhft.chronicle.hash.impl.stage.data.bytes.EntryKeyBytesData; +import net.openhft.chronicle.hash.impl.stage.entry.*; +import net.openhft.chronicle.hash.impl.stage.hash.KeyBytesInterop; +import net.openhft.chronicle.hash.impl.stage.hash.OwnerThreadHolder; +import net.openhft.chronicle.hash.impl.stage.hash.ThreadLocalCopiesHolder; +import net.openhft.chronicle.map.impl.stage.data.DummyValueZeroData; +import net.openhft.chronicle.map.impl.stage.data.bytes.EntryValueBytesData; +import net.openhft.chronicle.map.impl.stage.data.instance.WrappedValueInstanceData; +import net.openhft.chronicle.map.impl.stage.entry.ReplicatedMapEntryStages; +import net.openhft.chronicle.map.impl.stage.iter.DeprecatedMapKeyContextOnIteration; +import net.openhft.chronicle.map.impl.stage.iter.IterationCheckOnEachPublicOperation; +import net.openhft.chronicle.map.impl.stage.iter.ReplicatedMapSegmentIteration; +import net.openhft.chronicle.map.impl.stage.map.MapEntryOperationsDelegation; +import net.openhft.chronicle.map.impl.stage.map.ReplicatedChronicleMapHolderImpl; +import net.openhft.chronicle.map.impl.stage.map.ValueBytesInterop; +import net.openhft.chronicle.map.impl.stage.map.WrappedValueInstanceValueHolder; +import net.openhft.chronicle.map.impl.stage.replication.ReplicationUpdate; +import net.openhft.sg.Context; +import net.openhft.sg.Staged; + +@Staged +@Context(topLevel = { + CompilationAnchor.class, + OwnerThreadHolder.class, + ThreadLocalCopiesHolder.class, + ReplicatedChronicleMapHolderImpl.class, + + ReplicatedMapSegmentIteration.class, + + HashLookup.class, + KeyBytesInterop.class, + SegmentStages.class, + HashLookupPos.class, + IterationCheckOnEachPublicOperation.class, + AllocatedChunks.class, + + WrappedValueInstanceValueHolder.class, + ReplicatedMapEntryStages.class, + ValueBytesInterop.class, + MapEntryOperationsDelegation.class, + + ReplicationUpdate.class, +}, nested = { + ReadLock.class, + UpdateLock.class, + WriteLock.class, + + EntryKeyBytesData.class, + EntryValueBytesData.class, + + WrappedValueInstanceData.class, + + DeprecatedMapKeyContextOnIteration.class, + + DummyValueZeroData.class, +}) +public class ReplicatedMapIterationContext { +} diff --git a/src/main/java/net/openhft/chronicle/map/impl/ReplicatedMapQueryContext.java b/src/main/java/net/openhft/chronicle/map/impl/ReplicatedMapQueryContext.java new file mode 100644 index 000000000..595972ea8 --- /dev/null +++ b/src/main/java/net/openhft/chronicle/map/impl/ReplicatedMapQueryContext.java @@ -0,0 +1,117 @@ +/* + * Copyright 2015 Higher Frequency Trading + * + * http://www.higherfrequencytrading.com + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package net.openhft.chronicle.map.impl; + +import net.openhft.chronicle.hash.impl.stage.data.bytes.EntryKeyBytesData; +import net.openhft.chronicle.hash.impl.stage.data.bytes.InputKeyBytesData; +import net.openhft.chronicle.hash.impl.stage.data.instance.InputKeyInstanceData; +import net.openhft.chronicle.hash.impl.stage.entry.HashLookup; +import net.openhft.chronicle.hash.impl.stage.entry.ReadLock; +import net.openhft.chronicle.hash.impl.stage.entry.UpdateLock; +import net.openhft.chronicle.hash.impl.stage.entry.WriteLock; +import net.openhft.chronicle.hash.impl.stage.hash.KeyBytesInterop; +import net.openhft.chronicle.hash.impl.stage.hash.LogHolder; +import net.openhft.chronicle.hash.impl.stage.hash.OwnerThreadHolder; +import net.openhft.chronicle.hash.impl.stage.hash.ThreadLocalCopiesHolder; +import net.openhft.chronicle.hash.impl.stage.input.HashInputBytes; +import net.openhft.chronicle.hash.impl.stage.query.HashLookupSearch; +import net.openhft.chronicle.hash.impl.stage.query.QueryHashLookupPos; +import net.openhft.chronicle.hash.impl.stage.query.QuerySegmentStages; +import net.openhft.chronicle.hash.impl.stage.query.SearchAllocatedChunks; +import net.openhft.chronicle.map.impl.stage.data.DummyValueZeroData; +import net.openhft.chronicle.map.impl.stage.data.bytes.*; +import net.openhft.chronicle.map.impl.stage.data.instance.InputValueInstanceData; +import net.openhft.chronicle.map.impl.stage.data.instance.WrappedValueInstanceData; +import net.openhft.chronicle.map.impl.stage.entry.MapEntryStages; +import net.openhft.chronicle.map.impl.stage.entry.ReplicatedMapEntryStages; +import net.openhft.chronicle.map.impl.stage.input.MapInputBytesValues; +import net.openhft.chronicle.map.impl.stage.input.ReplicatedInput; +import net.openhft.chronicle.map.impl.stage.map.*; +import net.openhft.chronicle.map.impl.stage.query.*; +import net.openhft.chronicle.map.impl.stage.replication.ReplicationUpdate; +import net.openhft.chronicle.map.impl.stage.ret.BytesReturnValue; +import net.openhft.chronicle.map.impl.stage.ret.DefaultReturnValue; +import net.openhft.chronicle.map.impl.stage.ret.UsingReturnValue; +import net.openhft.sg.Context; +import net.openhft.sg.Staged; + +@Staged +@Context(topLevel = { + CompilationAnchor.class, + OwnerThreadHolder.class, + ThreadLocalCopiesHolder.class, + + LogHolder.class, + + ReplicatedChronicleMapHolderImpl.class, + + HashLookup.class, + KeyBytesInterop.class, + QuerySegmentStages.class, + + HashLookupSearch.class, + QueryHashLookupPos.class, + + QueryCheckOnEachPublicOperation.class, + SearchAllocatedChunks.class, + + ReplicatedMapEntryStages.class, + MapEntryOperationsDelegation.class, + WrappedValueInstanceValueHolder.class, + ReplicatedMapQuery.class, + ReplicatedMapAbsent.class, + ValueBytesInterop.class, + ReplicatedMapAbsentHolder.class, + ReplicationUpdate.class, + ReplicatedInput.class, + + HashInputBytes.class, + MapInputBytesValues.class, +}, +nested = { + ReadLock.class, + UpdateLock.class, + WriteLock.class, + + EntryKeyBytesData.class, + EntryValueBytesData.class, + + InputKeyInstanceData.class, + InputValueInstanceData.class, + BytesReturnValue.class, + + InputKeyBytesData.class, + InputFirstValueBytesData.class, + InputSecondValueBytesData.class, + + WrappedValueInstanceData.class, + DeprecatedMapKeyContextOnQuery.class, + DeprecatedMapAcquireContextOnQuery.class, + DefaultReturnValue.class, + UsingReturnValue.class, + + ReplicatedMapAbsentDelegating.class, + + ReplicatedInputKeyBytesData.class, + ReplicatedInputValueBytesData.class, + + DummyValueZeroData.class, +}) +public class ReplicatedMapQueryContext { +} diff --git a/src/main/java/net/openhft/chronicle/map/impl/stage/data/DummyValueZeroData.java b/src/main/java/net/openhft/chronicle/map/impl/stage/data/DummyValueZeroData.java new file mode 100644 index 000000000..83d4e0ada --- /dev/null +++ b/src/main/java/net/openhft/chronicle/map/impl/stage/data/DummyValueZeroData.java @@ -0,0 +1,57 @@ +/* + * Copyright 2015 Higher Frequency Trading + * + * http://www.higherfrequencytrading.com + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package net.openhft.chronicle.map.impl.stage.data; + +import net.openhft.chronicle.bytes.RandomDataInput; +import net.openhft.chronicle.bytes.ZeroRandomDataInput; +import net.openhft.chronicle.hash.AbstractData; +import net.openhft.chronicle.map.impl.VanillaChronicleMapHolder; +import net.openhft.sg.StageRef; +import net.openhft.sg.Staged; + +@Staged +public class DummyValueZeroData extends AbstractData { + @StageRef + VanillaChronicleMapHolder mh; + + @Override + public RandomDataInput bytes() { + return ZeroRandomDataInput.INSTANCE; + } + + @Override + public long offset() { + return 0; + } + + @Override + public long size() { + return mh.m().valueSizeMarshaller.minEncodableSize(); + } + + @Override + public V get() { + throw new UnsupportedOperationException(); + } + + @Override + public V getUsing(V usingInstance) { + throw new UnsupportedOperationException(); + } +} diff --git a/src/main/java/net/openhft/chronicle/map/impl/stage/data/bytes/EntryValueBytesData.java b/src/main/java/net/openhft/chronicle/map/impl/stage/data/bytes/EntryValueBytesData.java new file mode 100644 index 000000000..7a8629ce1 --- /dev/null +++ b/src/main/java/net/openhft/chronicle/map/impl/stage/data/bytes/EntryValueBytesData.java @@ -0,0 +1,80 @@ +/* + * Copyright 2015 Higher Frequency Trading + * + * http://www.higherfrequencytrading.com + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package net.openhft.chronicle.map.impl.stage.data.bytes; + +import net.openhft.chronicle.bytes.RandomDataInput; +import net.openhft.chronicle.hash.AbstractData; +import net.openhft.chronicle.hash.impl.stage.hash.CheckOnEachPublicOperation; +import net.openhft.chronicle.map.impl.stage.entry.MapEntryStages; +import net.openhft.chronicle.map.impl.stage.map.ValueBytesInterop; +import net.openhft.sg.Stage; +import net.openhft.sg.StageRef; +import net.openhft.sg.Staged; + +@Staged +public class EntryValueBytesData extends AbstractData { + + @StageRef ValueBytesInterop vi; + @StageRef MapEntryStages entry; + @StageRef CheckOnEachPublicOperation checkOnEachPublicOperation; + + + @Stage("CachedEntryValue") private V cachedEntryValue; + @Stage("CachedEntryValue") private boolean cachedEntryValueRead = false; + + private void initCachedEntryValue() { + cachedEntryValue = innerGetUsing(cachedEntryValue); + cachedEntryValueRead = true; + } + + @Override + public RandomDataInput bytes() { + checkOnEachPublicOperation.checkOnEachPublicOperation(); + return entry.entryBS; + } + + @Override + public long offset() { + checkOnEachPublicOperation.checkOnEachPublicOperation(); + return entry.valueOffset; + } + + @Override + public long size() { + checkOnEachPublicOperation.checkOnEachPublicOperation(); + return entry.valueSize; + } + + @Override + public V get() { + checkOnEachPublicOperation.checkOnEachPublicOperation(); + return cachedEntryValue; + } + + @Override + public V getUsing(V usingValue) { + checkOnEachPublicOperation.checkOnEachPublicOperation(); + return innerGetUsing(usingValue); + } + + private V innerGetUsing(V usingValue) { + entry.entryBytes.position(entry.valueOffset); + return vi.valueReader.read(entry.entryBytes, size(), usingValue); + } +} diff --git a/src/main/java/net/openhft/chronicle/map/impl/stage/data/bytes/InputFirstValueBytesData.java b/src/main/java/net/openhft/chronicle/map/impl/stage/data/bytes/InputFirstValueBytesData.java new file mode 100644 index 000000000..5019b730a --- /dev/null +++ b/src/main/java/net/openhft/chronicle/map/impl/stage/data/bytes/InputFirstValueBytesData.java @@ -0,0 +1,70 @@ +/* + * Copyright 2015 Higher Frequency Trading + * + * http://www.higherfrequencytrading.com + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package net.openhft.chronicle.map.impl.stage.data.bytes; + +import net.openhft.chronicle.bytes.RandomDataInput; +import net.openhft.chronicle.hash.AbstractData; +import net.openhft.chronicle.hash.impl.stage.input.HashInputBytes; +import net.openhft.chronicle.map.impl.stage.input.MapInputBytesValues; +import net.openhft.chronicle.map.impl.stage.map.ValueBytesInterop; +import net.openhft.sg.Stage; +import net.openhft.sg.StageRef; +import net.openhft.sg.Staged; + +@Staged +public class InputFirstValueBytesData extends AbstractData { + + @StageRef HashInputBytes in; + @StageRef MapInputBytesValues values; + @StageRef ValueBytesInterop vi; + + @Stage("CachedBytesInputFirstValue") private V cachedBytesInputFirstValue; + @Stage("CachedBytesInputFirstValue") private boolean cachedBytesInputFirstValueRead = false; + + private void initCachedBytesInputFirstValue() { + cachedBytesInputFirstValue = getUsing(cachedBytesInputFirstValue); + cachedBytesInputFirstValueRead = true; + } + + @Override + public RandomDataInput bytes() { + return in.inputStore; + } + + @Override + public long offset() { + return values.firstInputValueOffset; + } + + @Override + public long size() { + return values.firstInputValueSize; + } + + @Override + public V get() { + return cachedBytesInputFirstValue; + } + + @Override + public V getUsing(V usingValue) { + in.inputBytes.position(values.firstInputValueOffset); + return vi.valueReader.read(in.inputBytes, size(), usingValue); + } +} diff --git a/src/main/java/net/openhft/chronicle/map/impl/stage/data/bytes/InputSecondValueBytesData.java b/src/main/java/net/openhft/chronicle/map/impl/stage/data/bytes/InputSecondValueBytesData.java new file mode 100644 index 000000000..d1a486115 --- /dev/null +++ b/src/main/java/net/openhft/chronicle/map/impl/stage/data/bytes/InputSecondValueBytesData.java @@ -0,0 +1,70 @@ +/* + * Copyright 2015 Higher Frequency Trading + * + * http://www.higherfrequencytrading.com + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package net.openhft.chronicle.map.impl.stage.data.bytes; + +import net.openhft.chronicle.bytes.RandomDataInput; +import net.openhft.chronicle.hash.AbstractData; +import net.openhft.chronicle.hash.impl.stage.input.HashInputBytes; +import net.openhft.chronicle.map.impl.stage.input.MapInputBytesValues; +import net.openhft.chronicle.map.impl.stage.map.ValueBytesInterop; +import net.openhft.sg.Stage; +import net.openhft.sg.StageRef; +import net.openhft.sg.Staged; + +@Staged +public class InputSecondValueBytesData extends AbstractData { + + @StageRef HashInputBytes in; + @StageRef MapInputBytesValues values; + @StageRef ValueBytesInterop vi; + + @Stage("CachedBytesInputSecondValue") private V cachedBytesInputSecondValue; + @Stage("CachedBytesInputSecondValue") private boolean cachedBytesInputSecondValueRead = false; + + private void initCachedBytesInputSecondValue() { + cachedBytesInputSecondValue = getUsing(cachedBytesInputSecondValue); + cachedBytesInputSecondValueRead = true; + } + + @Override + public RandomDataInput bytes() { + return in.inputStore; + } + + @Override + public long offset() { + return values.secondInputValueOffset; + } + + @Override + public long size() { + return values.secondInputValueSize; + } + + @Override + public V get() { + return cachedBytesInputSecondValue; + } + + @Override + public V getUsing(V usingValue) { + in.inputBytes.position(values.secondInputValueOffset); + return vi.valueReader.read(in.inputBytes, size(), usingValue); + } +} diff --git a/src/main/java/net/openhft/chronicle/map/impl/stage/data/bytes/ReplicatedInputKeyBytesData.java b/src/main/java/net/openhft/chronicle/map/impl/stage/data/bytes/ReplicatedInputKeyBytesData.java new file mode 100644 index 000000000..4a7ad6d01 --- /dev/null +++ b/src/main/java/net/openhft/chronicle/map/impl/stage/data/bytes/ReplicatedInputKeyBytesData.java @@ -0,0 +1,71 @@ +/* + * Copyright 2015 Higher Frequency Trading + * + * http://www.higherfrequencytrading.com + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package net.openhft.chronicle.map.impl.stage.data.bytes; + +import net.openhft.chronicle.bytes.RandomDataInput; +import net.openhft.chronicle.hash.AbstractData; +import net.openhft.chronicle.hash.impl.stage.hash.KeyBytesInterop; +import net.openhft.chronicle.map.impl.stage.input.ReplicatedInput; +import net.openhft.lang.io.Bytes; +import net.openhft.sg.Stage; +import net.openhft.sg.StageRef; +import net.openhft.sg.Staged; + + +@Staged +public class ReplicatedInputKeyBytesData extends AbstractData { + @StageRef ReplicatedInput in; + @StageRef KeyBytesInterop ki; + + @Stage("CachedBytesReplicatedInputKey") private K cachedBytesReplicatedInputKey; + @Stage("CachedBytesReplicatedInputKey") private boolean cachedBytesReplicatedInputKeyRead = + false; + + private void initCachedBytesReplicatedInputKey() { + cachedBytesReplicatedInputKey = getUsing(cachedBytesReplicatedInputKey); + cachedBytesReplicatedInputKeyRead = true; + } + + @Override + public RandomDataInput bytes() { + return in.replicatedInputStore; + } + + @Override + public long offset() { + return in.riKeyOffset; + } + + @Override + public long size() { + return in.riKeySize; + } + + @Override + public K get() { + return cachedBytesReplicatedInputKey; + } + + @Override + public K getUsing(K usingKey) { + Bytes inputBytes = in.replicatedInputBytes; + inputBytes.position(in.riKeyOffset); + return ki.keyReader.read(inputBytes, size(), usingKey); + } +} diff --git a/src/main/java/net/openhft/chronicle/map/impl/stage/data/bytes/ReplicatedInputValueBytesData.java b/src/main/java/net/openhft/chronicle/map/impl/stage/data/bytes/ReplicatedInputValueBytesData.java new file mode 100644 index 000000000..a6693bc05 --- /dev/null +++ b/src/main/java/net/openhft/chronicle/map/impl/stage/data/bytes/ReplicatedInputValueBytesData.java @@ -0,0 +1,71 @@ +/* + * Copyright 2015 Higher Frequency Trading + * + * http://www.higherfrequencytrading.com + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package net.openhft.chronicle.map.impl.stage.data.bytes; + +import net.openhft.chronicle.bytes.RandomDataInput; +import net.openhft.chronicle.hash.AbstractData; +import net.openhft.chronicle.map.impl.stage.input.ReplicatedInput; +import net.openhft.chronicle.map.impl.stage.map.ValueBytesInterop; +import net.openhft.lang.io.Bytes; +import net.openhft.sg.Stage; +import net.openhft.sg.StageRef; +import net.openhft.sg.Staged; + + +@Staged +public class ReplicatedInputValueBytesData extends AbstractData { + @StageRef ReplicatedInput in; + @StageRef ValueBytesInterop ki; + + @Stage("CachedBytesReplicatedInputValue") private V cachedBytesReplicatedInputValue; + @Stage("CachedBytesReplicatedInputValue") private boolean cachedBytesReplicatedInputValueRead = + false; + + private void initCachedBytesReplicatedInputValue() { + cachedBytesReplicatedInputValue = getUsing(cachedBytesReplicatedInputValue); + cachedBytesReplicatedInputValueRead = true; + } + + @Override + public RandomDataInput bytes() { + return in.replicatedInputStore; + } + + @Override + public long offset() { + return in.riValueOffset; + } + + @Override + public long size() { + return in.riValueSize; + } + + @Override + public V get() { + return cachedBytesReplicatedInputValue; + } + + @Override + public V getUsing(V usingValue) { + Bytes inputBytes = in.replicatedInputBytes; + inputBytes.position(in.riValueOffset); + return ki.valueReader.read(inputBytes, size(), usingValue); + } +} diff --git a/src/main/java/net/openhft/chronicle/map/impl/stage/data/instance/InputValueInstanceData.java b/src/main/java/net/openhft/chronicle/map/impl/stage/data/instance/InputValueInstanceData.java new file mode 100644 index 000000000..4b3aaf4bb --- /dev/null +++ b/src/main/java/net/openhft/chronicle/map/impl/stage/data/instance/InputValueInstanceData.java @@ -0,0 +1,65 @@ +/* + * Copyright 2015 Higher Frequency Trading + * + * http://www.higherfrequencytrading.com + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package net.openhft.chronicle.map.impl.stage.data.instance; + +import net.openhft.chronicle.hash.impl.CopyingInstanceData; +import net.openhft.chronicle.hash.serialization.internal.MetaBytesInterop; +import net.openhft.chronicle.map.impl.data.instance.ValueInitableData; +import net.openhft.chronicle.map.impl.stage.map.ValueBytesInterop; +import net.openhft.lang.io.DirectBytes; +import net.openhft.sg.Stage; +import net.openhft.sg.StageRef; +import net.openhft.sg.Staged; + +@Staged +public abstract class InputValueInstanceData> + extends CopyingInstanceData implements ValueInitableData { + + @StageRef ValueBytesInterop vi; + + private V value = null; + + @Override + public void initValue(V value) { + this.value = value; + } + + @Override + public V instance() { + return value; + } + + @Stage("Buffer") private DirectBytes buffer; + @Stage("Buffer") private boolean marshalled = false; + + private void initBuffer() { + MVI mvi = vi.valueMetaInterop(value); + long size = mvi.size(vi.valueInterop, value); + buffer = getBuffer(this.buffer, size); + mvi.write(vi.valueInterop, buffer, value); + buffer.flip(); + marshalled = true; + } + + @Override + public V getUsing(V usingValue) { + buffer.position(0); + return vi.valueReader.read(buffer, buffer.limit(), usingValue); + } +} diff --git a/src/main/java/net/openhft/chronicle/map/impl/stage/data/instance/WrappedValueInstanceData.java b/src/main/java/net/openhft/chronicle/map/impl/stage/data/instance/WrappedValueInstanceData.java new file mode 100644 index 000000000..2969efc30 --- /dev/null +++ b/src/main/java/net/openhft/chronicle/map/impl/stage/data/instance/WrappedValueInstanceData.java @@ -0,0 +1,101 @@ +/* + * Copyright 2015 Higher Frequency Trading + * + * http://www.higherfrequencytrading.com + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package net.openhft.chronicle.map.impl.stage.data.instance; + +import net.openhft.chronicle.hash.impl.CopyingInstanceData; +import net.openhft.chronicle.hash.serialization.internal.MetaBytesInterop; +import net.openhft.chronicle.map.impl.stage.map.ValueBytesInterop; +import net.openhft.chronicle.map.impl.VanillaChronicleMapHolder; +import net.openhft.lang.io.DirectBytes; +import net.openhft.sg.Stage; +import net.openhft.sg.StageRef; +import net.openhft.sg.Staged; + +@Staged +public class WrappedValueInstanceData< + V, VI, MVI extends MetaBytesInterop> + extends CopyingInstanceData { + + @StageRef VanillaChronicleMapHolder mh; + @StageRef ValueBytesInterop vi; + + private WrappedValueInstanceData next; + + boolean nextInit() { + return true; + } + + void closeNext() { + // do nothing + } + + @Stage("Next") + public WrappedValueInstanceData getUnusedWrappedValue() { + if (!valueInit()) + return this; + if (next == null) + next = new WrappedValueInstanceData<>(); + return next.getUnusedWrappedValue(); + } + + private V value; + + public boolean valueInit() { + return value != null; + } + + public void initValue(V value) { + mh.m().checkValue(value); + this.value = value; + } + + public void closeValue() { + value = null; + if (next != null) + next.closeValue(); + } + + @Override + public V instance() { + return value; + } + + @Stage("Buffer") private DirectBytes buf; + @Stage("Buffer") private boolean marshalled = false; + + private void initBuffer() { + MVI mvi = vi.valueMetaInterop(value); + long size = mvi.size(vi.valueInterop, value); + buf = getBuffer(this.buf, size); + mvi.write(vi.valueInterop, buf, value); + buf.flip(); + marshalled = true; + } + + @Override + public DirectBytes buffer() { + return buf; + } + + @Override + public V getUsing(V usingValue) { + buf.position(0); + return vi.valueReader.read(buf, buf.limit(), usingValue); + } +} diff --git a/src/main/java/net/openhft/chronicle/map/impl/stage/entry/MapEntryStages.java b/src/main/java/net/openhft/chronicle/map/impl/stage/entry/MapEntryStages.java new file mode 100644 index 000000000..9259f36f4 --- /dev/null +++ b/src/main/java/net/openhft/chronicle/map/impl/stage/entry/MapEntryStages.java @@ -0,0 +1,270 @@ +/* + * Copyright 2015 Higher Frequency Trading + * + * http://www.higherfrequencytrading.com + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package net.openhft.chronicle.map.impl.stage.entry; + +import net.openhft.chronicle.hash.Data; +import net.openhft.chronicle.hash.impl.stage.entry.AllocatedChunks; +import net.openhft.chronicle.hash.impl.stage.entry.HashEntryStages; +import net.openhft.chronicle.hash.impl.stage.entry.HashLookup; +import net.openhft.chronicle.map.MapEntry; +import net.openhft.chronicle.map.VanillaChronicleMap; +import net.openhft.chronicle.map.impl.VanillaChronicleMapHolder; +import net.openhft.chronicle.map.impl.stage.data.bytes.EntryValueBytesData; +import net.openhft.sg.Stage; +import net.openhft.sg.StageRef; +import net.openhft.sg.Staged; +import org.jetbrains.annotations.NotNull; + +@Staged +public abstract class MapEntryStages extends HashEntryStages + implements MapEntry { + + @StageRef VanillaChronicleMapHolder mh; + @StageRef AllocatedChunks allocatedChunks; + @StageRef HashLookup hashLookup; + + long countValueSizeOffset() { + return keyEnd(); + } + + public long valueSizeOffset = -1; + + void initValueSizeOffset() { + valueSizeOffset = countValueSizeOffset(); + } + + @Stage("ValSize") public long valueSize = -1; + @Stage("ValSize") public long valueOffset; + + @Stage("ValSize") private void countValueOffset() { + mh.m().alignment.alignPositionAddr(entryBytes); + valueOffset = entryBytes.position(); + } + + void initValSize(long valueSize) { + this.valueSize = valueSize; + entryBytes.position(valueSizeOffset); + mh.m().valueSizeMarshaller.writeSize(entryBytes, valueSize); + countValueOffset(); + } + + void initValSize() { + entryBytes.position(valueSizeOffset); + valueSize = mh.m().readValueSize(entryBytes); + countValueOffset(); + } + + void initValSizeEqualToOld(long oldValueSizeOffset, long oldValueSize, long oldValueOffset) { + valueSize = oldValueSize; + valueOffset = valueSizeOffset + (oldValueOffset - oldValueSizeOffset); + } + + public void initValue(Data value) { + entryBytes.position(valueSizeOffset); + initValSize(value.size()); + writeValue(value); + } + + public void writeValue(Data value) { + value.writeTo(entryBS, valueOffset); + } + + public void initValueWithoutSize( + Data value, long oldValueSizeOffset, long oldValueSize, long oldValueOffset) { + assert oldValueSize == value.size(); + initValSizeEqualToOld(oldValueSizeOffset, oldValueSize, oldValueOffset); + writeValue(value); + } + + @Override + protected long entryEnd() { + return valueOffset + valueSize; + } + + @StageRef public EntryValueBytesData entryValue; + + @NotNull + @Override + public Data value() { + checkOnEachPublicOperation.checkOnEachPublicOperation(); + return entryValue; + } + + public void putValueDeletedEntry(Data newValue) { + assert s.innerUpdateLock.isHeldByCurrentThread(); + + int newSizeInChunks; + long entryStartOffset = keySizeOffset; + long newSizeOfEverythingBeforeValue = -1; + boolean newValueSizeIsDifferent = newValue.size() != valueSize; + if (newValueSizeIsDifferent) { + newSizeOfEverythingBeforeValue = newSizeOfEverythingBeforeValue(newValue); + long newValueOffset = mh.m().alignment.alignAddr( + entryStartOffset + newSizeOfEverythingBeforeValue); + long newEntrySize = newValueOffset + newValue.size() - entryStartOffset; + newSizeInChunks = mh.m().inChunks(newEntrySize); + } else { + newSizeInChunks = entrySizeInChunks; + } + if (pos + newSizeInChunks < s.freeList.size() && + s.freeList.allClear(pos, pos + newSizeInChunks)) { + s.freeList.set(pos, pos + newSizeInChunks); + s.innerWriteLock.lock(); + allocatedChunks.incrementSegmentEntriesIfNeeded(); + if (newValueSizeIsDifferent) { + initValue(newValue); + } else { + writeValue(newValue); + } + } else { + if (newValueSizeIsDifferent) { + assert newSizeOfEverythingBeforeValue >= 0; + } else { + newSizeOfEverythingBeforeValue = newSizeOfEverythingBeforeValue(newValue); + } + long entrySize = innerEntrySize(newSizeOfEverythingBeforeValue, newValue.size()); + if (newValueSizeIsDifferent) { + allocatedChunks.initEntryAndKeyCopying(entrySize, valueSizeOffset - entryStartOffset); + initValue(newValue); + } else { + long oldValueSizeOffset = valueSizeOffset; + long oldValueSize = valueSize; + long oldValueOffset = valueOffset; + allocatedChunks.initEntryAndKeyCopying(entrySize, valueOffset - entryStartOffset); + initValueWithoutSize(newValue, oldValueSizeOffset, oldValueSize, oldValueOffset); + } + freeExtraAllocatedChunks(); + } + hashLookup.putValueVolatile(hlp.hashLookupPos, pos); + } + + public void writeValueAndPutPos(Data value) { + initValue(value); + freeExtraAllocatedChunks(); + hashLookup.putValueVolatile(hlp.hashLookupPos, pos); + } + + public long newSizeOfEverythingBeforeValue(Data newValue) { + return valueSizeOffset + mh.m().valueSizeMarshaller.sizeEncodingSize(newValue.size()) - + keySizeOffset; + } + + public void innerDefaultReplaceValue(Data newValue) { + assert s.innerUpdateLock.isHeldByCurrentThread(); + + boolean newValueSizeIsDifferent = newValue.size() != this.valueSize; + if (newValueSizeIsDifferent) { + long newSizeOfEverythingBeforeValue = newSizeOfEverythingBeforeValue(newValue); + long entryStartOffset = keySizeOffset; + VanillaChronicleMap m = mh.m(); + long newValueOffset = m.alignment.alignAddr( + entryStartOffset + newSizeOfEverythingBeforeValue); + long newEntrySize = newValueOffset + newValue.size() - entryStartOffset; + int newSizeInChunks = m.inChunks(newEntrySize); + newValueDoesNotFit: + if (newSizeInChunks > entrySizeInChunks) { + if (newSizeInChunks > m.maxChunksPerEntry) { + throw new IllegalArgumentException("Value too large: " + + "entry takes " + newSizeInChunks + " chunks, " + + m.maxChunksPerEntry + " is maximum."); + } + if (s.freeList.allClear(pos + entrySizeInChunks, pos + newSizeInChunks)) { + s.freeList.set(pos + entrySizeInChunks, pos + newSizeInChunks); + break newValueDoesNotFit; + } + relocation(newValue, newSizeOfEverythingBeforeValue); + return; + } else if (newSizeInChunks < entrySizeInChunks) { + // Freeing extra chunks + s.freeList.clear(pos + newSizeInChunks, pos + entrySizeInChunks); + // Do NOT reset nextPosToSearchFrom, because if value + // once was larger it could easily became larger again, + // But if these chunks will be taken by that time, + // this entry will need to be relocated. + } + // new size != old size => size is not constant => size is actually written => + // to prevent (at least) this execution: + // 1. concurrent reader thread reads the size + // 2. this thread updates the size and the value + // 3. concurrent reader reads the value + // We MUST upgrade to exclusive lock + } else { + // TODO to turn the following block on, JLANG-46 is required. Also unclear what happens + // if the value is DataValue generated with 2, 4 or 8 distinct bytes, putting on-heap + // implementation of such value is also not atomic currently, however there is a way + // to make it atomic, we should identify such cases and make a single write: + // state = UNSAFE.getLong(onHeapValueObject, offsetToTheFirstField); + // bytes.writeLong(state); +// boolean newValueSizeIsPowerOf2 = ((newValueSize - 1L) & newValueSize) != 0; +// if (!newValueSizeIsPowerOf2 || newValueSize > 8L) { +// // if the new value size is 1, 2, 4, or 8, it is written not atomically only if +// // the user provided own marshaller and writes value byte-by-byte, that is very +// // unlikely. in this case the user should update acquire write lock before write +// // updates himself +// upgradeToWriteLock(); +// } + } + s.innerWriteLock.lock(); + + if (newValueSizeIsDifferent) { + initValue(newValue); + } else { + writeValue(newValue); + } + hashLookup.putValueVolatile(hlp.hashLookupPos, pos); + } + + protected void relocation(Data newValue, long newSizeOfEverythingBeforeValue) { + s.free(pos, entrySizeInChunks); + long entrySize = innerEntrySize(newSizeOfEverythingBeforeValue, newValue.size()); + allocatedChunks.initEntryAndKeyCopying(entrySize, valueSizeOffset - keySizeOffset); + writeValueAndPutPos(newValue); + } + + public final long entrySize(long keySize, long valueSize) { + long sizeOfEverythingBeforeValue = sizeOfEverythingBeforeValue(keySize, valueSize); + return innerEntrySize(sizeOfEverythingBeforeValue, valueSize); + } + + public long innerEntrySize(long sizeOfEverythingBeforeValue, long valueSize) { + if (mh.m().constantlySizedEntry) { + return mh.m().alignment.alignAddr(sizeOfEverythingBeforeValue + valueSize); + } else if (mh.m().couldNotDetermineAlignmentBeforeAllocation) { + return sizeOfEverythingBeforeValue + mh.m().worstAlignment + valueSize; + } else { + return mh.m().alignment.alignAddr(sizeOfEverythingBeforeValue) + valueSize; + } + } + + long sizeOfEverythingBeforeValue(long keySize, long valueSize) { + return mh.m().metaDataBytes + + mh.m().keySizeMarshaller.sizeEncodingSize(keySize) + keySize + + mh.m().valueSizeMarshaller.sizeEncodingSize(valueSize); + } + + public final void freeExtraAllocatedChunks() { + // fast path + if (!mh.m().constantlySizedEntry && mh.m().couldNotDetermineAlignmentBeforeAllocation && + entrySizeInChunks < allocatedChunks.allocatedChunks) { + s.free(pos + entrySizeInChunks, allocatedChunks.allocatedChunks - entrySizeInChunks); + } else { + initTheEntrySizeInChunks(allocatedChunks.allocatedChunks); + } + } +} diff --git a/src/main/java/net/openhft/chronicle/map/impl/stage/entry/ReplicatedMapEntryStages.java b/src/main/java/net/openhft/chronicle/map/impl/stage/entry/ReplicatedMapEntryStages.java new file mode 100644 index 000000000..af49d094e --- /dev/null +++ b/src/main/java/net/openhft/chronicle/map/impl/stage/entry/ReplicatedMapEntryStages.java @@ -0,0 +1,168 @@ +/* + * Copyright 2015 Higher Frequency Trading + * + * http://www.higherfrequencytrading.com + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package net.openhft.chronicle.map.impl.stage.entry; + +import net.openhft.chronicle.hash.Data; +import net.openhft.chronicle.hash.replication.TimeProvider; +import net.openhft.chronicle.map.impl.ReplicatedChronicleMapHolder; +import net.openhft.chronicle.map.impl.stage.replication.ReplicationUpdate; +import net.openhft.chronicle.map.replication.MapReplicableEntry; +import net.openhft.sg.Stage; +import net.openhft.sg.StageRef; +import net.openhft.sg.Staged; + +import static net.openhft.chronicle.map.ReplicatedChronicleMap.ADDITIONAL_ENTRY_BYTES; + +@Staged +public abstract class ReplicatedMapEntryStages extends MapEntryStages + implements MapReplicableEntry { + + @StageRef ReplicatedChronicleMapHolder mh; + @StageRef ReplicationUpdate ru; + + @Stage("ReplicationState") long replicationBytesOffset = -1; + + void initReplicationState() { + replicationBytesOffset = keyEnd(); + } + + void updateReplicationState(long timestamp, byte identifier) { + entryBytes.position(replicationBytesOffset); + entryBytes.writeLong(timestamp); + entryBytes.writeByte(identifier); + } + + private long timestampOffset() { + return replicationBytesOffset; + } + + public long timestamp() { + return entryBS.readLong(replicationBytesOffset); + } + + private long identifierOffset() { + return replicationBytesOffset + 8L; + } + + byte identifier() { + return entryBS.readByte(identifierOffset()); + } + + private long entryDeletedOffset() { + return replicationBytesOffset + 9L; + } + + public boolean entryDeleted() { + return entryBS.readBoolean(entryDeletedOffset()); + } + + public void writeEntryPresent() { + entryBS.writeBoolean(entryDeletedOffset(), false); + } + + public void writeEntryDeleted() { + entryBS.writeBoolean(entryDeletedOffset(), true); + } + + @Override + public byte originIdentifier() { + checkOnEachPublicOperation.checkOnEachPublicOperation(); + return identifier(); + } + + @Override + public long originTimestamp() { + checkOnEachPublicOperation.checkOnEachPublicOperation(); + return timestamp(); + } + + @Override + long countValueSizeOffset() { + return super.countValueSizeOffset() + ADDITIONAL_ENTRY_BYTES; + } + + @Override + public void updateOrigin(byte newIdentifier, long newTimestamp) { + checkOnEachPublicOperation.checkOnEachPublicOperation(); + s.innerWriteLock.lock(); + updateReplicationState(newTimestamp, newIdentifier); + } + + @Override + public void dropChanged() { + checkOnEachPublicOperation.checkOnEachPublicOperation(); + s.innerUpdateLock.lock(); + ru.dropChange(); + } + + @Override + public void raiseChanged() { + checkOnEachPublicOperation.checkOnEachPublicOperation(); + s.innerUpdateLock.lock(); + ru.raiseChange(); + } + + public void updatedReplicationStateOnPresentEntry() { + if (!ru.replicationUpdateInit()) { + s.innerWriteLock.lock(); + long timestamp; + if (identifier() != mh.m().identifier()) { + timestamp = Math.max(timestamp() + 1, mh.m().timeProvider.currentTime()); + } else { + timestamp = mh.m().timeProvider.currentTime(); + } + updateReplicationState(timestamp, mh.m().identifier()); + } + } + + public void updatedReplicationStateOnAbsentEntry() { + if (!ru.replicationUpdateInit()) { + s.innerWriteLock.lock(); + updateReplicationState(mh.m().timeProvider.currentTime(), mh.m().identifier()); + } + } + + @Override + protected void relocation(Data newValue, long newSizeOfEverythingBeforeValue) { + long oldPos = pos; + super.relocation(newValue, newSizeOfEverythingBeforeValue); + ru.moveChange(oldPos, pos); + } + + private boolean testTimeStampInSensibleRange() { + if (mh.m().timeProvider == TimeProvider.SYSTEM) { + long currentTime = TimeProvider.SYSTEM.currentTime(); + assert Math.abs(currentTime - timestamp()) <= 100000000 : + "unrealistic timestamp: " + timestamp(); + assert Math.abs(currentTime - ru.innerRemoteTimestamp) <= 100000000 : + "unrealistic innerRemoteTimestamp: " + ru.innerRemoteTimestamp; + } + return true; + } + + @Override + long sizeOfEverythingBeforeValue(long keySize, long valueSize) { + return super.sizeOfEverythingBeforeValue(keySize, valueSize) + ADDITIONAL_ENTRY_BYTES; + } + + @Override + public void putValueDeletedEntry(Data newValue) { + throw new AssertionError("Replicated Map doesn't remove entries truly, yet"); + } +} diff --git a/src/main/java/net/openhft/chronicle/map/impl/stage/input/MapInputBytesValues.java b/src/main/java/net/openhft/chronicle/map/impl/stage/input/MapInputBytesValues.java new file mode 100644 index 000000000..813d012c1 --- /dev/null +++ b/src/main/java/net/openhft/chronicle/map/impl/stage/input/MapInputBytesValues.java @@ -0,0 +1,50 @@ +/* + * Copyright 2015 Higher Frequency Trading + * + * http://www.higherfrequencytrading.com + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package net.openhft.chronicle.map.impl.stage.input; + +import net.openhft.chronicle.hash.impl.stage.input.HashInputBytes; +import net.openhft.chronicle.map.impl.VanillaChronicleMapHolder; +import net.openhft.sg.Stage; +import net.openhft.sg.StageRef; +import net.openhft.sg.Staged; + +@Staged +public class MapInputBytesValues { + + @StageRef HashInputBytes in; + @StageRef VanillaChronicleMapHolder mh; + + @Stage("FirstInputValueOffsets") public long firstInputValueSize = -1; + @Stage("FirstInputValueOffsets") public long firstInputValueOffset; + + private void initFirstInputValueOffsets() { + in.inputBytes.position(in.inputKeyOffset + in.inputKeySize); + firstInputValueSize = mh.m().valueSizeMarshaller.readSize(in.inputBytes); + firstInputValueOffset = in.inputBytes.position(); + } + + @Stage("SecondInputValueOffsets") public long secondInputValueSize = -1; + @Stage("SecondInputValueOffsets") public long secondInputValueOffset; + + private void initSecondInputValueOffsets() { + in.inputBytes.position(firstInputValueOffset + firstInputValueSize); + secondInputValueSize = mh.m().valueSizeMarshaller.readSize(in.inputBytes); + secondInputValueOffset = in.inputBytes.position(); + } +} diff --git a/src/main/java/net/openhft/chronicle/map/impl/stage/input/ReplicatedInput.java b/src/main/java/net/openhft/chronicle/map/impl/stage/input/ReplicatedInput.java new file mode 100644 index 000000000..68ad3bac7 --- /dev/null +++ b/src/main/java/net/openhft/chronicle/map/impl/stage/input/ReplicatedInput.java @@ -0,0 +1,112 @@ +package net.openhft.chronicle.map.impl.stage.input; + +import net.openhft.chronicle.hash.Data; +import net.openhft.chronicle.hash.impl.JavaLangBytesReusableBytesStore; +import net.openhft.chronicle.hash.impl.stage.entry.SegmentStages; +import net.openhft.chronicle.hash.impl.stage.hash.LogHolder; +import net.openhft.chronicle.hash.replication.RemoteOperationContext; +import net.openhft.chronicle.map.impl.ReplicatedChronicleMapHolder; +import net.openhft.chronicle.map.impl.stage.data.DummyValueZeroData; +import net.openhft.chronicle.map.impl.stage.data.bytes.ReplicatedInputKeyBytesData; +import net.openhft.chronicle.map.impl.stage.data.bytes.ReplicatedInputValueBytesData; +import net.openhft.chronicle.map.impl.stage.entry.ReplicatedMapEntryStages; +import net.openhft.chronicle.map.impl.stage.query.ReplicatedMapQuery; +import net.openhft.chronicle.map.impl.stage.replication.ReplicationUpdate; +import net.openhft.chronicle.map.replication.MapRemoteQueryContext; +import net.openhft.lang.io.Bytes; +import net.openhft.sg.Stage; +import net.openhft.sg.StageRef; +import net.openhft.sg.Staged; + + +@Staged +public abstract class ReplicatedInput + implements RemoteOperationContext, MapRemoteQueryContext { + + @StageRef ReplicatedChronicleMapHolder mh; + @StageRef ReplicationUpdate ru; + @StageRef LogHolder lh; + @StageRef ReplicatedInputKeyBytesData replicatedInputKeyBytesValue; + @StageRef ReplicatedInputValueBytesData replicatedInputValueBytesValue; + @StageRef ReplicatedMapQuery q; + @StageRef SegmentStages s; + @StageRef ReplicatedMapEntryStages e; + @StageRef DummyValueZeroData dummyValue; + + @Override + public Data dummyZeroValue() { + return dummyValue; + } + + public Bytes replicatedInputBytes = null; + public final JavaLangBytesReusableBytesStore replicatedInputStore = + new JavaLangBytesReusableBytesStore(); + + public void initReplicatedInputBytes(Bytes replicatedInputBytes) { + this.replicatedInputBytes = replicatedInputBytes; + replicatedInputStore.setBytes(replicatedInputBytes); + } + + @Stage("ReplicationInput") public long riKeySize = -1; + @Stage("ReplicationInput") public long riValueSize; + + @Stage("ReplicationInput") public long riKeyOffset; + @Stage("ReplicationInput") public long riValueOffset; + + @Stage("ReplicationInput") public long riTimestamp; + @Stage("ReplicationInput") public byte riId; + @Stage("ReplicationInput") public boolean isDeleted; + + + public void initReplicationInput(Bytes replicatedInputBytes) { + initReplicatedInputBytes(replicatedInputBytes); + riKeySize = mh.m().keySizeMarshaller.readSize(replicatedInputBytes); + riValueSize = mh.m().valueSizeMarshaller.readSize(replicatedInputBytes); + + riTimestamp = replicatedInputBytes.readStopBit(); + riId = replicatedInputBytes.readByte(); + ru.initReplicationUpdate(riTimestamp, riId); + + isDeleted = replicatedInputBytes.readBoolean(); + + riKeyOffset = replicatedInputBytes.position(); + riValueOffset = riKeyOffset + riKeySize; + } + + public void processReplicatedEvent() { + if (riId == mh.m().identifier()) { + // this may occur when working with UDP, as we may receive our own data + return; + } + + q.initInputKey(replicatedInputKeyBytesValue); + + boolean debugEnabled = lh.LOG.isDebugEnabled(); + + s.innerUpdateLock.lock(); + if (isDeleted) { + if (debugEnabled) { + lh.LOG.debug("READING FROM SOURCE - into local-id={}, remote={}, remove(key={})", + mh.m().identifier(), riId, q.inputKey); + } + mh.m().remoteOperations.remove(this); + mh.m().setLastModificationTime(riId, riTimestamp); + return; + } + + String message = null; + if (debugEnabled) { + message = String.format( + "READING FROM SOURCE - into local-id=%d, remote-id=%d, put(key=%s,", + mh.m().identifier(), riId, q.inputKey); + } + + + mh.m().remoteOperations.put(this, replicatedInputValueBytesValue); + mh.m().setLastModificationTime(riId, riTimestamp); + + if (debugEnabled) { + lh.LOG.debug(message + "value=" + replicatedInputValueBytesValue + ")"); + } + } +} diff --git a/src/main/java/net/openhft/chronicle/map/impl/stage/iter/DeprecatedMapKeyContextOnIteration.java b/src/main/java/net/openhft/chronicle/map/impl/stage/iter/DeprecatedMapKeyContextOnIteration.java new file mode 100644 index 000000000..8fc57cf99 --- /dev/null +++ b/src/main/java/net/openhft/chronicle/map/impl/stage/iter/DeprecatedMapKeyContextOnIteration.java @@ -0,0 +1,128 @@ +package net.openhft.chronicle.map.impl.stage.iter; + +import net.openhft.chronicle.hash.Data; +import net.openhft.chronicle.hash.impl.stage.entry.SegmentStages; +import net.openhft.chronicle.hash.impl.stage.hash.CheckOnEachPublicOperation; +import net.openhft.chronicle.hash.locks.InterProcessLock; +import net.openhft.chronicle.map.MapKeyContext; +import net.openhft.chronicle.map.impl.stage.entry.MapEntryStages; +import net.openhft.chronicle.map.impl.stage.map.MapEntryOperationsDelegation; +import net.openhft.lang.io.Bytes; +import net.openhft.sg.StageRef; +import net.openhft.sg.Staged; +import org.jetbrains.annotations.NotNull; + +@Staged +public class DeprecatedMapKeyContextOnIteration implements MapKeyContext { + + @StageRef CheckOnEachPublicOperation checkOnEachPublicOperation; + @StageRef SegmentStages s; + @StageRef MapSegmentIteration it; + @StageRef MapEntryOperationsDelegation ops; + @StageRef MapEntryStages e; + + @Override + public long valueOffset() { + checkOnEachPublicOperation.checkOnEachPublicOperation(); + return e.valueOffset; + } + + @Override + public long valueSize() { + checkOnEachPublicOperation.checkOnEachPublicOperation(); + return e.valueSize; + } + + @Override + public boolean valueEqualTo(V value) { + checkOnEachPublicOperation.checkOnEachPublicOperation(); + return Data.bytesEquivalent(e.entryValue, it.context().wrapValueAsValue(value)); + } + + @Override + public V get() { + checkOnEachPublicOperation.checkOnEachPublicOperation(); + return it.value().get(); + } + + @Override + public V getUsing(V usingValue) { + checkOnEachPublicOperation.checkOnEachPublicOperation(); + return it.value().getUsing(usingValue); + } + + @Override + public boolean put(V newValue) { + checkOnEachPublicOperation.checkOnEachPublicOperation(); + ops.replaceValue(it, it.context().wrapValueAsValue(newValue)); + return true; + } + + @NotNull + @Override + public K key() { + checkOnEachPublicOperation.checkOnEachPublicOperation(); + return it.key().get(); + } + + @NotNull + @Override + public Bytes entry() { + checkOnEachPublicOperation.checkOnEachPublicOperation(); + return e.entryBytes; + } + + @Override + public long keyOffset() { + checkOnEachPublicOperation.checkOnEachPublicOperation(); + return e.keyOffset; + } + + @Override + public long keySize() { + checkOnEachPublicOperation.checkOnEachPublicOperation(); + return e.keySize; + } + + @Override + public boolean containsKey() { + checkOnEachPublicOperation.checkOnEachPublicOperation(); + return true; + } + + @Override + public boolean remove() { + checkOnEachPublicOperation.checkOnEachPublicOperation(); + ops.remove(it); + return true; + } + + @Override + public void close() { + throw new UnsupportedOperationException("close() is not supported during iteration"); + } + + @NotNull + @Override + public InterProcessLock readLock() { + throw unsupportedLocks(); + } + + @NotNull + @Override + public InterProcessLock updateLock() { + throw unsupportedLocks(); + } + + @NotNull + @Override + public InterProcessLock writeLock() { + throw unsupportedLocks(); + } + + @NotNull + private UnsupportedOperationException unsupportedLocks() { + return new UnsupportedOperationException( + "Lock operations are not supported (and not needed!) during iteration"); + } +} diff --git a/src/main/java/net/openhft/chronicle/map/impl/stage/iter/IterationCheckOnEachPublicOperation.java b/src/main/java/net/openhft/chronicle/map/impl/stage/iter/IterationCheckOnEachPublicOperation.java new file mode 100644 index 000000000..a994c6181 --- /dev/null +++ b/src/main/java/net/openhft/chronicle/map/impl/stage/iter/IterationCheckOnEachPublicOperation.java @@ -0,0 +1,35 @@ +/* + * Copyright 2015 Higher Frequency Trading + * + * http://www.higherfrequencytrading.com + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package net.openhft.chronicle.map.impl.stage.iter; + +import net.openhft.chronicle.hash.impl.stage.hash.CheckOnEachPublicOperation; +import net.openhft.sg.StageRef; +import net.openhft.sg.Staged; + +@Staged +public class IterationCheckOnEachPublicOperation extends CheckOnEachPublicOperation { + + @StageRef MapSegmentIteration iteration; + + @Override + public void checkOnEachPublicOperation() { + super.checkOnEachPublicOperation(); + iteration.checkEntryNotRemovedOnThisIteration(); + } +} diff --git a/src/main/java/net/openhft/chronicle/map/impl/stage/iter/MapSegmentIteration.java b/src/main/java/net/openhft/chronicle/map/impl/stage/iter/MapSegmentIteration.java new file mode 100644 index 000000000..6e1a5a30d --- /dev/null +++ b/src/main/java/net/openhft/chronicle/map/impl/stage/iter/MapSegmentIteration.java @@ -0,0 +1,55 @@ +/* + * Copyright 2015 Higher Frequency Trading + * + * http://www.higherfrequencytrading.com + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package net.openhft.chronicle.map.impl.stage.iter; + +import net.openhft.chronicle.hash.Data; +import net.openhft.chronicle.hash.impl.stage.iter.HashSegmentIteration; +import net.openhft.chronicle.map.MapContext; +import net.openhft.chronicle.map.MapEntry; +import net.openhft.chronicle.map.impl.IterationContextInterface; +import net.openhft.chronicle.map.impl.stage.entry.MapEntryStages; +import net.openhft.chronicle.map.impl.stage.map.WrappedValueInstanceValueHolder; +import net.openhft.sg.StageRef; +import net.openhft.sg.Staged; +import org.jetbrains.annotations.NotNull; + +@Staged +public abstract class MapSegmentIteration extends HashSegmentIteration> + implements MapEntry, IterationContextInterface { + + @StageRef MapEntryStages entry; + @StageRef public DeprecatedMapKeyContextOnIteration deprecatedMapKeyContextOnIteration; + @StageRef WrappedValueInstanceValueHolder wrappedValueInstanceValueHolder; + + @Override + public void doReplaceValue(Data newValue) { + checkOnEachPublicOperation.checkOnEachPublicOperation(); + try { + entry.innerDefaultReplaceValue(newValue); + } finally { + s.innerWriteLock.unlock(); + } + } + + @NotNull + @Override + public MapContext context() { + return wrappedValueInstanceValueHolder; + } +} diff --git a/src/main/java/net/openhft/chronicle/map/impl/stage/iter/ReplicatedMapSegmentIteration.java b/src/main/java/net/openhft/chronicle/map/impl/stage/iter/ReplicatedMapSegmentIteration.java new file mode 100644 index 000000000..e8e2ac834 --- /dev/null +++ b/src/main/java/net/openhft/chronicle/map/impl/stage/iter/ReplicatedMapSegmentIteration.java @@ -0,0 +1,83 @@ +package net.openhft.chronicle.map.impl.stage.iter; + +import net.openhft.chronicle.hash.Data; +import net.openhft.chronicle.hash.replication.ReplicableEntry; +import net.openhft.chronicle.map.impl.ReplicatedIterationContextInterface; +import net.openhft.chronicle.map.impl.stage.data.DummyValueZeroData; +import net.openhft.chronicle.map.impl.stage.entry.ReplicatedMapEntryStages; +import net.openhft.chronicle.map.impl.stage.replication.ReplicationUpdate; +import net.openhft.sg.StageRef; +import net.openhft.sg.Staged; + +import java.util.function.Consumer; + +@Staged +public abstract class ReplicatedMapSegmentIteration extends MapSegmentIteration + implements ReplicatedIterationContextInterface, ReplicableEntry { + + @StageRef ReplicatedMapEntryStages e; + @StageRef ReplicationUpdate ru; + @StageRef DummyValueZeroData dummyValue; + + @Override + public boolean entryIsPresent() { + return !e.entryDeleted(); + } + + @Override + public void doReplaceValue(Data newValue) { + checkOnEachPublicOperation.checkOnEachPublicOperation(); + try { + entry.innerDefaultReplaceValue(newValue); + ru.updateChange(); + e.updatedReplicationStateOnPresentEntry(); + } finally { + s.innerWriteLock.unlock(); + } + } + + @Override + public void forEachReplicableEntry(Consumer action) { + s.innerUpdateLock.lock(); + try { + long entries = s.entries(); + if (entries == 0) + return; + long startPos = 0L; + while (!hashLookup.empty(hashLookup.readEntry(startPos))) { + startPos = hashLookup.step(startPos); + } + hlp.initHashLookupPos(startPos); + do { + hlp.setHashLookupPos(hashLookup.step(hlp.hashLookupPos)); + long entry = hashLookup.readEntry(hlp.hashLookupPos); + if (!hashLookup.empty(entry)) { + e.readExistingEntry(hashLookup.value(entry)); + action.accept(this); + if (--entries == 0) + break; + } + } while (hlp.hashLookupPos != startPos); + } finally { + s.innerReadLock.unlock(); + } + } + + + + @Override + public void doRemove() { + checkOnEachPublicOperation.checkOnEachPublicOperation(); + initEntryRemovedOnThisIteration(true); + try { + if (e.valueSize > dummyValue.size()) + e.innerDefaultReplaceValue(dummyValue); + e.updatedReplicationStateOnPresentEntry(); + e.writeEntryDeleted(); + ru.updateChange(); + s.deleted(s.deleted() + 1); + } finally { + s.innerWriteLock.unlock(); + } + } +} diff --git a/src/main/java/net/openhft/chronicle/map/impl/stage/map/MapEntryOperationsDelegation.java b/src/main/java/net/openhft/chronicle/map/impl/stage/map/MapEntryOperationsDelegation.java new file mode 100644 index 000000000..aa046186a --- /dev/null +++ b/src/main/java/net/openhft/chronicle/map/impl/stage/map/MapEntryOperationsDelegation.java @@ -0,0 +1,43 @@ +package net.openhft.chronicle.map.impl.stage.map; + +import net.openhft.chronicle.hash.Data; +import net.openhft.chronicle.hash.impl.stage.hash.CheckOnEachPublicOperation; +import net.openhft.chronicle.map.MapAbsentEntry; +import net.openhft.chronicle.map.MapContext; +import net.openhft.chronicle.map.MapEntry; +import net.openhft.chronicle.map.impl.VanillaChronicleMapHolder; +import net.openhft.sg.StageRef; +import net.openhft.sg.Staged; +import org.jetbrains.annotations.NotNull; + +@Staged +public abstract class MapEntryOperationsDelegation implements MapContext { + + @StageRef CheckOnEachPublicOperation checkOnEachPublicOperation; + @StageRef VanillaChronicleMapHolder mh; + + + @Override + public R replaceValue(@NotNull MapEntry entry, Data newValue) { + checkOnEachPublicOperation.checkOnEachPublicOperation(); + return mh.m().entryOperations.replaceValue(entry, newValue); + } + + @Override + public R remove(@NotNull MapEntry entry) { + checkOnEachPublicOperation.checkOnEachPublicOperation(); + return mh.m().entryOperations.remove(entry); + } + + @Override + public Data defaultValue(@NotNull MapAbsentEntry absentEntry) { + checkOnEachPublicOperation.checkOnEachPublicOperation(); + return mh.m().entryOperations.defaultValue(absentEntry); + } + + @Override + public R insert(@NotNull MapAbsentEntry absentEntry, Data value) { + checkOnEachPublicOperation.checkOnEachPublicOperation(); + return mh.m().entryOperations.insert(absentEntry, value); + } +} diff --git a/src/main/java/net/openhft/chronicle/map/impl/stage/map/ReplicatedChronicleMapHolderImpl.java b/src/main/java/net/openhft/chronicle/map/impl/stage/map/ReplicatedChronicleMapHolderImpl.java new file mode 100644 index 000000000..acd903c04 --- /dev/null +++ b/src/main/java/net/openhft/chronicle/map/impl/stage/map/ReplicatedChronicleMapHolderImpl.java @@ -0,0 +1,62 @@ +/* + * Copyright 2015 Higher Frequency Trading + * + * http://www.higherfrequencytrading.com + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package net.openhft.chronicle.map.impl.stage.map; + +import net.openhft.chronicle.hash.impl.stage.hash.Chaining; +import net.openhft.chronicle.hash.serialization.internal.MetaBytesInterop; +import net.openhft.chronicle.map.ChronicleMap; +import net.openhft.chronicle.map.ReplicatedChronicleMap; +import net.openhft.chronicle.map.impl.ReplicatedChronicleMapHolder; +import net.openhft.sg.Staged; + +@Staged +public class ReplicatedChronicleMapHolderImpl< + K, KI, MKI extends MetaBytesInterop, + V, VI, MVI extends MetaBytesInterop, R + > + extends Chaining + implements ReplicatedChronicleMapHolder { + + private final ReplicatedChronicleMap m; + + public ReplicatedChronicleMapHolderImpl(ReplicatedChronicleMap m) { + super(); + this.m = m; + } + + public ReplicatedChronicleMapHolderImpl(ReplicatedChronicleMapHolderImpl c) { + super(c); + this.m = (ReplicatedChronicleMap) c.m; + } + + @Override + public Chaining createChaining() { + return new ReplicatedChronicleMapHolderImpl(this); + } + + @Override + public ReplicatedChronicleMap m() { + return m; + } + + @Override + public ChronicleMap map() { + return m(); + } +} diff --git a/src/main/java/net/openhft/chronicle/map/impl/stage/map/ValueBytesInterop.java b/src/main/java/net/openhft/chronicle/map/impl/stage/map/ValueBytesInterop.java new file mode 100644 index 000000000..2cf33d87c --- /dev/null +++ b/src/main/java/net/openhft/chronicle/map/impl/stage/map/ValueBytesInterop.java @@ -0,0 +1,42 @@ +/* + * Copyright 2015 Higher Frequency Trading + * + * http://www.higherfrequencytrading.com + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package net.openhft.chronicle.map.impl.stage.map; + +import net.openhft.chronicle.hash.impl.stage.hash.ThreadLocalCopiesHolder; +import net.openhft.chronicle.hash.serialization.BytesReader; +import net.openhft.chronicle.hash.serialization.internal.MetaBytesInterop; +import net.openhft.chronicle.map.impl.VanillaChronicleMapHolder; +import net.openhft.sg.StageRef; +import net.openhft.sg.Staged; + +@Staged +public class ValueBytesInterop> { + @StageRef VanillaChronicleMapHolder mh; + @StageRef ThreadLocalCopiesHolder ch; + + public final BytesReader valueReader = + mh.m().valueReaderProvider.get(ch.copies, mh.m().originalValueReader); + public final VI valueInterop = + mh.m().valueInteropProvider.get(ch.copies, mh.m().originalValueInterop); + + public MVI valueMetaInterop(V value) { + return mh.m().metaValueInteropProvider.get( + ch.copies, mh.m().originalMetaValueInterop, valueInterop, value); + } +} diff --git a/src/main/java/net/openhft/chronicle/map/impl/stage/map/VanillaChronicleMapHolderImpl.java b/src/main/java/net/openhft/chronicle/map/impl/stage/map/VanillaChronicleMapHolderImpl.java new file mode 100644 index 000000000..3e6de092f --- /dev/null +++ b/src/main/java/net/openhft/chronicle/map/impl/stage/map/VanillaChronicleMapHolderImpl.java @@ -0,0 +1,62 @@ +/* + * Copyright 2015 Higher Frequency Trading + * + * http://www.higherfrequencytrading.com + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package net.openhft.chronicle.map.impl.stage.map; + +import net.openhft.chronicle.hash.impl.stage.hash.Chaining; +import net.openhft.chronicle.hash.serialization.internal.MetaBytesInterop; +import net.openhft.chronicle.map.ChronicleMap; +import net.openhft.chronicle.map.VanillaChronicleMap; +import net.openhft.chronicle.map.impl.VanillaChronicleMapHolder; +import net.openhft.sg.Staged; + +@Staged +public class VanillaChronicleMapHolderImpl< + K, KI, MKI extends MetaBytesInterop, + V, VI, MVI extends MetaBytesInterop, R + > + extends Chaining + implements VanillaChronicleMapHolder { + + private final VanillaChronicleMap m; + + public VanillaChronicleMapHolderImpl(VanillaChronicleMap m) { + super(); + this.m = m; + } + + public VanillaChronicleMapHolderImpl(VanillaChronicleMapHolderImpl c) { + super(c); + this.m = (VanillaChronicleMap) c.m; + } + + @Override + public Chaining createChaining() { + return new VanillaChronicleMapHolderImpl(this); + } + + @Override + public VanillaChronicleMap m() { + return m; + } + + @Override + public ChronicleMap map() { + return m(); + } +} diff --git a/src/main/java/net/openhft/chronicle/map/impl/stage/map/WrappedValueInstanceValueHolder.java b/src/main/java/net/openhft/chronicle/map/impl/stage/map/WrappedValueInstanceValueHolder.java new file mode 100644 index 000000000..7b3175499 --- /dev/null +++ b/src/main/java/net/openhft/chronicle/map/impl/stage/map/WrappedValueInstanceValueHolder.java @@ -0,0 +1,25 @@ +package net.openhft.chronicle.map.impl.stage.map; + +import net.openhft.chronicle.hash.Data; +import net.openhft.chronicle.hash.impl.stage.hash.CheckOnEachPublicOperation; +import net.openhft.chronicle.map.MapContext; +import net.openhft.chronicle.map.impl.stage.data.instance.WrappedValueInstanceData; +import net.openhft.sg.StageRef; +import net.openhft.sg.Staged; + +@Staged +public abstract class WrappedValueInstanceValueHolder implements MapContext { + + @StageRef CheckOnEachPublicOperation checkOnEachPublicOperation; + @StageRef WrappedValueInstanceData wrappedValueInstanceValue; + + + @Override + public Data wrapValueAsValue(V value) { + checkOnEachPublicOperation.checkOnEachPublicOperation(); + WrappedValueInstanceData wrapped = this.wrappedValueInstanceValue; + wrapped = wrapped.getUnusedWrappedValue(); + wrapped.initValue(value); + return wrapped; + } +} diff --git a/src/main/java/net/openhft/chronicle/map/impl/stage/query/DeprecatedMapAcquireContextOnQuery.java b/src/main/java/net/openhft/chronicle/map/impl/stage/query/DeprecatedMapAcquireContextOnQuery.java new file mode 100644 index 000000000..7d3860a04 --- /dev/null +++ b/src/main/java/net/openhft/chronicle/map/impl/stage/query/DeprecatedMapAcquireContextOnQuery.java @@ -0,0 +1,152 @@ +/* + * Copyright 2015 Higher Frequency Trading + * + * http://www.higherfrequencytrading.com + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package net.openhft.chronicle.map.impl.stage.query; + +import net.openhft.chronicle.hash.Data; +import net.openhft.chronicle.hash.impl.stage.hash.CheckOnEachPublicOperation; +import net.openhft.chronicle.hash.locks.InterProcessLock; +import net.openhft.chronicle.map.MapEntry; +import net.openhft.chronicle.map.MapKeyContext; +import net.openhft.chronicle.map.impl.stage.entry.MapEntryStages; +import net.openhft.chronicle.map.impl.stage.ret.UsingReturnValue; +import net.openhft.lang.io.Bytes; +import net.openhft.sg.StageRef; +import net.openhft.sg.Staged; +import org.jetbrains.annotations.NotNull; + +@Staged +public class DeprecatedMapAcquireContextOnQuery implements MapKeyContext { + + @StageRef CheckOnEachPublicOperation checkOnEachPublicOperation; + @StageRef MapEntryStages e; + @StageRef MapQuery q; + @StageRef UsingReturnValue usingReturn; + + @Override + public long valueOffset() { + checkOnEachPublicOperation.checkOnEachPublicOperation(); + return e.valueOffset; + } + + @Override + public long valueSize() { + checkOnEachPublicOperation.checkOnEachPublicOperation(); + return e.valueSize; + } + + @Override + public boolean valueEqualTo(V value) { + checkOnEachPublicOperation.checkOnEachPublicOperation(); + return Data.bytesEquivalent(e.entryValue, q.wrapValueAsValue(value)); + } + + @Override + public V get() { + assert containsKey(); + return usingReturn.returnValue(); + } + + @Override + public V getUsing(V usingValue) { + return containsKey() ? q.value().getUsing(usingValue) : null; + } + + @Override + public boolean put(V newValue) { + checkOnEachPublicOperation.checkOnEachPublicOperation(); + updateLock().lock(); + MapEntry entry = q.entry(); + if (entry != null) { + q.replaceValue(entry, q.wrapValueAsValue(newValue)); + } else { + q.insert(q.absentEntry(), q.wrapValueAsValue(newValue)); + } + return true; + } + + @NotNull + @Override + public K key() { + checkOnEachPublicOperation.checkOnEachPublicOperation(); + return q.queriedKey().get(); + } + + @NotNull + @Override + public Bytes entry() { + checkOnEachPublicOperation.checkOnEachPublicOperation(); + return e.entryBytes; + } + + @Override + public long keyOffset() { + checkOnEachPublicOperation.checkOnEachPublicOperation(); + return e.keyOffset; + } + + @Override + public long keySize() { + checkOnEachPublicOperation.checkOnEachPublicOperation(); + return e.keySize; + } + + @Override + public boolean containsKey() { + checkOnEachPublicOperation.checkOnEachPublicOperation(); + return q.entry() != null; + } + + @Override + public boolean remove() { + checkOnEachPublicOperation.checkOnEachPublicOperation(); + updateLock().lock(); + MapEntry entry = q.entry(); + if (entry != null) { + q.remove(entry); + return true; + } else { + return false; + } + } + + @Override + public void close() { + checkOnEachPublicOperation.checkOnEachPublicOperation(); + put(usingReturn.returnValue()); + q.close(); + } + + @NotNull + @Override + public InterProcessLock readLock() { + return q.readLock(); + } + + @NotNull + @Override + public InterProcessLock updateLock() { + return q.updateLock(); + } + + @NotNull + @Override + public InterProcessLock writeLock() { + return q.writeLock(); + } +} diff --git a/src/main/java/net/openhft/chronicle/map/impl/stage/query/DeprecatedMapKeyContextOnQuery.java b/src/main/java/net/openhft/chronicle/map/impl/stage/query/DeprecatedMapKeyContextOnQuery.java new file mode 100644 index 000000000..cead32685 --- /dev/null +++ b/src/main/java/net/openhft/chronicle/map/impl/stage/query/DeprecatedMapKeyContextOnQuery.java @@ -0,0 +1,148 @@ +/* + * Copyright 2015 Higher Frequency Trading + * + * http://www.higherfrequencytrading.com + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package net.openhft.chronicle.map.impl.stage.query; + +import net.openhft.chronicle.hash.Data; +import net.openhft.chronicle.hash.impl.stage.hash.CheckOnEachPublicOperation; +import net.openhft.chronicle.hash.locks.InterProcessLock; +import net.openhft.chronicle.map.MapEntry; +import net.openhft.chronicle.map.MapKeyContext; +import net.openhft.chronicle.map.impl.stage.entry.MapEntryStages; +import net.openhft.lang.io.Bytes; +import net.openhft.sg.StageRef; +import net.openhft.sg.Staged; +import org.jetbrains.annotations.NotNull; + +@Staged +public class DeprecatedMapKeyContextOnQuery implements MapKeyContext { + + @StageRef CheckOnEachPublicOperation checkOnEachPublicOperation; + @StageRef MapEntryStages e; + @StageRef MapQuery q; + + @Override + public long valueOffset() { + checkOnEachPublicOperation.checkOnEachPublicOperation(); + return e.valueOffset; + } + + @Override + public long valueSize() { + checkOnEachPublicOperation.checkOnEachPublicOperation(); + return e.valueSize; + } + + @Override + public boolean valueEqualTo(V value) { + checkOnEachPublicOperation.checkOnEachPublicOperation(); + return Data.bytesEquivalent(e.entryValue, q.wrapValueAsValue(value)); + } + + @Override + public V get() { + return containsKey() ? q.value().get() : null; + } + + @Override + public V getUsing(V usingValue) { + return containsKey() ? q.value().getUsing(usingValue) : null; + } + + @Override + public boolean put(V newValue) { + checkOnEachPublicOperation.checkOnEachPublicOperation(); + updateLock().lock(); + MapEntry entry = q.entry(); + if (entry != null) { + q.replaceValue(entry, q.wrapValueAsValue(newValue)); + } else { + q.insert(q.absentEntry(), q.wrapValueAsValue(newValue)); + } + return true; + } + + @NotNull + @Override + public K key() { + checkOnEachPublicOperation.checkOnEachPublicOperation(); + return q.queriedKey().get(); + } + + @NotNull + @Override + public Bytes entry() { + checkOnEachPublicOperation.checkOnEachPublicOperation(); + return e.entryBytes; + } + + @Override + public long keyOffset() { + checkOnEachPublicOperation.checkOnEachPublicOperation(); + return e.keyOffset; + } + + @Override + public long keySize() { + checkOnEachPublicOperation.checkOnEachPublicOperation(); + return e.keySize; + } + + @Override + public boolean containsKey() { + checkOnEachPublicOperation.checkOnEachPublicOperation(); + return q.entry() != null; + } + + @Override + public boolean remove() { + checkOnEachPublicOperation.checkOnEachPublicOperation(); + updateLock().lock(); + MapEntry entry = q.entry(); + if (entry != null) { + q.remove(entry); + return true; + } else { + return false; + } + } + + @Override + public void close() { + checkOnEachPublicOperation.checkOnEachPublicOperation(); + q.close(); + } + + @NotNull + @Override + public InterProcessLock readLock() { + return q.readLock(); + } + + @NotNull + @Override + public InterProcessLock updateLock() { + return q.updateLock(); + } + + @NotNull + @Override + public InterProcessLock writeLock() { + return q.writeLock(); + } +} diff --git a/src/main/java/net/openhft/chronicle/map/impl/stage/query/MapAbsent.java b/src/main/java/net/openhft/chronicle/map/impl/stage/query/MapAbsent.java new file mode 100644 index 000000000..ca4f56951 --- /dev/null +++ b/src/main/java/net/openhft/chronicle/map/impl/stage/query/MapAbsent.java @@ -0,0 +1,74 @@ +package net.openhft.chronicle.map.impl.stage.query; + +import net.openhft.chronicle.hash.Data; +import net.openhft.chronicle.hash.impl.stage.entry.SegmentStages; +import net.openhft.chronicle.hash.impl.stage.hash.CheckOnEachPublicOperation; +import net.openhft.chronicle.hash.impl.stage.query.HashLookupSearch; +import net.openhft.chronicle.map.MapAbsentEntry; +import net.openhft.chronicle.map.MapContext; +import net.openhft.chronicle.map.impl.VanillaChronicleMapHolder; +import net.openhft.chronicle.map.impl.stage.entry.MapEntryStages; +import net.openhft.sg.StageRef; +import net.openhft.sg.Staged; +import org.jetbrains.annotations.NotNull; + +import static net.openhft.chronicle.hash.impl.stage.query.HashQuery.SearchState.PRESENT; + +@Staged +public class MapAbsent implements MapAbsentEntry { + + @StageRef MapQuery q; + @StageRef MapEntryStages e; + @StageRef public HashLookupSearch hashLookupSearch; + @StageRef public CheckOnEachPublicOperation checkOnEachPublicOperation; + @StageRef public SegmentStages s; + @StageRef VanillaChronicleMapHolder mh; + @StageRef public DeprecatedMapKeyContextOnQuery deprecatedMapKeyContext; + + void putEntry(Data value) { + assert q.searchStateAbsent(); + long entrySize = e.entrySize(q.inputKey.size(), value.size()); + q.allocatedChunks.initEntryAndKey(entrySize); + e.initValue(value); + e.freeExtraAllocatedChunks(); + hashLookupSearch.putNewVolatile(e.pos); + } + + @NotNull + @Override + public MapContext context() { + checkOnEachPublicOperation.checkOnEachPublicOperation(); + return q; + } + + @NotNull + @Override + public Data absentKey() { + checkOnEachPublicOperation.checkOnEachPublicOperation(); + return q.inputKey; + } + + @Override + public void doInsert(Data value) { + q.putPrefix(); + if (!q.searchStatePresent()) { + if (q.searchStateDeleted()) { + e.putValueDeletedEntry(value); + } else { + putEntry(value); + } + s.incrementModCount(); + q.setSearchState(PRESENT); + } else { + throw new IllegalStateException( + "Entry is present in the map when doInsert() is called"); + } + } + + @NotNull + @Override + public Data defaultValue() { + checkOnEachPublicOperation.checkOnEachPublicOperation(); + return q.wrapValueAsValue(mh.m().defaultValue(deprecatedMapKeyContext)); + } +} diff --git a/src/main/java/net/openhft/chronicle/map/impl/stage/query/MapAbsentHolder.java b/src/main/java/net/openhft/chronicle/map/impl/stage/query/MapAbsentHolder.java new file mode 100644 index 000000000..32d254ac4 --- /dev/null +++ b/src/main/java/net/openhft/chronicle/map/impl/stage/query/MapAbsentHolder.java @@ -0,0 +1,17 @@ +package net.openhft.chronicle.map.impl.stage.query; + +import net.openhft.chronicle.map.MapAbsentEntry; +import net.openhft.chronicle.map.impl.MapAbsentEntryHolder; +import net.openhft.sg.StageRef; +import net.openhft.sg.Staged; + +@Staged +public class MapAbsentHolder implements MapAbsentEntryHolder { + + @StageRef MapAbsent ab; + + @Override + public MapAbsentEntry absent() { + return ab; + } +} diff --git a/src/main/java/net/openhft/chronicle/map/impl/stage/query/MapQuery.java b/src/main/java/net/openhft/chronicle/map/impl/stage/query/MapQuery.java new file mode 100644 index 000000000..5c301ba06 --- /dev/null +++ b/src/main/java/net/openhft/chronicle/map/impl/stage/query/MapQuery.java @@ -0,0 +1,108 @@ +/* + * Copyright 2015 Higher Frequency Trading + * + * http://www.higherfrequencytrading.com + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package net.openhft.chronicle.map.impl.stage.query; + +import net.openhft.chronicle.hash.Data; +import net.openhft.chronicle.hash.impl.stage.query.HashQuery; +import net.openhft.chronicle.hash.impl.stage.query.SearchAllocatedChunks; +import net.openhft.chronicle.map.ExternalMapQueryContext; +import net.openhft.chronicle.map.MapAbsentEntry; +import net.openhft.chronicle.map.MapContext; +import net.openhft.chronicle.map.MapEntry; +import net.openhft.chronicle.map.impl.MapAbsentEntryHolder; +import net.openhft.chronicle.map.impl.QueryContextInterface; +import net.openhft.chronicle.map.impl.VanillaChronicleMapHolder; +import net.openhft.chronicle.map.impl.stage.data.bytes.InputFirstValueBytesData; +import net.openhft.chronicle.map.impl.stage.data.bytes.InputSecondValueBytesData; +import net.openhft.chronicle.map.impl.stage.data.instance.InputValueInstanceData; +import net.openhft.chronicle.map.impl.stage.entry.MapEntryStages; +import net.openhft.chronicle.map.impl.stage.ret.DefaultReturnValue; +import net.openhft.chronicle.map.impl.stage.ret.UsingReturnValue; +import net.openhft.sg.StageRef; +import net.openhft.sg.Staged; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import static net.openhft.chronicle.hash.impl.stage.query.HashQuery.SearchState.PRESENT; + +@Staged +public abstract class MapQuery extends HashQuery + implements MapEntry, ExternalMapQueryContext, + QueryContextInterface { + + @StageRef VanillaChronicleMapHolder mh; + @StageRef MapEntryStages e; + @StageRef SearchAllocatedChunks allocatedChunks; + @StageRef public DeprecatedMapKeyContextOnQuery deprecatedMapKeyContext; + @StageRef public DeprecatedMapAcquireContextOnQuery deprecatedMapAcquireContext; + + @StageRef public InputValueInstanceData inputValueInstanceValue; + + @StageRef public InputFirstValueBytesData inputFirstValueBytesValue; + @StageRef public InputSecondValueBytesData inputSecondValueBytesValue; + + @StageRef public DefaultReturnValue defaultReturnValue; + @StageRef public UsingReturnValue usingReturnValue; + + @StageRef public MapAbsentEntryHolder absent; + + @Override + public MapEntry entry() { + checkOnEachPublicOperation.checkOnEachPublicOperation(); + return entryPresent() ? this : null; + } + + @Nullable + @Override + public MapAbsentEntry absentEntry() { + checkOnEachPublicOperation.checkOnEachPublicOperation(); + return entryPresent() ? null : absent.absent(); + } + + protected void putPrefix() { + checkOnEachPublicOperation.checkOnEachPublicOperation(); + boolean underUpdatedLockIsHeld = !s.innerUpdateLock.isHeldByCurrentThread(); + if (underUpdatedLockIsHeld) + s.innerUpdateLock.lock(); + boolean searchResultsNotTrusted = underUpdatedLockIsHeld || + s.concurrentSameThreadContexts; + if (hlp.hashLookupPosInit() && searchStateAbsent() && searchResultsNotTrusted) + hlp.closeHashLookupPos(); + } + + @Override + public void doReplaceValue(Data newValue) { + putPrefix(); + if (searchStatePresent()) { + e.innerDefaultReplaceValue(newValue); + s.incrementModCount(); + setSearchState(PRESENT); + } else { + throw new IllegalStateException( + "Entry is absent in the map when doReplaceValue() is called"); + } + } + + @NotNull + @Override + public MapContext context() { + checkOnEachPublicOperation.checkOnEachPublicOperation(); + return this; + } +} diff --git a/src/main/java/net/openhft/chronicle/map/impl/stage/query/QueryCheckOnEachPublicOperation.java b/src/main/java/net/openhft/chronicle/map/impl/stage/query/QueryCheckOnEachPublicOperation.java new file mode 100644 index 000000000..49a6654c9 --- /dev/null +++ b/src/main/java/net/openhft/chronicle/map/impl/stage/query/QueryCheckOnEachPublicOperation.java @@ -0,0 +1,36 @@ +/* + * Copyright 2015 Higher Frequency Trading + * + * http://www.higherfrequencytrading.com + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package net.openhft.chronicle.map.impl.stage.query; + +import net.openhft.chronicle.hash.impl.stage.hash.CheckOnEachPublicOperation; +import net.openhft.chronicle.hash.impl.stage.query.HashQuery; +import net.openhft.sg.StageRef; +import net.openhft.sg.Staged; + +@Staged +public class QueryCheckOnEachPublicOperation extends CheckOnEachPublicOperation { + + @StageRef HashQuery q; + + @Override + public void checkOnEachPublicOperation() { + super.checkOnEachPublicOperation(); + q.dropSearchIfNestedContextsAndPresentHashLookupSlotCheckFailed(); + } +} diff --git a/src/main/java/net/openhft/chronicle/map/impl/stage/query/ReplicatedMapAbsent.java b/src/main/java/net/openhft/chronicle/map/impl/stage/query/ReplicatedMapAbsent.java new file mode 100644 index 000000000..ae9d7b712 --- /dev/null +++ b/src/main/java/net/openhft/chronicle/map/impl/stage/query/ReplicatedMapAbsent.java @@ -0,0 +1,36 @@ +package net.openhft.chronicle.map.impl.stage.query; + +import net.openhft.chronicle.hash.Data; +import net.openhft.chronicle.hash.impl.stage.query.HashQuery; +import net.openhft.chronicle.map.impl.stage.entry.ReplicatedMapEntryStages; +import net.openhft.chronicle.map.impl.stage.replication.ReplicationUpdate; +import net.openhft.sg.StageRef; +import net.openhft.sg.Staged; + +@Staged +public class ReplicatedMapAbsent extends MapAbsent { + + @StageRef MapQuery q; + @StageRef ReplicatedMapEntryStages e; + @StageRef ReplicationUpdate ru; + + @Override + public void doInsert(Data value) { + q.putPrefix(); + if (!q.entryPresent()) { + if (!q.searchStatePresent()) { + putEntry(value); + q.setSearchState(HashQuery.SearchState.PRESENT); + } else { + e.innerDefaultReplaceValue(value); + s.deleted(s.deleted() - 1); + } + s.incrementModCount(); + e.writeEntryPresent(); + ru.updateChange(); + e.updatedReplicationStateOnAbsentEntry(); + } else { + throw new IllegalStateException("Entry is absent in the map when doInsert() is called"); + } + } +} diff --git a/src/main/java/net/openhft/chronicle/map/impl/stage/query/ReplicatedMapAbsentDelegating.java b/src/main/java/net/openhft/chronicle/map/impl/stage/query/ReplicatedMapAbsentDelegating.java new file mode 100644 index 000000000..225d98e5f --- /dev/null +++ b/src/main/java/net/openhft/chronicle/map/impl/stage/query/ReplicatedMapAbsentDelegating.java @@ -0,0 +1,37 @@ +package net.openhft.chronicle.map.impl.stage.query; + +import net.openhft.chronicle.hash.Data; +import net.openhft.chronicle.map.MapAbsentEntry; +import net.openhft.chronicle.map.MapContext; +import net.openhft.sg.StageRef; +import net.openhft.sg.Staged; +import org.jetbrains.annotations.NotNull; + +@Staged +public class ReplicatedMapAbsentDelegating implements MapAbsentEntry { + + @StageRef ReplicatedMapAbsent delegate; + + @NotNull + @Override + public MapContext context() { + return delegate.context(); + } + + @Override + public void doInsert(Data value) { + delegate.doInsert(value); + } + + @NotNull + @Override + public Data defaultValue() { + return delegate.defaultValue(); + } + + @NotNull + @Override + public Data absentKey() { + return delegate.absentKey(); + } +} diff --git a/src/main/java/net/openhft/chronicle/map/impl/stage/query/ReplicatedMapAbsentHolder.java b/src/main/java/net/openhft/chronicle/map/impl/stage/query/ReplicatedMapAbsentHolder.java new file mode 100644 index 000000000..8a084bbb9 --- /dev/null +++ b/src/main/java/net/openhft/chronicle/map/impl/stage/query/ReplicatedMapAbsentHolder.java @@ -0,0 +1,17 @@ +package net.openhft.chronicle.map.impl.stage.query; + +import net.openhft.chronicle.map.MapAbsentEntry; +import net.openhft.chronicle.map.impl.MapAbsentEntryHolder; +import net.openhft.sg.StageRef; +import net.openhft.sg.Staged; + +@Staged +public class ReplicatedMapAbsentHolder implements MapAbsentEntryHolder { + + @StageRef ReplicatedMapAbsent ab; + + @Override + public MapAbsentEntry absent() { + return ab; + } +} diff --git a/src/main/java/net/openhft/chronicle/map/impl/stage/query/ReplicatedMapQuery.java b/src/main/java/net/openhft/chronicle/map/impl/stage/query/ReplicatedMapQuery.java new file mode 100644 index 000000000..4ad6a8d35 --- /dev/null +++ b/src/main/java/net/openhft/chronicle/map/impl/stage/query/ReplicatedMapQuery.java @@ -0,0 +1,94 @@ +/* + * Copyright 2015 Higher Frequency Trading + * + * http://www.higherfrequencytrading.com + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package net.openhft.chronicle.map.impl.stage.query; + +import net.openhft.chronicle.hash.Data; +import net.openhft.chronicle.map.MapAbsentEntry; +import net.openhft.chronicle.map.impl.stage.data.DummyValueZeroData; +import net.openhft.chronicle.map.impl.stage.entry.ReplicatedMapEntryStages; +import net.openhft.chronicle.map.impl.stage.replication.ReplicationUpdate; +import net.openhft.chronicle.map.impl.stage.ret.BytesReturnValue; +import net.openhft.chronicle.map.replication.MapRemoteQueryContext; +import net.openhft.chronicle.map.replication.MapReplicableEntry; +import net.openhft.sg.StageRef; +import net.openhft.sg.Staged; +import org.jetbrains.annotations.Nullable; + +@Staged +public abstract class ReplicatedMapQuery extends MapQuery + implements MapRemoteQueryContext { + + @StageRef ReplicatedMapEntryStages e; + @StageRef ReplicationUpdate ru; + + @StageRef BytesReturnValue bytesReturnValue; + + @StageRef ReplicatedMapAbsentDelegating absentDelegating; + + @Nullable + @Override + public MapAbsentEntry absentEntry() { + checkOnEachPublicOperation.checkOnEachPublicOperation(); + if (entryPresent()) { + return null; + } else { + if (!searchStatePresent()) { + return absentDelegating; + } else { + assert e.entryDeleted(); + return absent.absent(); + } + } + } + + @Override + public boolean entryPresent() { + return super.entryPresent() && !e.entryDeleted(); + } + + @StageRef DummyValueZeroData dummyValue; + + @Override + public MapReplicableEntry entry() { + return (MapReplicableEntry) super.entry(); + } + + @Override + public void doRemove() { + checkOnEachPublicOperation.checkOnEachPublicOperation(); + s.innerUpdateLock.lock(); + if (entryPresent()) { + if (e.valueSize > dummyValue.size()) + e.innerDefaultReplaceValue(dummyValue); + e.updatedReplicationStateOnPresentEntry(); + e.writeEntryDeleted(); + ru.updateChange(); + s.deleted(s.deleted() + 1); + } else { + throw new IllegalStateException("Entry is absent in the map when doRemove() is called"); + } + } + + @Override + public void doReplaceValue(Data newValue) { + super.doReplaceValue(newValue); + ru.updateChange(); + e.updatedReplicationStateOnPresentEntry(); + } +} diff --git a/src/main/java/net/openhft/chronicle/map/impl/stage/replication/ReplicationUpdate.java b/src/main/java/net/openhft/chronicle/map/impl/stage/replication/ReplicationUpdate.java new file mode 100644 index 000000000..8c596daac --- /dev/null +++ b/src/main/java/net/openhft/chronicle/map/impl/stage/replication/ReplicationUpdate.java @@ -0,0 +1,78 @@ +/* + * Copyright 2015 Higher Frequency Trading + * + * http://www.higherfrequencytrading.com + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package net.openhft.chronicle.map.impl.stage.replication; + +import net.openhft.chronicle.hash.impl.stage.entry.SegmentStages; +import net.openhft.chronicle.hash.impl.stage.hash.CheckOnEachPublicOperation; +import net.openhft.chronicle.hash.replication.RemoteOperationContext; +import net.openhft.chronicle.map.impl.ReplicatedChronicleMapHolder; +import net.openhft.chronicle.map.impl.stage.entry.ReplicatedMapEntryStages; +import net.openhft.sg.Stage; +import net.openhft.sg.StageRef; +import net.openhft.sg.Staged; + +@Staged +public abstract class ReplicationUpdate implements RemoteOperationContext { + @StageRef SegmentStages s; + @StageRef ReplicatedMapEntryStages e; + @StageRef ReplicatedChronicleMapHolder mh; + @StageRef CheckOnEachPublicOperation checkOnEachPublicOperation; + + @Stage("ReplicationUpdate") public long innerRemoteTimestamp; + @Stage("ReplicationUpdate") public byte innerRemoteIdentifier = (byte) 0; + + public abstract boolean replicationUpdateInit(); + + public void initReplicationUpdate(long timestamp, byte identifier) { + innerRemoteTimestamp = timestamp; + if (identifier == 0) + throw new IllegalStateException("identifier can't be 0"); + innerRemoteIdentifier = identifier; + } + + public void dropChange() { + mh.m().dropChange(s.segmentIndex, e.pos); + } + + public void moveChange(long oldPos, long newPos) { + mh.m().moveChange(s.segmentIndex, oldPos, newPos); + } + + public void updateChange() { + if (!replicationUpdateInit()) { + raiseChange(); + } + } + + public void raiseChange() { + mh.m().raiseChange(s.segmentIndex, e.pos); + } + + @Override + public long remoteTimestamp() { + checkOnEachPublicOperation.checkOnEachPublicOperation(); + return innerRemoteTimestamp; + } + + @Override + public byte remoteIdentifier() { + checkOnEachPublicOperation.checkOnEachPublicOperation(); + return innerRemoteIdentifier; + } +} diff --git a/src/main/java/net/openhft/chronicle/map/impl/stage/ret/BytesReturnValue.java b/src/main/java/net/openhft/chronicle/map/impl/stage/ret/BytesReturnValue.java new file mode 100644 index 000000000..478b39ed8 --- /dev/null +++ b/src/main/java/net/openhft/chronicle/map/impl/stage/ret/BytesReturnValue.java @@ -0,0 +1,52 @@ +package net.openhft.chronicle.map.impl.stage.ret; + +import net.openhft.chronicle.hash.Data; +import net.openhft.chronicle.hash.impl.JavaLangBytesReusableBytesStore; +import net.openhft.chronicle.map.ReturnValue; +import net.openhft.chronicle.map.TcpReplicator.TcpSocketChannelEntryWriter; +import net.openhft.chronicle.map.impl.VanillaChronicleMapHolder; +import net.openhft.lang.io.Bytes; +import net.openhft.sg.Stage; +import net.openhft.sg.StageRef; +import net.openhft.sg.Staged; +import org.jetbrains.annotations.NotNull; + +@Staged +public class BytesReturnValue implements ReturnValue, AutoCloseable { + + @StageRef + VanillaChronicleMapHolder mh; + + private final JavaLangBytesReusableBytesStore outputStore = + new JavaLangBytesReusableBytesStore(); + + @Stage("Output") TcpSocketChannelEntryWriter output = null; + @Stage("Output") long startOutputPos; + + public void initOutput(TcpSocketChannelEntryWriter output) { + this.output = output; + startOutputPos = output.in().position(); + } + + @Override + public void returnValue(@NotNull Data value) { + long valueSize = value.size(); + long totalSize = 1L + mh.m().valueSizeMarshaller.sizeEncodingSize(valueSize) + valueSize; + output.ensureBufferSize(totalSize); + Bytes out = output.in(); + out.writeBoolean(false); + mh.m().valueSizeMarshaller.writeSize(out, valueSize); + long outPosition = out.position(); + out.skip(valueSize); + outputStore.setBytes(out); + value.writeTo(outputStore, outPosition); + } + + @Override + public void close() { + if (output.in().position() == startOutputPos) { + output.ensureBufferSize(1L); + output.in().writeBoolean(true); + } + } +} diff --git a/src/main/java/net/openhft/chronicle/map/impl/stage/ret/DefaultReturnValue.java b/src/main/java/net/openhft/chronicle/map/impl/stage/ret/DefaultReturnValue.java new file mode 100644 index 000000000..dbbf7e797 --- /dev/null +++ b/src/main/java/net/openhft/chronicle/map/impl/stage/ret/DefaultReturnValue.java @@ -0,0 +1,31 @@ +package net.openhft.chronicle.map.impl.stage.ret; + +import net.openhft.chronicle.hash.Data; +import net.openhft.chronicle.map.impl.ret.InstanceReturnValue; +import net.openhft.sg.Staged; +import org.jetbrains.annotations.NotNull; + +@Staged +public abstract class DefaultReturnValue implements InstanceReturnValue { + private V defaultReturnedValue = null; + + abstract boolean defaultReturnedValueInit(); + + private void initDefaultReturnedValue(@NotNull Data value) { + defaultReturnedValue = value.getUsing(null); + } + + @Override + public void returnValue(@NotNull Data value) { + initDefaultReturnedValue(value); + } + + @Override + public V returnValue() { + if (defaultReturnedValueInit()) { + return defaultReturnedValue; + } else { + return null; + } + } +} diff --git a/src/main/java/net/openhft/chronicle/map/impl/stage/ret/UsingReturnValue.java b/src/main/java/net/openhft/chronicle/map/impl/stage/ret/UsingReturnValue.java new file mode 100644 index 000000000..1c279dee7 --- /dev/null +++ b/src/main/java/net/openhft/chronicle/map/impl/stage/ret/UsingReturnValue.java @@ -0,0 +1,39 @@ +package net.openhft.chronicle.map.impl.stage.ret; + +import net.openhft.chronicle.hash.Data; +import net.openhft.chronicle.map.impl.ret.UsableReturnValue; +import net.openhft.sg.Staged; +import org.jetbrains.annotations.NotNull; + +@Staged +public abstract class UsingReturnValue implements UsableReturnValue { + + private V usingReturnValue = (V) USING_RETURN_VALUE_UNINT; + + @Override + public void initUsingReturnValue(V usingReturnValue) { + this.usingReturnValue = usingReturnValue; + } + + private V returnedValue = null; + + abstract boolean returnedValueInit(); + + private void initReturnedValue(@NotNull Data value) { + returnedValue = value.getUsing(usingReturnValue); + } + + @Override + public void returnValue(@NotNull Data value) { + initReturnedValue(value); + } + + @Override + public V returnValue() { + if (returnedValueInit()) { + return returnedValue; + } else { + return null; + } + } +}