First commit

This commit is contained in:
Andrea Cavalli 2018-11-19 15:16:12 +01:00
parent 2025e3cc37
commit 8e37cfa4e0
15 changed files with 435 additions and 0 deletions

2
jcwdb.iml Normal file
View File

@ -0,0 +1,2 @@
<?xml version="1.0" encoding="UTF-8"?>
<module type="JAVA_MODULE" version="4" />

75
pom.xml Normal file
View File

@ -0,0 +1,75 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.warp</groupId>
<artifactId>jcwdb</artifactId>
<version>1.0-SNAPSHOT</version>
<name>jcwdb</name>
<!-- FIXME change it to the project's website -->
<url>http://www.example.com</url>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>11</maven.compiler.source>
<maven.compiler.target>11</maven.compiler.target>
</properties>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>it.unimi.dsi</groupId>
<artifactId>fastutil</artifactId>
<version>8.2.2</version>
</dependency>
<dependency>
<groupId>com.esotericsoftware</groupId>
<artifactId>kryo</artifactId>
<version>5.0.0-RC1</version>
</dependency>
</dependencies>
<build>
<pluginManagement><!-- lock down plugins versions to avoid using Maven defaults (may be moved to parent pom) -->
<plugins>
<plugin>
<artifactId>maven-clean-plugin</artifactId>
<version>3.0.0</version>
</plugin>
<!-- see http://maven.apache.org/ref/current/maven-core/default-bindings.html#Plugin_bindings_for_jar_packaging -->
<plugin>
<artifactId>maven-resources-plugin</artifactId>
<version>3.0.2</version>
</plugin>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.7.0</version>
</plugin>
<plugin>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.22.1</version>
</plugin>
<plugin>
<artifactId>maven-jar-plugin</artifactId>
<version>3.0.2</version>
</plugin>
<plugin>
<artifactId>maven-install-plugin</artifactId>
<version>2.5.2</version>
</plugin>
<plugin>
<artifactId>maven-deploy-plugin</artifactId>
<version>2.8.2</version>
</plugin>
</plugins>
</pluginManagement>
</build>
</project>

View File

@ -0,0 +1,13 @@
package org.warp;
/**
* Hello world!
*
*/
public class App
{
public static void main( String[] args )
{
System.out.println( "Hello World!" );
}
}

View File

@ -0,0 +1,29 @@
package org.warp.jcwdb;
import java.io.IOException;
public class CacheIndexManager implements IndexManager {
public CacheIndexManager() {
}
@Override
public <T> T get(long index, int type, DBReader<T> reader) {
return null;
}
@Override
public <T> void set(long index, int type, DBWriter<T> writer) {
}
@Override
public void delete(long index) {
}
@Override
public boolean has(long index) {
return false;
}
}

View File

@ -0,0 +1,7 @@
package org.warp.jcwdb;
import com.esotericsoftware.kryo.io.Input;
public interface DBReader<T> {
public T read(Input i);
}

View File

@ -0,0 +1,4 @@
package org.warp.jcwdb;
public interface DBTypeParser<T> extends DBReader<T>, DBWriter<T> {
}

View File

@ -0,0 +1,7 @@
package org.warp.jcwdb;
import com.esotericsoftware.kryo.io.Output;
public interface DBWriter<T> {
public void write(Output o);
}

View File

@ -0,0 +1,19 @@
package org.warp.jcwdb;
public abstract class EntryReference<T> {
private final JCWDatabase db;
private final long entryId;
private final DBTypeParser parser;
public T value;
public EntryReference(JCWDatabase db, long entryId, DBTypeParser<T> parser) {
this.db = db;
this.entryId = entryId;
this.parser = parser;
this.value = db.get(entryId, parser);
}
public void save() {
db.set(entryId, parser);
}
}

View File

@ -0,0 +1,92 @@
package org.warp.jcwdb;
import com.esotericsoftware.kryo.io.Output;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.nio.channels.Channels;
import java.nio.channels.SeekableByteChannel;
import java.util.*;
public class FileAllocator {
/**
* Edit this using editIndex()
*/
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
* @return new offset
*/
private long allocate(int size) {
return 0; // TODO: fare
}
private void editIndex(long index, long offset, int size, int type) {
editIndex(index, new IndexDetails(offset, size, type));
}
private void editIndex(long index, IndexDetails details) {
indicesOffset.put(index, details);
dirtyIndices.add(index);
}
}

View File

@ -0,0 +1,45 @@
package org.warp.jcwdb;
import com.esotericsoftware.kryo.io.Input;
import com.esotericsoftware.kryo.io.Output;
import java.io.IOException;
import java.nio.channels.Channels;
import java.nio.channels.SeekableByteChannel;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.StandardOpenOption;
public class FileIndexManager implements IndexManager {
private final SeekableByteChannel dataFileChannel, metadataFileChannel;
private final FileAllocator fileAllocator;
public FileIndexManager(Path dataFile, Path metadataFile) throws IOException {
dataFileChannel = Files.newByteChannel(dataFile, StandardOpenOption.CREATE);
metadataFileChannel = Files.newByteChannel(metadataFile, StandardOpenOption.CREATE);
fileAllocator = new FileAllocator(dataFileChannel);
}
@Override
public <T> T get(long l, int type, DBReader<T> r) {
Input i = new Input(Channels.newInputStream(dataFileChannel));
T result = r.read(i);
i.close();
return result;
}
@Override
public void set(long index, int type, DBWriter w) throws IOException {
fileAllocator.write(index, type, w);
}
@Override
public void delete(long index) {
}
@Override
public boolean has(long index) {
return false;
}
}

View File

@ -0,0 +1,58 @@
package org.warp.jcwdb;
import java.util.Objects;
public class IndexDetails {
private final long offset;
private final int size;
private final int type;
public IndexDetails(long offset, int size, int type) {
this.offset = offset;
this.size = size;
this.type = type;
}
public IndexDetails(IndexDetails indexDetails) {
this.offset = indexDetails.offset;
this.size = indexDetails.size;
this.type = indexDetails.type;
}
public long getOffset() {
return offset;
}
public int getSize() {
return size;
}
public int getType() {
return type;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
IndexDetails that = (IndexDetails) o;
return offset == that.offset &&
size == that.size &&
type == that.type;
}
@Override
public int hashCode() {
return Objects.hash(offset);
}
@Override
public String toString() {
return "IndexDetails{" +
"offset=" + offset +
", size=" + size +
", type=" + type +
'}';
}
}

View File

@ -0,0 +1,10 @@
package org.warp.jcwdb;
import java.io.IOException;
public interface IndexManager {
public <T> T get(long index, int type, DBReader<T> reader) throws IOException;
public <T> void set(long index, int type, DBWriter<T> writer) throws IOException;
public void delete(long index) throws IOException;
public boolean has(long index);
}

View File

@ -0,0 +1,15 @@
package org.warp.jcwdb;
import com.esotericsoftware.kryo.Kryo;
import java.io.IOException;
import java.nio.file.Path;
public class JCWDatabase {
private static final Kryo kryo = new Kryo();
private final MixedIndexDatabase indices;
public JCWDatabase(Path dataFile, Path metadataFile) throws IOException {
this.indices = new MixedIndexDatabase(dataFile, metadataFile);
}
}

View File

@ -0,0 +1,39 @@
package org.warp.jcwdb;
import it.unimi.dsi.fastutil.longs.Long2LongLinkedOpenHashMap;
import it.unimi.dsi.fastutil.longs.Long2LongMap;
import java.io.IOException;
import java.nio.file.Path;
public class MixedIndexDatabase implements IndexManager {
private final Long2LongMap mostAccessedIndices;
private final FileIndexManager fileIndices;
private final CacheIndexManager cacheIndices;
public MixedIndexDatabase(Path dataFile, Path metadataFile) throws IOException {
this.mostAccessedIndices = new Long2LongLinkedOpenHashMap();
this.fileIndices = new FileIndexManager(dataFile, metadataFile);
this.cacheIndices = new CacheIndexManager();
}
@Override
public <T> T get(long index, int type, DBReader<T> reader) {
return null;
}
@Override
public <T> void set(long index, int type, DBWriter<T> writer) {
}
@Override
public void delete(long index) {
}
@Override
public boolean has(long index) {
return false;
}
}

View File

@ -0,0 +1,20 @@
package org.warp;
import static org.junit.Assert.assertTrue;
import org.junit.Test;
/**
* Unit test for simple App.
*/
public class AppTest
{
/**
* Rigorous Test :-)
*/
@Test
public void shouldAnswerWithTrue()
{
assertTrue( true );
}
}