Initial implementation
This commit is contained in:
parent
8e37cfa4e0
commit
ce9f5a20a8
@ -1,13 +0,0 @@
|
|||||||
package org.warp;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Hello world!
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
public class App
|
|
||||||
{
|
|
||||||
public static void main( String[] args )
|
|
||||||
{
|
|
||||||
System.out.println( "Hello World!" );
|
|
||||||
}
|
|
||||||
}
|
|
@ -3,17 +3,25 @@ package org.warp.jcwdb;
|
|||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
|
||||||
public class CacheIndexManager implements IndexManager {
|
public class CacheIndexManager implements IndexManager {
|
||||||
public CacheIndexManager() {
|
private final TypesManager typesManager;
|
||||||
|
|
||||||
|
public CacheIndexManager(TypesManager typesManager) {
|
||||||
|
this.typesManager = typesManager;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public <T> T get(long index, int type, DBReader<T> reader) {
|
public <T> T get(long index, DBReader<T> reader) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public <T> void set(long index, int type, DBWriter<T> writer) {
|
public int getType(long index) throws IOException {
|
||||||
|
// TODO Auto-generated method stub
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public <T> void set(long index, DBDataOutput<T> writer) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -26,4 +34,10 @@ public class CacheIndexManager implements IndexManager {
|
|||||||
public boolean has(long index) {
|
public boolean has(long index) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void close() throws IOException {
|
||||||
|
// TODO Auto-generated method stub
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
5
src/main/java/org/warp/jcwdb/Castable.java
Normal file
5
src/main/java/org/warp/jcwdb/Castable.java
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
package org.warp.jcwdb;
|
||||||
|
|
||||||
|
public interface Castable {
|
||||||
|
public <T> T cast();
|
||||||
|
}
|
28
src/main/java/org/warp/jcwdb/DBDataOutput.java
Normal file
28
src/main/java/org/warp/jcwdb/DBDataOutput.java
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
package org.warp.jcwdb;
|
||||||
|
|
||||||
|
public interface DBDataOutput<T> {
|
||||||
|
public int getSize();
|
||||||
|
public int getType();
|
||||||
|
public DBWriter<T> getWriter();
|
||||||
|
|
||||||
|
public static <T> DBDataOutput<T> create(DBWriter<T> writer, int type, int size) {
|
||||||
|
return new DBDataOutput<T>() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getSize() {
|
||||||
|
return size;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getType() {
|
||||||
|
return type;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public DBWriter<T> getWriter() {
|
||||||
|
return writer;
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
18
src/main/java/org/warp/jcwdb/DBStandardTypes.java
Normal file
18
src/main/java/org/warp/jcwdb/DBStandardTypes.java
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
package org.warp.jcwdb;
|
||||||
|
|
||||||
|
public class DBStandardTypes {
|
||||||
|
private static final int STD = 0xFFFFF000;
|
||||||
|
public static final int BOOLEAN = STD| 0;
|
||||||
|
public static final int BYTE = STD| 1;
|
||||||
|
public static final int SHORT = STD| 2;
|
||||||
|
public static final int CHAR = STD| 3;
|
||||||
|
public static final int INTEGER = STD| 4;
|
||||||
|
public static final int FLOAT = STD| 5;
|
||||||
|
public static final int DOUBLE = STD| 6;
|
||||||
|
public static final int STRING = STD| 7;
|
||||||
|
public static final int BYTE_ARRAY = STD| 8;
|
||||||
|
|
||||||
|
public static void registerStandardTypes(TypesManager typesManager) {
|
||||||
|
typesManager.registerType(STRING, new DBStringParser());
|
||||||
|
}
|
||||||
|
}
|
23
src/main/java/org/warp/jcwdb/DBStringParser.java
Normal file
23
src/main/java/org/warp/jcwdb/DBStringParser.java
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
package org.warp.jcwdb;
|
||||||
|
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
|
|
||||||
|
import com.esotericsoftware.kryo.io.Input;
|
||||||
|
import com.esotericsoftware.kryo.io.Output;
|
||||||
|
|
||||||
|
public class DBStringParser extends DBTypeParserImpl<String> {
|
||||||
|
private static final DBReader<String> defaultReader = (i) -> {
|
||||||
|
return i.readString();
|
||||||
|
};
|
||||||
|
|
||||||
|
public DBReader<String> getReader() {
|
||||||
|
return defaultReader;
|
||||||
|
}
|
||||||
|
|
||||||
|
public DBDataOutput<String> getWriter(final String value) {
|
||||||
|
final byte[] bytes = value.getBytes(StandardCharsets.UTF_8);
|
||||||
|
return DBDataOutput.create((o) -> {
|
||||||
|
o.write(bytes);
|
||||||
|
}, DBStandardTypes.STRING, bytes.length);
|
||||||
|
}
|
||||||
|
}
|
@ -1,4 +1,6 @@
|
|||||||
package org.warp.jcwdb;
|
package org.warp.jcwdb;
|
||||||
|
|
||||||
public interface DBTypeParser<T> extends DBReader<T>, DBWriter<T> {
|
public interface DBTypeParser<T> extends Castable {
|
||||||
|
public DBReader<T> getReader();
|
||||||
|
public DBDataOutput<T> getWriter(final T value);
|
||||||
}
|
}
|
||||||
|
9
src/main/java/org/warp/jcwdb/DBTypeParserImpl.java
Normal file
9
src/main/java/org/warp/jcwdb/DBTypeParserImpl.java
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
package org.warp.jcwdb;
|
||||||
|
|
||||||
|
public abstract class DBTypeParserImpl<T> implements DBTypeParser<T> {
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
@Override
|
||||||
|
public T cast() {
|
||||||
|
return (T) this;
|
||||||
|
}
|
||||||
|
}
|
@ -1,19 +1,21 @@
|
|||||||
package org.warp.jcwdb;
|
package org.warp.jcwdb;
|
||||||
|
|
||||||
public abstract class EntryReference<T> {
|
import java.io.IOException;
|
||||||
|
|
||||||
|
public class EntryReference<T> {
|
||||||
private final JCWDatabase db;
|
private final JCWDatabase db;
|
||||||
private final long entryId;
|
private final long entryId;
|
||||||
private final DBTypeParser parser;
|
private final DBTypeParser<T> parser;
|
||||||
public T value;
|
public T value;
|
||||||
|
|
||||||
public EntryReference(JCWDatabase db, long entryId, DBTypeParser<T> parser) {
|
public EntryReference(JCWDatabase db, long entryId, DBTypeParser<T> parser) throws IOException {
|
||||||
this.db = db;
|
this.db = db;
|
||||||
this.entryId = entryId;
|
this.entryId = entryId;
|
||||||
this.parser = parser;
|
this.parser = parser;
|
||||||
this.value = db.get(entryId, parser);
|
this.value = db.getIndexManager().get(entryId, parser.getReader());
|
||||||
}
|
}
|
||||||
|
|
||||||
public void save() {
|
public void save() throws IOException {
|
||||||
db.set(entryId, parser);
|
db.getIndexManager().set(entryId, parser.getWriter(value));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -4,89 +4,63 @@ import com.esotericsoftware.kryo.io.Output;
|
|||||||
|
|
||||||
import java.io.ByteArrayOutputStream;
|
import java.io.ByteArrayOutputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.nio.ByteBuffer;
|
||||||
import java.nio.channels.Channels;
|
import java.nio.channels.Channels;
|
||||||
|
import java.nio.channels.FileChannel;
|
||||||
import java.nio.channels.SeekableByteChannel;
|
import java.nio.channels.SeekableByteChannel;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
|
||||||
public class FileAllocator {
|
public class FileAllocator {
|
||||||
|
private final SeekableByteChannel dataFileChannel;
|
||||||
|
private volatile long allocableOffset;
|
||||||
|
private volatile boolean closed;
|
||||||
|
private final Object closeLock = new Object();
|
||||||
|
|
||||||
|
public FileAllocator(SeekableByteChannel dataFileChannel) throws IOException {
|
||||||
|
this.dataFileChannel = dataFileChannel;
|
||||||
|
this.allocableOffset = this.dataFileChannel.size();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Edit this using editIndex()
|
* TODO: not implemented
|
||||||
*/
|
|
||||||
private final Map<Long, IndexDetails> indicesOffset;
|
|
||||||
/**
|
|
||||||
* Edit this using editIndex()
|
|
||||||
*/
|
|
||||||
private final Set<Long> dirtyIndices;
|
|
||||||
private final SeekableByteChannel fileChannel;
|
|
||||||
|
|
||||||
public FileAllocator(SeekableByteChannel fileChannel) {
|
|
||||||
indicesOffset = new HashMap<>();
|
|
||||||
dirtyIndices = new HashSet<>();
|
|
||||||
this.fileChannel = fileChannel;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void write(final long index, final int type, final DBWriter w) throws IOException {
|
|
||||||
IndexDetails indexDetails = indicesOffset.getOrDefault(index, null);
|
|
||||||
if (indexDetails == null) {
|
|
||||||
allocateAndWrite(index, type, w);
|
|
||||||
} else {
|
|
||||||
write(index, indexDetails, w);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private ByteArrayOutputStream getBytes(DBWriter w) {
|
|
||||||
final ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
|
||||||
w.write(new Output(baos));
|
|
||||||
return baos;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void write(final long index, final IndexDetails indexDetails, DBWriter w) throws IOException {
|
|
||||||
final int size = indexDetails.getSize();
|
|
||||||
final long offset = indexDetails.getOffset();
|
|
||||||
final int type = indexDetails.getType();
|
|
||||||
|
|
||||||
final ByteArrayOutputStream baos = getBytes(w);
|
|
||||||
long newOffset;
|
|
||||||
int newSize = baos.size();
|
|
||||||
if (newSize > size) {
|
|
||||||
newOffset = allocate(newSize);
|
|
||||||
} else {
|
|
||||||
newOffset = offset;
|
|
||||||
}
|
|
||||||
if (size != newSize) {
|
|
||||||
editIndex(index, newOffset, newSize, type);
|
|
||||||
}
|
|
||||||
final Output o = new Output(Channels.newOutputStream(fileChannel.position(newOffset)));
|
|
||||||
o.write(baos.toByteArray());
|
|
||||||
o.close();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void allocateAndWrite(final long index, final int type, DBWriter w) throws IOException {
|
|
||||||
final ByteArrayOutputStream baos = getBytes(w);
|
|
||||||
final int size = baos.size();
|
|
||||||
final long offset = allocate(size);
|
|
||||||
editIndex(index, offset, size, type);
|
|
||||||
|
|
||||||
final Output o = new Output(Channels.newOutputStream(fileChannel.position(offset)));
|
|
||||||
o.write(baos.toByteArray());
|
|
||||||
o.close();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get an offset
|
|
||||||
* @param size
|
* @param size
|
||||||
* @return new offset
|
* @param type
|
||||||
|
* @return offset
|
||||||
*/
|
*/
|
||||||
private long allocate(int size) {
|
public long allocate(int size) {
|
||||||
return 0; // TODO: fare
|
checkClosed();
|
||||||
|
long allocatedOffset = allocableOffset;
|
||||||
|
allocatedOffset += size;
|
||||||
|
return allocatedOffset;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void editIndex(long index, long offset, int size, int type) {
|
|
||||||
editIndex(index, new IndexDetails(offset, size, type));
|
public void close() throws IOException {
|
||||||
|
if (closed) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
synchronized (closeLock) {
|
||||||
|
if (closed) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
closed = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Frees the unused bytes
|
||||||
|
* @param startPosition
|
||||||
|
* @param length
|
||||||
|
*/
|
||||||
|
public void markFree(long startPosition, int length) {
|
||||||
|
checkClosed();
|
||||||
|
// TODO: advanced feature, not implemented.
|
||||||
}
|
}
|
||||||
|
|
||||||
private void editIndex(long index, IndexDetails details) {
|
|
||||||
indicesOffset.put(index, details);
|
private void checkClosed() {
|
||||||
dirtyIndices.add(index);
|
if (closed) {
|
||||||
|
throw new RuntimeException("Index Manager is closed.");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3,43 +3,164 @@ package org.warp.jcwdb;
|
|||||||
import com.esotericsoftware.kryo.io.Input;
|
import com.esotericsoftware.kryo.io.Input;
|
||||||
import com.esotericsoftware.kryo.io.Output;
|
import com.esotericsoftware.kryo.io.Output;
|
||||||
|
|
||||||
|
import java.io.ByteArrayOutputStream;
|
||||||
|
import java.io.FileInputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.nio.ByteBuffer;
|
||||||
import java.nio.channels.Channels;
|
import java.nio.channels.Channels;
|
||||||
import java.nio.channels.SeekableByteChannel;
|
import java.nio.channels.SeekableByteChannel;
|
||||||
import java.nio.file.Files;
|
import java.nio.file.Files;
|
||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
import java.nio.file.StandardOpenOption;
|
import java.nio.file.StandardOpenOption;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
public class FileIndexManager implements IndexManager {
|
public class FileIndexManager implements IndexManager {
|
||||||
|
private final TypesManager typesManager;
|
||||||
private final SeekableByteChannel dataFileChannel, metadataFileChannel;
|
private final SeekableByteChannel dataFileChannel, metadataFileChannel;
|
||||||
private final FileAllocator fileAllocator;
|
private final FileAllocator fileAllocator;
|
||||||
|
private volatile boolean closed;
|
||||||
|
private final Object closeLock = new Object();
|
||||||
|
|
||||||
public FileIndexManager(Path dataFile, Path metadataFile) throws IOException {
|
/**
|
||||||
|
* Edit this using editIndex()
|
||||||
|
* Get using getIndexMetadata()
|
||||||
|
* This hashmap must contain all indices.
|
||||||
|
*/
|
||||||
|
private final Map<Long, IndexDetails> loadedIndices;
|
||||||
|
/**
|
||||||
|
* Edit this using editIndex()
|
||||||
|
*/
|
||||||
|
private final Set<Long> dirtyLoadedIndices;
|
||||||
|
|
||||||
|
public FileIndexManager(TypesManager typesManager, Path dataFile, Path metadataFile) throws IOException {
|
||||||
|
this.typesManager = typesManager;
|
||||||
|
loadedIndices = new HashMap<>();
|
||||||
|
dirtyLoadedIndices = new HashSet<>();
|
||||||
dataFileChannel = Files.newByteChannel(dataFile, StandardOpenOption.CREATE);
|
dataFileChannel = Files.newByteChannel(dataFile, StandardOpenOption.CREATE);
|
||||||
metadataFileChannel = Files.newByteChannel(metadataFile, StandardOpenOption.CREATE);
|
metadataFileChannel = Files.newByteChannel(metadataFile, StandardOpenOption.CREATE);
|
||||||
fileAllocator = new FileAllocator(dataFileChannel);
|
fileAllocator = new FileAllocator(dataFileChannel);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public <T> T get(long l, int type, DBReader<T> r) {
|
public <T> T get(long index, DBReader<T> reader) throws IOException {
|
||||||
Input i = new Input(Channels.newInputStream(dataFileChannel));
|
checkClosed();
|
||||||
T result = r.read(i);
|
IndexDetails details = getIndexMetadata(index);
|
||||||
|
Input i = new Input(Channels.newInputStream(dataFileChannel.position(details.getOffset())));
|
||||||
|
T result = reader.read(i);
|
||||||
i.close();
|
i.close();
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void set(long index, int type, DBWriter w) throws IOException {
|
public int getType(long index) throws IOException {
|
||||||
fileAllocator.write(index, type, w);
|
return getIndexMetadata(index).getType();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public <T> void set(long index, DBDataOutput<T> data) throws IOException {
|
||||||
|
checkClosed();
|
||||||
|
IndexDetails indexDetails = getIndexMetadataUnsafe(index);
|
||||||
|
if (indexDetails == null || indexDetails.getSize() < data.getSize()) {
|
||||||
|
allocateAndWrite(index, data);
|
||||||
|
} else {
|
||||||
|
if (indexDetails.getSize() > data.getSize()) {
|
||||||
|
editIndex(index, indexDetails.getOffset(), data.getSize(), indexDetails.getType());
|
||||||
|
fileAllocator.markFree(indexDetails.getOffset()+data.getSize(), data.getSize());
|
||||||
|
}
|
||||||
|
write(index, indexDetails, data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void write(final long index, final IndexDetails indexDetails, DBDataOutput<?> data) throws IOException {
|
||||||
|
final long offset = indexDetails.getOffset();
|
||||||
|
|
||||||
|
final Output o = new Output(Channels.newOutputStream(dataFileChannel.position(offset)));
|
||||||
|
data.getWriter().write(o);
|
||||||
|
o.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void allocateAndWrite(final long index, DBDataOutput<?> w) throws IOException {
|
||||||
|
final int size = w.getSize();
|
||||||
|
final int type = w.getType();
|
||||||
|
final long offset = fileAllocator.allocate(size);
|
||||||
|
IndexDetails details = editIndex(index, offset, size, type);
|
||||||
|
write(index, details, w);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void delete(long index) {
|
public void delete(long index) {
|
||||||
|
checkClosed();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean has(long index) {
|
public boolean has(long index) {
|
||||||
|
checkClosed();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private IndexDetails editIndex(long index, long offset, int size, int type) {
|
||||||
|
IndexDetails indexDetails = new IndexDetails(offset, size, type);
|
||||||
|
editIndex(index, indexDetails);
|
||||||
|
return indexDetails;
|
||||||
|
}
|
||||||
|
|
||||||
|
private IndexDetails getIndexMetadataUnsafe(long index) {
|
||||||
|
IndexDetails details = loadedIndices.getOrDefault(index, null);
|
||||||
|
if (details != null) return details;
|
||||||
|
|
||||||
|
// TODO: implement index loading from file
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private IndexDetails getIndexMetadata(long index) throws IOException {
|
||||||
|
IndexDetails details = getIndexMetadataUnsafe(index);
|
||||||
|
if (details == null)
|
||||||
|
throw new IOException("Index " + index + " not found");
|
||||||
|
else
|
||||||
|
return details;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void editIndex(long index, IndexDetails details) {
|
||||||
|
loadedIndices.put(index, details);
|
||||||
|
dirtyLoadedIndices.add(index);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void close() throws IOException {
|
||||||
|
if (closed) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
synchronized (closeLock) {
|
||||||
|
if (closed) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
closed = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
SeekableByteChannel metadata = metadataFileChannel;
|
||||||
|
ByteBuffer metadataEntryBuffer = ByteBuffer.allocateDirect(IndexDetails.TOTAL_BYTES);
|
||||||
|
long lastIndex = -2;
|
||||||
|
for (Long index : dirtyLoadedIndices) {
|
||||||
|
IndexDetails indexDetails = loadedIndices.get(index);
|
||||||
|
if (index - lastIndex != 1) {
|
||||||
|
metadata = metadata.position(index * IndexDetails.TOTAL_BYTES);
|
||||||
|
}
|
||||||
|
metadataEntryBuffer.putLong(indexDetails.getOffset());
|
||||||
|
metadataEntryBuffer.putInt(indexDetails.getSize());
|
||||||
|
metadataEntryBuffer.putInt(indexDetails.getType());
|
||||||
|
metadata.write(metadataEntryBuffer);
|
||||||
|
lastIndex = index;
|
||||||
|
}
|
||||||
|
fileAllocator.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void checkClosed() {
|
||||||
|
if (closed) {
|
||||||
|
throw new RuntimeException("Index Manager is closed.");
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -3,6 +3,10 @@ package org.warp.jcwdb;
|
|||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
|
||||||
public class IndexDetails {
|
public class IndexDetails {
|
||||||
|
public static final int OFFSET_BYTES = Long.SIZE;
|
||||||
|
public static final int DATA_SIZE_BYTES = Integer.SIZE;
|
||||||
|
public static final int TYPE_BYTES = Integer.SIZE;
|
||||||
|
public static final int TOTAL_BYTES = OFFSET_BYTES + DATA_SIZE_BYTES + TYPE_BYTES;
|
||||||
private final long offset;
|
private final long offset;
|
||||||
private final int size;
|
private final int size;
|
||||||
private final int type;
|
private final int type;
|
||||||
|
@ -3,8 +3,10 @@ package org.warp.jcwdb;
|
|||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
|
||||||
public interface IndexManager {
|
public interface IndexManager {
|
||||||
public <T> T get(long index, int type, DBReader<T> reader) throws IOException;
|
public <T> T get(long index, DBReader<T> reader) throws IOException;
|
||||||
public <T> void set(long index, int type, DBWriter<T> writer) throws IOException;
|
int getType(long index) throws IOException;
|
||||||
|
public <T> void set(long index, DBDataOutput<T> writer) throws IOException;
|
||||||
public void delete(long index) throws IOException;
|
public void delete(long index) throws IOException;
|
||||||
public boolean has(long index);
|
public boolean has(long index);
|
||||||
|
public void close() throws IOException;
|
||||||
}
|
}
|
||||||
|
@ -1,15 +1,31 @@
|
|||||||
package org.warp.jcwdb;
|
package org.warp.jcwdb;
|
||||||
|
|
||||||
import com.esotericsoftware.kryo.Kryo;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
|
|
||||||
public class JCWDatabase {
|
public class JCWDatabase {
|
||||||
private static final Kryo kryo = new Kryo();
|
private final TypesManager typesManager;
|
||||||
private final MixedIndexDatabase indices;
|
private final MixedIndexDatabase indices;
|
||||||
|
|
||||||
public JCWDatabase(Path dataFile, Path metadataFile) throws IOException {
|
public JCWDatabase(Path dataFile, Path metadataFile) throws IOException {
|
||||||
this.indices = new MixedIndexDatabase(dataFile, metadataFile);
|
this.typesManager = new TypesManager();
|
||||||
|
this.indices = new MixedIndexDatabase(typesManager, dataFile, metadataFile);
|
||||||
|
}
|
||||||
|
|
||||||
|
public <T> EntryReference<T> getRoot() {
|
||||||
|
// Get type of index 0
|
||||||
|
int type = this.indices.getType(0);
|
||||||
|
// Get the parser
|
||||||
|
DBTypeParser<T> parser = this.typesManager.get(type);
|
||||||
|
// Return the reference
|
||||||
|
try {
|
||||||
|
return new EntryReference<T>(this, 0, parser);
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new RuntimeException("Can't load root!", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public IndexManager getIndexManager() {
|
||||||
|
return indices;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -7,23 +7,32 @@ import java.io.IOException;
|
|||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
|
|
||||||
public class MixedIndexDatabase implements IndexManager {
|
public class MixedIndexDatabase implements IndexManager {
|
||||||
|
private final TypesManager typesManager;
|
||||||
private final Long2LongMap mostAccessedIndices;
|
private final Long2LongMap mostAccessedIndices;
|
||||||
private final FileIndexManager fileIndices;
|
private final FileIndexManager fileIndices;
|
||||||
private final CacheIndexManager cacheIndices;
|
private final CacheIndexManager cacheIndices;
|
||||||
|
|
||||||
public MixedIndexDatabase(Path dataFile, Path metadataFile) throws IOException {
|
public MixedIndexDatabase(TypesManager typesManager, Path dataFile, Path metadataFile) throws IOException {
|
||||||
|
this.typesManager = typesManager;
|
||||||
this.mostAccessedIndices = new Long2LongLinkedOpenHashMap();
|
this.mostAccessedIndices = new Long2LongLinkedOpenHashMap();
|
||||||
this.fileIndices = new FileIndexManager(dataFile, metadataFile);
|
this.fileIndices = new FileIndexManager(typesManager, dataFile, metadataFile);
|
||||||
this.cacheIndices = new CacheIndexManager();
|
this.cacheIndices = new CacheIndexManager(typesManager);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public <T> T get(long index, int type, DBReader<T> reader) {
|
public <T> T get(long index, DBReader<T> reader) {
|
||||||
|
// TODO: implement
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public <T> void set(long index, int type, DBWriter<T> writer) {
|
public int getType(long index) {
|
||||||
|
// TODO: implement
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public <T> void set(long index, DBDataOutput<T> writer) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -36,4 +45,11 @@ public class MixedIndexDatabase implements IndexManager {
|
|||||||
public boolean has(long index) {
|
public boolean has(long index) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void close() throws IOException {
|
||||||
|
// TODO: move all cached indices to filesIndices before closing.
|
||||||
|
this.cacheIndices.close();
|
||||||
|
this.fileIndices.close();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
22
src/main/java/org/warp/jcwdb/TypesManager.java
Normal file
22
src/main/java/org/warp/jcwdb/TypesManager.java
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
package org.warp.jcwdb;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Map.Entry;
|
||||||
|
import java.util.HashMap;
|
||||||
|
|
||||||
|
public class TypesManager {
|
||||||
|
private final Map<Integer, DBTypeParser<?>> types;
|
||||||
|
|
||||||
|
public TypesManager() {
|
||||||
|
types = new HashMap<>();
|
||||||
|
DBStandardTypes.registerStandardTypes(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
public <T> void registerType(int type, DBTypeParser<T> parser) {
|
||||||
|
this.types.put(type, parser);
|
||||||
|
}
|
||||||
|
|
||||||
|
public <T> DBTypeParser<T> get(int type) {
|
||||||
|
return types.get(type).cast();
|
||||||
|
}
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user