Skip to content
Open
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
12 changes: 7 additions & 5 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,8 @@ subprojects {
"--add-exports=java.base/sun.nio.ch=ALL-UNNAMED",
"--add-exports=jdk.unsupported/sun.misc=ALL-UNNAMED",
"--add-exports=jdk.compiler/com.sun.tools.javac.file=ALL-UNNAMED",
"--add-exports=java.base/java.lang.reflect=ALL-UNNAMED"]
"--add-exports=java.base/java.lang.reflect=ALL-UNNAMED"
]
}

compileTestJava {
Expand Down Expand Up @@ -260,13 +261,14 @@ subprojects {
"--add-opens=java.base/java.io=ALL-UNNAMED",
"--add-opens=java.base/java.util=ALL-UNNAMED",
"--add-opens=java.base/java.lang.reflect=ALL-UNNAMED",
"--enable-native-access=ALL-UNNAMED",
"-XX:+UnlockDiagnosticVMOptions",
"-XX:+DebugNonSafepoints",
//"-XX:+UseShenandoahGC",
// "-Xlog:gc*=debug:file=g1.log",
// "-XX:+UseZGC",
"-Xlog:gc*=debug:file=g1.log",
"-XX:+UseZGC",
// "-XX:+ZGenerational",
// "-verbose:gc",
"-verbose:gc",
"-XX:+HeapDumpOnOutOfMemoryError",
//"-XX:HeapDumpPath=heapdump.hprof",
"-XX:+UseStringDeduplication",
Expand All @@ -285,7 +287,7 @@ subprojects {
/* "-XX:MaxInlineSize=500" */])

minHeapSize = '5g'
maxHeapSize = '8g'
maxHeapSize = '12g'
}
}

Expand Down
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
253 changes: 0 additions & 253 deletions bundles/sirix-core/g1-chicago.log

This file was deleted.

38,662 changes: 0 additions & 38,662 deletions bundles/sirix-core/g1-detailed.log

This file was deleted.

13,733 changes: 0 additions & 13,733 deletions bundles/sirix-core/shenandoah.log

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,12 @@ public static int compareStructure(final Path file) {
*/
private DatabaseType databaseType;

/**
* Maximum buffer size for memory segment allocation.
* Default is 1GB.
*/
private long maxSegmentAllocationSize = 1L << 30; // 1GB default

/**
* Constructor with the path to be set.
*
Expand Down Expand Up @@ -180,6 +186,28 @@ public DatabaseType getDatabaseType() {
return databaseType;
}

/**
* Set the maximum buffer size for memory segment allocation.
*
* @param size maximum buffer size in bytes
* @return this {@link DatabaseConfiguration} instance
*/
public DatabaseConfiguration setMaxSegmentAllocationSize(final long size) {
checkArgument(size > 0, "Max buffer size must be positive");
this.maxSegmentAllocationSize = size;
return this;
}

/**
* Get the maximum buffer size for memory segment allocation.
*
* @return maximum buffer size in bytes
*/
public long getMaxSegmentAllocationSize() {
return maxSegmentAllocationSize;
}


/**
* Set unique maximum resource ID.
*
Expand Down Expand Up @@ -260,6 +288,7 @@ public static void serialize(final DatabaseConfiguration config) throws SirixIOE
jsonWriter.name("file").value(filePath);
jsonWriter.name("ID").value(config.maxResourceID);
jsonWriter.name("databaseType").value(config.databaseType.toString());
jsonWriter.name("maxSegmentAllocationSize").value(config.maxSegmentAllocationSize);
jsonWriter.endObject();
} catch (final IOException e) {
throw new SirixIOException(e);
Expand Down Expand Up @@ -287,10 +316,13 @@ public static DatabaseConfiguration deserialize(final Path file) {
final String databaseType = jsonReader.nextName();
assert databaseType.equals("databaseType");
final String type = jsonReader.nextString();
final String maxSegmentAllocationSizeName = jsonReader.nextName();
assert maxSegmentAllocationSizeName.equals("maxSegmentAllocationSize");
final long maxSegmentAllocationSize = jsonReader.nextLong();
jsonReader.endObject();
final DatabaseType dbType = DatabaseType.fromString(type)
.orElseThrow(() -> new IllegalStateException("Type can not be unknown."));
return new DatabaseConfiguration(dbFile).setMaximumResourceID(ID).setDatabaseType(dbType);
return new DatabaseConfiguration(dbFile).setMaximumResourceID(ID).setDatabaseType(dbType).setMaxSegmentAllocationSize(maxSegmentAllocationSize);
} catch (final IOException e) {
throw new SirixIOException(e);
}
Expand Down
37 changes: 35 additions & 2 deletions bundles/sirix-core/src/main/java/io/sirix/access/Databases.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,11 @@
import io.sirix.api.*;
import io.sirix.api.json.JsonResourceSession;
import io.sirix.api.xml.XmlResourceSession;
import io.sirix.cache.BufferManager;
import io.sirix.cache.*;
import io.sirix.exception.SirixIOException;
import io.sirix.exception.SirixUsageException;
import io.sirix.utils.LogWrapper;
import io.sirix.utils.OS;
import io.sirix.utils.SirixFiles;
import org.slf4j.LoggerFactory;

Expand Down Expand Up @@ -40,7 +41,8 @@ private Databases() {
/**
* Buffer managers / page cache for each resource.
*/
private static final ConcurrentMap<Path, ConcurrentMap<Path, BufferManager>> BUFFER_MANAGERS = new ConcurrentHashMap<>();
private static final ConcurrentMap<Path, ConcurrentMap<Path, BufferManager>> BUFFER_MANAGERS =
new ConcurrentHashMap<>();

/**
* DI component that manages the database.
Expand Down Expand Up @@ -82,6 +84,10 @@ public static synchronized boolean createJsonDatabase(final DatabaseConfiguratio
}

private static boolean createTheDatabase(final DatabaseConfiguration dbConfig) {
requireNonNull(dbConfig);

initAllocator(dbConfig.getMaxSegmentAllocationSize());

boolean returnVal = true;
// if file is existing, skipping
final var databaseFile = dbConfig.getDatabaseFile();
Expand Down Expand Up @@ -158,6 +164,22 @@ public static synchronized void removeDatabase(final Path dbFile) {
bufferManagers.values().forEach(BufferManager::clearAllCaches);
}
SirixFiles.recursiveRemove(dbFile);

freeAllocatedMemory();
} else {
logger.warn("Database at {} could not be removed, because it is either not existing or still in use.", dbFile);
}
}

public static void freeAllocatedMemory() {
if (MANAGER.sessions().isEmpty()) {
// // If no sessions are left, we can clean up the allocator.
// MemorySegmentAllocator segmentAllocator =
// OS.isWindows() ? WindowsMemorySegmentAllocator.getInstance() : LinuxMemorySegmentAllocator.getInstance();
// segmentAllocator.free();
KeyValueLeafPagePool.getInstance().free();
BUFFER_MANAGERS.values()
.forEach((resourcePathsToBufferManagers -> resourcePathsToBufferManagers.forEach((_, bufferManager) -> bufferManager.clearAllCaches())));
}
}

Expand Down Expand Up @@ -257,9 +279,20 @@ private static <M extends ResourceSession<R, W>, R extends NodeReadOnlyTrx & Nod
if (dbConfig == null) {
throw new IllegalStateException("Configuration may not be null!");
}

initAllocator(dbConfig.getMaxSegmentAllocationSize());
return databaseType.createDatabase(dbConfig, user);
}

private static void initAllocator(long maxSegmentAllocationSize) {
if (MANAGER.sessions().isEmpty()) {
KeyValueLeafPagePool.getInstance().init(maxSegmentAllocationSize);
// MemorySegmentAllocator segmentAllocator =
// OS.isWindows() ? WindowsMemorySegmentAllocator.getInstance() : LinuxMemorySegmentAllocator.getInstance();
// segmentAllocator.init(maxSegmentAllocationSize);
}
}

/**
* Determines if a database already exists.
*
Expand Down
23 changes: 13 additions & 10 deletions bundles/sirix-core/src/main/java/io/sirix/access/LocalDatabase.java
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ public final class LocalDatabase<T extends ResourceSession<? extends NodeReadOnl
*/
private final ResourceStore<T> resourceStore;

private final PathBasedPool<ResourceSession<?, ?>> resourceManagers;
private final PathBasedPool<ResourceSession<?, ?>> resourceSessions;

/**
* This field should be use to fetch the locks for resource managers.
Expand All @@ -102,24 +102,24 @@ public final class LocalDatabase<T extends ResourceSession<? extends NodeReadOnl
* @param sessions The database sessions management instance.
* @param resourceStore The resource store used by this database.
* @param writeLocks Manages the locks for resource managers.
* @param resourceManagers The pool for resource managers.
* @param resourceSessions The pool for resource managers.
*/
public LocalDatabase(final TransactionManager transactionManager, final DatabaseConfiguration dbConfig,
final PathBasedPool<Database<?>> sessions, final ResourceStore<T> resourceStore,
final WriteLocksRegistry writeLocks, final PathBasedPool<ResourceSession<?, ?>> resourceManagers) {
final WriteLocksRegistry writeLocks, final PathBasedPool<ResourceSession<?, ?>> resourceSessions) {
this.transactionManager = transactionManager;
this.dbConfig = requireNonNull(dbConfig);
this.sessions = sessions;
this.resourceStore = resourceStore;
this.resourceManagers = resourceManagers;
this.resourceSessions = resourceSessions;
this.writeLocks = writeLocks;
this.resourceIDsToResourceNames = Maps.synchronizedBiMap(HashBiMap.create());
this.sessions.putObject(dbConfig.getDatabaseFile(), this);
this.bufferManagers = Databases.getBufferManager(dbConfig.getDatabaseFile());
}

private void addResourceToBufferManagerMapping(Path resourceFile, ResourceConfiguration resourceConfig) {
bufferManagers.put(resourceFile, new BufferManagerImpl(10_000, 1_000, 5_000, 50_000, 500, 20));
private void addResourceToBufferManagerMapping(Path resourceFile) {
bufferManagers.put(resourceFile, new BufferManagerImpl(500_000, 65_536 * 100, 5_000, 50_000, 500, 20));
}

@Override
Expand Down Expand Up @@ -148,7 +148,7 @@ private void addResourceToBufferManagerMapping(Path resourceFile, ResourceConfig

// Add resource to buffer manager mapping.
if (!bufferManagers.containsKey(resourcePath)) {
addResourceToBufferManagerMapping(resourcePath, resourceConfig);
addResourceToBufferManagerMapping(resourcePath);
}

return resourceStore.beginResourceSession(resourceConfig, bufferManagers.get(resourcePath), resourcePath);
Expand Down Expand Up @@ -220,7 +220,7 @@ public synchronized boolean createResource(final ResourceConfiguration resourceC
}

if (!bufferManagers.containsKey(path)) {
addResourceToBufferManagerMapping(path, resourceConfig);
addResourceToBufferManagerMapping(path);
}

return returnVal;
Expand Down Expand Up @@ -269,8 +269,8 @@ public synchronized Database<T> removeResource(final String name) {
dbConfig.getDatabaseFile().resolve(DatabaseConfiguration.DatabasePaths.DATA.getFile()).resolve(name);

// Check that no running resource managers / sessions are opened.
if (this.resourceManagers.containsAnyEntry(resourceFile)) {
throw new IllegalStateException("Open resource managers found, must be closed first: " + resourceManagers);
if (this.resourceSessions.containsAnyEntry(resourceFile)) {
throw new IllegalStateException("Open resource managers found, must be closed first: " + resourceSessions);
}

// If file is existing and folder is a Sirix-dataplace, delete it.
Expand Down Expand Up @@ -362,6 +362,9 @@ public synchronized void close() {
// Remove from database mapping.
this.sessions.removeObject(dbConfig.getDatabaseFile(), this);

// Free all allocated memory if it's the last database which is closed.
Databases.freeAllocatedMemory();

// Remove lock file.
SirixFiles.recursiveRemove(dbConfig.getDatabaseFile().resolve(DatabaseConfiguration.DatabasePaths.LOCK.getFile()));
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;

import static java.util.Collections.unmodifiableMap;

Expand All @@ -29,7 +30,7 @@ public class PathBasedPool<E> {
/**
* The thread safe map of objects in the pool.
*/
private final Map<Path, Set<E>> sessions;
private final ConcurrentMap<Path, Set<E>> sessions;

/**
* Default Constructor
Expand Down Expand Up @@ -58,6 +59,15 @@ public boolean containsAnyEntry(final Path file) {
return this.sessions.containsKey(file);
}

/**
* Checks if the pool is empty.
*
* @return {@code true} if the pool is empty, {@code false} otherwise.
*/
public boolean isEmpty() {
return this.sessions.isEmpty();
}

/**
* Package private method to remove a database.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,20 +31,19 @@
import com.google.common.base.MoreObjects;
import com.google.gson.stream.JsonReader;
import com.google.gson.stream.JsonWriter;
import io.sirix.access.trx.node.HashType;
import io.sirix.node.NodeSerializerImpl;
import io.sirix.node.interfaces.RecordSerializer;
import net.openhft.hashing.LongHashFunction;
import org.checkerframework.checker.index.qual.NonNegative;
import io.sirix.BinaryEncodingVersion;
import io.sirix.access.trx.node.HashType;
import io.sirix.exception.SirixIOException;
import io.sirix.io.StorageType;
import io.sirix.io.bytepipe.ByteHandler;
import io.sirix.io.bytepipe.ByteHandlerKind;
import io.sirix.io.bytepipe.ByteHandlerPipeline;
import io.sirix.io.bytepipe.LZ4Compressor;
import io.sirix.node.NodeSerializerImpl;
import io.sirix.node.interfaces.RecordSerializer;
import io.sirix.settings.VersioningType;
import io.sirix.utils.OS;
import net.openhft.hashing.LongHashFunction;
import org.checkerframework.checker.index.qual.NonNegative;

import java.io.FileReader;
import java.io.FileWriter;
Expand Down Expand Up @@ -169,8 +168,8 @@ public static int compareStructure(final Path file) {
/**
* Standard storage.
*/
private static final StorageType STORAGE =
OS.isWindows() ? StorageType.FILE_CHANNEL : OS.is64Bit() ? StorageType.MEMORY_MAPPED : StorageType.FILE_CHANNEL;
private static final StorageType STORAGE = StorageType.FILE_CHANNEL;
//OS.isWindows() ? StorageType.FILE_CHANNEL : OS.is64Bit() ? StorageType.MEMORY_MAPPED : StorageType.FILE_CHANNEL;

/**
* Standard versioning approach.
Expand Down Expand Up @@ -709,7 +708,7 @@ public static final class Builder {
/**
* Determines if node history should be stored or not.
*/
private boolean storeNodeHistory;
private boolean storeNodeHistory = true;

private BinaryEncodingVersion binaryEncodingVersion = BINARY_ENCODING_VERSION;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ public R getOpenResourceSession(final Path resourceFile) {

@Override
public void close() {
resourceSessions.forEach((resourceName, resourceMgr) -> resourceMgr.close());
resourceSessions.forEach((_, resourceSession) -> resourceSession.close());
resourceSessions.clear();
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ public abstract class AbstractNodeReadOnlyTrx<T extends NodeCursor & NodeReadOnl
/**
* ID of transaction.
*/
protected final long id;
protected final int id;

/**
* State of transaction including all cached stuff.
Expand Down Expand Up @@ -75,7 +75,7 @@ public abstract class AbstractNodeReadOnlyTrx<T extends NodeCursor & NodeReadOnl
* @param resourceSession The resource manager for the current transaction
* @param itemList Read-transaction-exclusive item list.
*/
protected AbstractNodeReadOnlyTrx(final @NonNegative long trxId, final @NonNull PageReadOnlyTrx pageReadTransaction,
protected AbstractNodeReadOnlyTrx(final @NonNegative int trxId, final @NonNull PageReadOnlyTrx pageReadTransaction,
final @NonNull N documentNode, final InternalResourceSession<T, W> resourceSession,
final ItemList<AtomicValue> itemList) {
this.itemList = itemList;
Expand Down Expand Up @@ -196,7 +196,7 @@ public long getPathNodeKey() {
}

@Override
public long getId() {
public int getId() {
assertNotClosed();
return id;
}
Expand Down Expand Up @@ -534,11 +534,8 @@ public boolean isClosed() {
}

@Override
public synchronized void close() {
public void close() {
if (!isClosed) {
// Close own state.
pageReadOnlyTrx.close();

// Callback on session to make sure everything is cleaned up.
resourceSession.closeReadTransaction(id);

Expand Down
Loading