Revert method and field reordering

This commit is contained in:
leventov
2017-06-04 12:33:41 -05:00
parent 5c8c50ba6b
commit 3e903775f9
4 changed files with 180 additions and 148 deletions
@@ -71,84 +71,113 @@ public abstract class VanillaChronicleHash<K,
public static final long RESERVED_GLOBAL_MUTABLE_STATE_BYTES = 1024;
// --- Start of instance fields ---
/**
* Global mutable state lock doesn't yet need read-write levels and waits;
* Used the same locking strategy as in segment locks
* (VanillaReadWriteUpdateWithWaitsLockingStrategy) in order to simplify Chronicle Map
* specification (having only one kind of locks to specify and implement).
*/
static final LockingStrategy globalMutableStateLockingStrategy =
VanillaReadWriteUpdateWithWaitsLockingStrategy.instance();
static final TryAcquireOperation<LockingStrategy> globalMutableStateLockTryAcquireOperation =
TryAcquireOperations.lock();
static final
AcquisitionStrategy<LockingStrategy, RuntimeException>
globalMutableStateLockAcquisitionStrategy =
AcquisitionStrategies.spinLoopOrFail(2, TimeUnit.SECONDS);
private static final long GLOBAL_MUTABLE_STATE_LOCK_OFFSET = 0L;
private static final long GLOBAL_MUTABLE_STATE_VALUE_OFFSET = 8L;
/////////////////////////////////////////////////
private String dataFileVersion;
/////////////////////////////////////////////////
// If the hash was created in the first place, or read from disk
public transient boolean createdOrInMemory;
/////////////////////////////////////////////////
// Key Data model
public Class<K> keyClass;
public SizeMarshaller keySizeMarshaller;
public SizedReader<K> keyReader;
public DataAccess<K> keyDataAccess;
/////////////////////////////////////////////////
public boolean checksumEntries;
/////////////////////////////////////////////////
// Concurrency (number of segments), memory management and dependent fields
public int actualSegments;
public HashSplitting hashSplitting;
public long chunkSize;
public int maxChunksPerEntry;
public long actualChunksPerSegmentTier;
/////////////////////////////////////////////////
// Precomputed offsets and sizes for fast Context init
int segmentHeaderSize;
public int tierHashLookupValueBits;
public int tierHashLookupKeyBits;
public int tierHashLookupSlotSize;
public long tierHashLookupCapacity;
public long maxEntriesPerHashLookup;
long tierHashLookupInnerSize;
public long tierHashLookupOuterSize;
public long tierFreeListInnerSize;
public long tierFreeListOuterSize;
public int tierEntrySpaceInnerOffset;
public long tierSize;
public long tiersInBulk;
public transient List<TierBulkData> tierBulkOffsets;
public transient long headerSize;
public transient long segmentHeadersOffset;
/////////////////////////////////////////////////
// Miscellaneous fields
public transient CompactOffHeapLinearHashTable hashLookup;
public transient Identity identity;
protected int log2TiersInBulk;
/////////////////////////////////////////////////
// Bytes Store (essentially, the base address) and serialization-dependent offsets
protected transient BytesStore bs;
/////////////////////////////////////////////////
// Precomputed offsets and sizes for fast Context init
int segmentHeaderSize;
long tierHashLookupInnerSize;
long tierEntrySpaceInnerSize;
public int tierEntrySpaceInnerOffset;
long tierEntrySpaceOuterSize;
public long tierSize;
long maxExtraTiers;
long tierBulkSizeInBytes;
long tierBulkInnerOffsetToTiers;
transient long segmentsOffset;
/////////////////////////////////////////////////
private String dataFileVersion;
public long tiersInBulk;
protected int log2TiersInBulk;
/////////////////////////////////////////////////
// Resources
private transient File file;
private transient RandomAccessFile raf;
// --- End of instance fields ---
private transient ChronicleHashResources resources;
private transient Cleaner cleaner;
/////////////////////////////////////////////////
// Bytes Store (essentially, the base address) and serialization-dependent offsets
protected transient BytesStore bs;
public static class TierBulkData {
public final BytesStore bytesStore;
public final long offset;
public TierBulkData(BytesStore bytesStore, long offset) {
this.bytesStore = bytesStore;
this.offset = offset;
}
public TierBulkData(TierBulkData data, long offset) {
this.bytesStore = data.bytesStore;
this.offset = offset;
}
}
public transient List<TierBulkData> tierBulkOffsets;
public transient long headerSize;
public transient long segmentHeadersOffset;
transient long segmentsOffset;
/////////////////////////////////////////////////
// Miscellaneous fields
public transient CompactOffHeapLinearHashTable hashLookup;
private transient VanillaGlobalMutableState globalMutableState;
/**
* {@link ChronicleHashCloseOnExitHook} needs to use {@code VanillaChronicleHash}es as
* WeakHashMap keys, but with identity comparison, not Map's equals() and hashCode().
*/
public class Identity {
public VanillaChronicleHash hash() {
return VanillaChronicleHash.this;
}
}
public transient Identity identity;
// --- End of instance fields ---
public VanillaChronicleHash(ChronicleMapBuilder<K, ?> builder) {
// Version
dataFileVersion = BuildVersion.version();
@@ -209,20 +238,6 @@ public abstract class VanillaChronicleHash<K,
checksumEntries = privateAPI.checksumEntries();
}
public static IOException throwRecoveryOrReturnIOException(
File file, String message, boolean recover) {
message = "file=" + file + " " + message;
if (recover) {
throw new ChronicleHashRecoveryFailedException(message);
} else {
return new IOException(message);
}
}
private static long roundUpMapHeaderSize(long headerSize) {
return CACHE_LINES.align(headerSize, BYTES);
}
@Override
public void readMarshallable(@NotNull WireIn wire) {
readMarshallableFields(wire);
@@ -409,6 +424,20 @@ public abstract class VanillaChronicleHash<K,
}
}
public static IOException throwRecoveryOrReturnIOException(
File file, String message, boolean recover) {
message = "file=" + file + " " + message;
if (recover) {
throw new ChronicleHashRecoveryFailedException(message);
} else {
return new IOException(message);
}
}
private static long roundUpMapHeaderSize(long headerSize) {
return CACHE_LINES.align(headerSize, BYTES);
}
public final void createInMemoryStoreAndSegments(ChronicleHashResources resources)
throws IOException {
this.resources = resources;
@@ -710,6 +739,24 @@ public abstract class VanillaChronicleHash<K,
return actualSegments;
}
/**
* Global mutable state lock doesn't yet need read-write levels and waits;
* Used the same locking strategy as in segment locks
* (VanillaReadWriteUpdateWithWaitsLockingStrategy) in order to simplify Chronicle Map
* specification (having only one kind of locks to specify and implement).
*/
static final LockingStrategy globalMutableStateLockingStrategy =
VanillaReadWriteUpdateWithWaitsLockingStrategy.instance();
static final TryAcquireOperation<LockingStrategy> globalMutableStateLockTryAcquireOperation =
TryAcquireOperations.lock();
static final
AcquisitionStrategy<LockingStrategy, RuntimeException>
globalMutableStateLockAcquisitionStrategy =
AcquisitionStrategies.spinLoopOrFail(2, TimeUnit.SECONDS);
private static final long GLOBAL_MUTABLE_STATE_LOCK_OFFSET = 0L;
private static final long GLOBAL_MUTABLE_STATE_VALUE_OFFSET = 8L;
private long globalMutableStateAddress() {
return bsAddress() + headerSize;
}
@@ -998,29 +1045,4 @@ public abstract class VanillaChronicleHash<K,
public List<WeakReference<ContextHolder>> allContexts() {
return Collections.unmodifiableList(resources.contexts());
}
public static class TierBulkData {
public final BytesStore bytesStore;
public final long offset;
public TierBulkData(BytesStore bytesStore, long offset) {
this.bytesStore = bytesStore;
this.offset = offset;
}
public TierBulkData(TierBulkData data, long offset) {
this.bytesStore = data.bytesStore;
this.offset = offset;
}
}
/**
* {@link ChronicleHashCloseOnExitHook} needs to use {@code VanillaChronicleHash}es as
* WeakHashMap keys, but with identity comparison, not Map's equals() and hashCode().
*/
public class Identity {
public VanillaChronicleHash hash() {
return VanillaChronicleHash.this;
}
}
}
@@ -143,7 +143,7 @@ public final class SerializationBuilder<T> implements Cloneable {
try {
return (Byteable) OS.memory().allocateInstance(tClass);
} catch (InstantiationException e) {
throw new AssertionError(e);
throw new IllegalStateException(e);
}
}
@@ -152,6 +152,7 @@ public final class ChronicleMapBuilder<K, V> implements
private static final double UNDEFINED_DOUBLE_CONFIG = Double.NaN;
private static final ConcurrentHashMap<File, Void> fileLockingControl =
new ConcurrentHashMap<>(128);
private static int MAX_BOOTSTRAPPING_HEADER_SIZE = (int) MemoryUnit.KILOBYTES.toBytes(16);
private static final Logger chronicleMapLogger = LoggerFactory.getLogger(ChronicleMap.class);
private static final ChronicleHashCorruption.Listener defaultChronicleMapCorruptionListener =
corruption -> {
@@ -161,7 +162,8 @@ public final class ChronicleMapBuilder<K, V> implements
chronicleMapLogger.error(corruption.message());
}
};
private static int MAX_BOOTSTRAPPING_HEADER_SIZE = (int) MemoryUnit.KILOBYTES.toBytes(16);
private String name;
SerializationBuilder<K> keyBuilder;
SerializationBuilder<V> valueBuilder;
K averageKey;
@@ -175,6 +177,7 @@ public final class ChronicleMapBuilder<K, V> implements
long cleanupTimeout = 1;
TimeUnit cleanupTimeoutUnit = TimeUnit.MINUTES;
boolean cleanupRemovedEntries = true;
//////////////////////////////
// Configuration fields
DefaultValueProvider<K, V> defaultValueProvider = DefaultSpi.defaultValueProvider();
@@ -182,7 +185,6 @@ public final class ChronicleMapBuilder<K, V> implements
MapMethods<K, V, ?> methods = DefaultSpi.mapMethods();
MapEntryOperations<K, V, ?> entryOperations = mapEntryOperations();
MapRemoteOperations<K, V, ?> remoteOperations = mapRemoteOperations();
private String name;
// not final because of cloning
private ChronicleMapBuilderPrivateAPI<K, V> privateAPI =
new ChronicleMapBuilderPrivateAPI<>(this);
@@ -418,52 +420,6 @@ public final class ChronicleMapBuilder<K, V> implements
writeFully(fileChannel, SIZE_WORD_OFFSET, headerBuffer);
}
/**
* @return ByteBuffer, in [position, limit) range the self bootstrapping header is read
*/
private static ByteBuffer readSelfBootstrappingHeader(
File file, RandomAccessFile raf, int headerSize, boolean recover,
ChronicleHashCorruption.Listener corruptionListener,
ChronicleHashCorruptionImpl corruption) throws IOException {
if (raf.length() < headerSize + SELF_BOOTSTRAPPING_HEADER_OFFSET) {
throw throwRecoveryOrReturnIOException(file,
"The file is shorter than the header size: " + headerSize +
", file size: " + raf.length(), recover);
}
FileChannel fileChannel = raf.getChannel();
ByteBuffer headerBuffer = ByteBuffer.allocate(
SELF_BOOTSTRAPPING_HEADER_OFFSET + headerSize);
headerBuffer.order(LITTLE_ENDIAN);
readFully(fileChannel, 0, headerBuffer);
if (headerBuffer.remaining() > 0) {
throw throwRecoveryOrReturnIOException(file, "Unable to read the header fully, " +
headerBuffer.remaining() + " is remaining to read, likely the file was " +
"truncated", recover);
}
int sizeWord = headerBuffer.getInt(SIZE_WORD_OFFSET);
if (!SizePrefixedBlob.isReady(sizeWord)) {
if (recover) {
report(corruptionListener, corruption, -1, () ->
format("file={}: size-prefixed blob readiness bit is set to NOT_COMPLETE",
file)
);
// the bit will be overwritten to READY in the end of recovery procedure, so nothing
// to fix right here
} else {
throw new IOException("file=" + file + ": sizeWord is not ready: " + sizeWord);
}
}
headerBuffer.position(SELF_BOOTSTRAPPING_HEADER_OFFSET);
return headerBuffer;
}
private static boolean checkSumSelfBootstrappingHeader(
ByteBuffer headerBuffer, int headerSize) {
long checkSum = headerChecksum(headerBuffer, headerSize);
long storedChecksum = headerBuffer.getLong(HEADER_OFFSET);
return storedChecksum == checkSum;
}
@Override
public ChronicleMapBuilder<K, V> clone() {
try {
@@ -1709,6 +1665,52 @@ public final class ChronicleMapBuilder<K, V> implements
}
}
/**
* @return ByteBuffer, in [position, limit) range the self bootstrapping header is read
*/
private static ByteBuffer readSelfBootstrappingHeader(
File file, RandomAccessFile raf, int headerSize, boolean recover,
ChronicleHashCorruption.Listener corruptionListener,
ChronicleHashCorruptionImpl corruption) throws IOException {
if (raf.length() < headerSize + SELF_BOOTSTRAPPING_HEADER_OFFSET) {
throw throwRecoveryOrReturnIOException(file,
"The file is shorter than the header size: " + headerSize +
", file size: " + raf.length(), recover);
}
FileChannel fileChannel = raf.getChannel();
ByteBuffer headerBuffer = ByteBuffer.allocate(
SELF_BOOTSTRAPPING_HEADER_OFFSET + headerSize);
headerBuffer.order(LITTLE_ENDIAN);
readFully(fileChannel, 0, headerBuffer);
if (headerBuffer.remaining() > 0) {
throw throwRecoveryOrReturnIOException(file, "Unable to read the header fully, " +
headerBuffer.remaining() + " is remaining to read, likely the file was " +
"truncated", recover);
}
int sizeWord = headerBuffer.getInt(SIZE_WORD_OFFSET);
if (!SizePrefixedBlob.isReady(sizeWord)) {
if (recover) {
report(corruptionListener, corruption, -1, () ->
format("file={}: size-prefixed blob readiness bit is set to NOT_COMPLETE",
file)
);
// the bit will be overwritten to READY in the end of recovery procedure, so nothing
// to fix right here
} else {
throw new IOException("file=" + file + ": sizeWord is not ready: " + sizeWord);
}
}
headerBuffer.position(SELF_BOOTSTRAPPING_HEADER_OFFSET);
return headerBuffer;
}
private static boolean checkSumSelfBootstrappingHeader(
ByteBuffer headerBuffer, int headerSize) {
long checkSum = headerChecksum(headerBuffer, headerSize);
long storedChecksum = headerBuffer.getLong(HEADER_OFFSET);
return storedChecksum == checkSum;
}
private VanillaChronicleMap<K, V, ?> createWithNewFile(
VanillaChronicleMap<K, V, ?> map, File file, RandomAccessFile raf,
ChronicleHashResources resources, ByteBuffer headerBuffer, int headerSize)
@@ -1749,7 +1751,6 @@ public final class ChronicleMapBuilder<K, V> implements
Bytes<ByteBuffer> headerBytes = Bytes.wrapForRead(headerBuffer);
headerBytes.readPosition(headerBuffer.position());
headerBytes.readLimit(headerBuffer.limit());
System.out.println(headerBytes);
Wire wire = new TextWire(headerBytes);
VanillaChronicleMap<K, V, ?> map = wire.getValueIn().typedMarshallable();
map.initBeforeMapping(file, raf, headerBuffer.limit(), recover);
@@ -56,29 +56,20 @@ public class VanillaChronicleMap<K, V, R>
ExternalMapQueryContext<K, V, ?>>
implements AbstractChronicleMap<K, V> {
/////////////////////////////////////////////////
// Value Data model
Class<V> valueClass;
public SizeMarshaller valueSizeMarshaller;
public SizedReader<V> valueReader;
public DataAccess<V> valueDataAccess;
public boolean constantlySizedEntry;
/////////////////////////////////////////////////
// Memory management and dependent fields
public int alignment;
public int worstAlignment;
public transient boolean couldNotDetermineAlignmentBeforeAllocation;
/** @see net.openhft.chronicle.set.SetFromMap */
public transient ChronicleSet<K> chronicleSet;
public transient MapEntryOperations<K, V, R> entryOperations;
public transient MapMethods<K, V, R> methods;
public transient DefaultValueProvider<K, V> defaultValueProvider;
/////////////////////////////////////////////////
// Value Data model
Class<V> valueClass;
/////////////////////////////////////////////////
// Behavior
transient boolean putReturnsNull;
transient boolean removeReturnsNull;
transient Set<Entry<K, V>> entrySet;
transient ThreadLocal<ContextHolder> cxt;
/////////////////////////////////////////////////
private transient String name;
/**
@@ -87,7 +78,25 @@ public class VanillaChronicleMap<K, V, R>
* initOwnTransients().
*/
private transient String identityString;
public transient boolean couldNotDetermineAlignmentBeforeAllocation;
/////////////////////////////////////////////////
// Behavior
transient boolean putReturnsNull;
transient boolean removeReturnsNull;
transient Set<Entry<K, V>> entrySet;
/** @see net.openhft.chronicle.set.SetFromMap */
public transient ChronicleSet<K> chronicleSet;
public transient MapEntryOperations<K, V, R> entryOperations;
public transient MapMethods<K, V, R> methods;
private transient boolean defaultEntryOperationsAndMethods;
public transient DefaultValueProvider<K, V> defaultValueProvider;
transient ThreadLocal<ContextHolder> cxt;
public VanillaChronicleMap(ChronicleMapBuilder<K, V> builder) throws IOException {
super(builder);
@@ -107,10 +116,6 @@ public class VanillaChronicleMap<K, V, R>
initTransients();
}
public static long alignAddr(long addr, long alignment) {
return (addr + alignment - 1) & ~(alignment - 1L);
}
@Override
protected void readMarshallableFields(@NotNull WireIn wireIn) {
super.readMarshallableFields(wireIn);
@@ -282,7 +287,7 @@ public class VanillaChronicleMap<K, V, R>
", identityHashCode=" + System.identityHashCode(this) +
"}";
}
@Override
public void clear() {
forEachEntry(c -> c.context().remove(c));
@@ -301,6 +306,10 @@ public class VanillaChronicleMap<K, V, R>
entry.readSkip(skip);
}
public static long alignAddr(long addr, long alignment) {
return (addr + alignment - 1) & ~(alignment - 1L);
}
final ChainingInterface q() {
ThreadLocal<ContextHolder> cxt = this.cxt;
if (cxt == null)