Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@
import java.io.RandomAccessFile;
import java.lang.ref.WeakReference;
import java.lang.reflect.Type;
import java.nio.Buffer;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.channels.FileLock;
Expand Down Expand Up @@ -425,7 +426,8 @@ public final void initBeforeMapping(@NotNull final File file,
throw throwRecoveryOrReturnIOException(file, "truncated", recover);
}
}
globalMutableStateBuffer.flip();
//! Keep the Java 8 Buffer descriptor when this reopening path is compiled on newer JDKs.
((Buffer) globalMutableStateBuffer).flip();
//noinspection unchecked
globalMutableState.bytesStore(BytesStore.wrap(globalMutableStateBuffer), 0, globalMutableState.maxSize());
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@
import java.io.*;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Modifier;
import java.nio.Buffer;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
import java.util.HashMap;
Expand Down Expand Up @@ -356,7 +357,8 @@ private static void writeNotComplete(@NotNull final FileChannel fileChannel,
final int headerSize) throws IOException {
//noinspection PointlessBitwiseExpression
headerBuffer.putInt(SIZE_WORD_OFFSET, NOT_COMPLETE | DATA | headerSize);
headerBuffer.clear().position(SIZE_WORD_OFFSET).limit(SIZE_WORD_OFFSET + 4);
//! Buffer views preserve Java 8 call descriptors when compiling on newer JDKs.
((Buffer) headerBuffer).clear().position(SIZE_WORD_OFFSET).limit(SIZE_WORD_OFFSET + 4);
writeFully(fileChannel, SIZE_WORD_OFFSET, headerBuffer);
}

Expand Down Expand Up @@ -388,11 +390,12 @@ private static <K, V> ByteBuffer writeHeader(@NotNull final FileChannel fileChan
headerBuffer.putInt(SIZE_WORD_OFFSET, NOT_COMPLETE | DATA | headerSize);

// Write the size-prefixed blob to the file
headerBuffer.position(0);
headerBuffer.limit(headerLimit);
final Buffer headerView = headerBuffer;
headerView.position(0);
headerView.limit(headerLimit);
writeFully(fileChannel, 0, headerBuffer);

headerBuffer.position(SELF_BOOTSTRAPPING_HEADER_OFFSET);
headerView.position(SELF_BOOTSTRAPPING_HEADER_OFFSET);
return headerBuffer;
}

Expand All @@ -406,7 +409,7 @@ private static void commitChronicleMapReady(@NotNull final VanillaChronicleHash

//noinspection PointlessBitwiseExpression
headerBuffer.putInt(SIZE_WORD_OFFSET, READY | DATA | headerSize);
headerBuffer.clear().position(SIZE_WORD_OFFSET).limit(SIZE_WORD_OFFSET + 4);
((Buffer) headerBuffer).clear().position(SIZE_WORD_OFFSET).limit(SIZE_WORD_OFFSET + 4);
writeFully(fileChannel, SIZE_WORD_OFFSET, headerBuffer);
}

Expand Down Expand Up @@ -446,7 +449,7 @@ private static ByteBuffer readSelfBootstrappingHeader(@NotNull final File file,
throw new IOException("file=" + file + ": sizeWord is not ready: " + sizeWord);
}
}
headerBuffer.position(SELF_BOOTSTRAPPING_HEADER_OFFSET);
((Buffer) headerBuffer).position(SELF_BOOTSTRAPPING_HEADER_OFFSET);
return headerBuffer;
}

Expand Down Expand Up @@ -1789,7 +1792,7 @@ private int waitUntilReady(@NotNull final RandomAccessFile raf,
for (int attempt = 0; attempt < attempts; attempt++) {
if (raf.length() >= SELF_BOOTSTRAPPING_HEADER_OFFSET) {

sizeWordBuffer.clear();
((Buffer) sizeWordBuffer).clear();
readFully(fileChannel, SIZE_WORD_OFFSET, sizeWordBuffer);
if (sizeWordBuffer.remaining() == 0) {
int sizeWord = sizeWordBuffer.getInt(0);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
/*
* Copyright 2013-2025 chronicle.software; SPDX-License-Identifier: Apache-2.0
*/
package net.openhft.chronicle.map;

import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TemporaryFolder;

import java.io.File;
import java.io.IOException;

import static org.junit.Assert.assertEquals;

public class PersistedMapHeaderTest {
@Rule
public final TemporaryFolder temporaryFolder = TemporaryFolder.builder().assureDeletion().build();

@Test
public void createReopenAndRecoverPreserveEntries() throws IOException {
File file = temporaryFolder.newFile("header.map");
ChronicleMapBuilder<Long, Long> builder = ChronicleMap.of(Long.class, Long.class).entries(10);

try (ChronicleMap<Long, Long> created = builder.createPersistedTo(file)) {
created.put(1L, 42L);
assertEquals(Long.valueOf(42L), created.get(1L));
}
try (ChronicleMap<Long, Long> reopened = builder.createPersistedTo(file)) {
assertEquals(Long.valueOf(42L), reopened.get(1L));
reopened.put(2L, 43L);
}
try (ChronicleMap<Long, Long> recovered = builder.recoverPersistedTo(file, true)) {
assertEquals(2, recovered.size());
assertEquals(Long.valueOf(42L), recovered.get(1L));
assertEquals(Long.valueOf(43L), recovered.get(2L));
}
try (ChronicleMap<Long, Long> reopened = builder.createPersistedTo(file)) {
assertEquals(2, reopened.size());
assertEquals(Long.valueOf(42L), reopened.get(1L));
assertEquals(Long.valueOf(43L), reopened.get(2L));
}
}
}