Implemented indexOf
This commit is contained in:
parent
9db950fe1c
commit
bcbcc6f294
5
pom.xml
5
pom.xml
@ -35,6 +35,11 @@
|
|||||||
<artifactId>kryo</artifactId>
|
<artifactId>kryo</artifactId>
|
||||||
<version>5.0.0-RC1</version>
|
<version>5.0.0-RC1</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>net.openhft</groupId>
|
||||||
|
<artifactId>zero-allocation-hashing</artifactId>
|
||||||
|
<version>0.8</version>
|
||||||
|
</dependency>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
|
||||||
<build>
|
<build>
|
||||||
|
@ -45,4 +45,10 @@ public class CacheIndexManager implements IndexManager {
|
|||||||
public void close() {
|
public void close() {
|
||||||
// TODO: implement
|
// TODO: implement
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public long clean() {
|
||||||
|
// TODO Auto-generated method stub
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -3,9 +3,10 @@ package org.warp.jcwdb;
|
|||||||
public interface DBDataOutput<T> {
|
public interface DBDataOutput<T> {
|
||||||
int getSize();
|
int getSize();
|
||||||
int getType();
|
int getType();
|
||||||
|
long calculateHash();
|
||||||
DBWriter<T> getWriter();
|
DBWriter<T> getWriter();
|
||||||
|
|
||||||
static <T> DBDataOutput<T> create(DBWriter<T> writer, int type, int size) {
|
static <T> DBDataOutput<T> create(DBWriter<T> writer, int type, int size, long hash) {
|
||||||
return new DBDataOutput<T>() {
|
return new DBDataOutput<T>() {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -17,6 +18,11 @@ public interface DBDataOutput<T> {
|
|||||||
public int getType() {
|
public int getType() {
|
||||||
return type;
|
return type;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public long calculateHash() {
|
||||||
|
return hash;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public DBWriter<T> getWriter() {
|
public DBWriter<T> getWriter() {
|
||||||
|
@ -5,7 +5,10 @@ import java.io.ByteArrayOutputStream;
|
|||||||
import com.esotericsoftware.kryo.Kryo;
|
import com.esotericsoftware.kryo.Kryo;
|
||||||
import com.esotericsoftware.kryo.io.Output;
|
import com.esotericsoftware.kryo.io.Output;
|
||||||
|
|
||||||
|
import net.openhft.hashing.LongHashFunction;
|
||||||
|
|
||||||
public class DBGenericObjectParser extends DBTypeParserImpl<Object> {
|
public class DBGenericObjectParser extends DBTypeParserImpl<Object> {
|
||||||
|
private static final LongHashFunction hashFunction = net.openhft.hashing.LongHashFunction.xx();
|
||||||
private static final Kryo kryo = new Kryo();
|
private static final Kryo kryo = new Kryo();
|
||||||
static {
|
static {
|
||||||
kryo.setRegistrationRequired(false);
|
kryo.setRegistrationRequired(false);
|
||||||
@ -25,9 +28,22 @@ public class DBGenericObjectParser extends DBTypeParserImpl<Object> {
|
|||||||
kryo.writeClassAndObject(tmpO, value);
|
kryo.writeClassAndObject(tmpO, value);
|
||||||
tmpO.flush();
|
tmpO.flush();
|
||||||
final byte[] bytes = baos.toByteArray();
|
final byte[] bytes = baos.toByteArray();
|
||||||
|
final long hash = hashFunction.hashBytes(bytes);
|
||||||
tmpO.close();
|
tmpO.close();
|
||||||
return DBDataOutput.create((o) -> {
|
return DBDataOutput.create((o) -> {
|
||||||
o.write(bytes);
|
o.write(bytes);
|
||||||
}, DBStandardTypes.GENERIC_OBJECT, bytes.length);
|
}, DBStandardTypes.GENERIC_OBJECT, bytes.length, hash);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public long calculateHash(Object value) {
|
||||||
|
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||||
|
Output tmpO = new Output(baos);
|
||||||
|
kryo.writeClassAndObject(tmpO, value);
|
||||||
|
tmpO.flush();
|
||||||
|
final byte[] bytes = baos.toByteArray();
|
||||||
|
final long hash = hashFunction.hashBytes(bytes);
|
||||||
|
tmpO.close();
|
||||||
|
return hash;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,6 +2,8 @@ package org.warp.jcwdb;
|
|||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
|
||||||
|
import it.unimi.dsi.fastutil.longs.LongArrayList;
|
||||||
|
|
||||||
public class DBLightListParser extends DBTypeParserImpl<LightList> {
|
public class DBLightListParser extends DBTypeParserImpl<LightList> {
|
||||||
private final JCWDatabase db;
|
private final JCWDatabase db;
|
||||||
|
|
||||||
@ -11,23 +13,33 @@ public class DBLightListParser extends DBTypeParserImpl<LightList> {
|
|||||||
|
|
||||||
public DBReader<LightList> getReader() {
|
public DBReader<LightList> getReader() {
|
||||||
return (i, size) -> {
|
return (i, size) -> {
|
||||||
ArrayList<Long> internalList = new ArrayList<>();
|
LongArrayList internalList = new LongArrayList();
|
||||||
long max = size / Long.BYTES;
|
LongArrayList hashes = new LongArrayList();
|
||||||
|
long max = size / (Long.BYTES * 2);
|
||||||
for (int item = 0; item < max; item++){
|
for (int item = 0; item < max; item++){
|
||||||
long itm = i.readLong();
|
long itm = i.readLong();
|
||||||
|
long hash = i.readLong();
|
||||||
internalList.add(itm);
|
internalList.add(itm);
|
||||||
|
hashes.add(hash);
|
||||||
}
|
}
|
||||||
return new LightList(db, internalList);
|
return new LightList(db, internalList, hashes);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
public DBDataOutput<LightList> getWriter(final LightList value) {
|
public DBDataOutput<LightList> getWriter(final LightList value) {
|
||||||
final int elementsCount = value.internalList.size();
|
final int elementsCount = value.size();
|
||||||
return DBDataOutput.create((o) -> {
|
return DBDataOutput.create((o) -> {
|
||||||
ArrayList<Long> list = value.internalList;
|
LongArrayList list = value.internalList;
|
||||||
for (Long item : list) {
|
LongArrayList hashes = value.hashes;
|
||||||
o.writeLong(item);
|
for (int i = 0; i < elementsCount; i++) {
|
||||||
|
o.writeLong(list.getLong(i));
|
||||||
|
o.writeLong(hashes.getLong(i));
|
||||||
}
|
}
|
||||||
}, DBStandardTypes.LIGHT_LIST, elementsCount * Long.BYTES);
|
}, DBStandardTypes.LIGHT_LIST, elementsCount * Long.BYTES * 2, calculateHash(value));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public long calculateHash(LightList value) {
|
||||||
|
return value.hashCodeLong();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,12 +1,13 @@
|
|||||||
package org.warp.jcwdb;
|
package org.warp.jcwdb;
|
||||||
|
|
||||||
import java.io.ByteArrayOutputStream;
|
import java.nio.charset.StandardCharsets;
|
||||||
|
|
||||||
import com.esotericsoftware.kryo.io.Output;
|
import net.openhft.hashing.LongHashFunction;
|
||||||
|
|
||||||
public class DBStringParser extends DBTypeParserImpl<String> {
|
public class DBStringParser extends DBTypeParserImpl<String> {
|
||||||
|
private static final LongHashFunction hashFunction = net.openhft.hashing.LongHashFunction.xx();
|
||||||
private static final DBReader<String> defaultReader = (i, size) -> {
|
private static final DBReader<String> defaultReader = (i, size) -> {
|
||||||
return i.readString();
|
return new String(i.readBytes(size), StandardCharsets.UTF_16LE);
|
||||||
};
|
};
|
||||||
|
|
||||||
public DBReader<String> getReader() {
|
public DBReader<String> getReader() {
|
||||||
@ -14,14 +15,13 @@ public class DBStringParser extends DBTypeParserImpl<String> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public DBDataOutput<String> getWriter(final String value) {
|
public DBDataOutput<String> getWriter(final String value) {
|
||||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
|
||||||
Output tmpO = new Output(baos);
|
|
||||||
tmpO.writeString(value);
|
|
||||||
tmpO.flush();
|
|
||||||
final byte[] bytes = baos.toByteArray();
|
|
||||||
tmpO.close();
|
|
||||||
return DBDataOutput.create((o) -> {
|
return DBDataOutput.create((o) -> {
|
||||||
o.write(bytes);
|
o.write(value.getBytes(StandardCharsets.UTF_16LE));
|
||||||
}, DBStandardTypes.STRING, bytes.length);
|
}, DBStandardTypes.STRING, value.length() * 2, calculateHash(value));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public long calculateHash(String value) {
|
||||||
|
return hashFunction.hashBytes(value.getBytes(StandardCharsets.UTF_16LE));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3,4 +3,5 @@ package org.warp.jcwdb;
|
|||||||
public interface DBTypeParser<T> extends Castable {
|
public interface DBTypeParser<T> extends Castable {
|
||||||
DBReader<T> getReader();
|
DBReader<T> getReader();
|
||||||
DBDataOutput<T> getWriter(final T value);
|
DBDataOutput<T> getWriter(final T value);
|
||||||
|
long calculateHash(final T value);
|
||||||
}
|
}
|
||||||
|
@ -18,7 +18,7 @@ public class EntryReference<T> implements Castable, AutoCloseable {
|
|||||||
this.db = db;
|
this.db = db;
|
||||||
this.entryIndex = entryId;
|
this.entryIndex = entryId;
|
||||||
this.parser = parser;
|
this.parser = parser;
|
||||||
this.value = db.indices.get(entryId, parser.getReader());
|
this.value = db.getIndexManager().get(entryId, parser.getReader());
|
||||||
}
|
}
|
||||||
|
|
||||||
public EntryReference(JCWDatabase db, long entryId, DBTypeParser<T> parser, T value) {
|
public EntryReference(JCWDatabase db, long entryId, DBTypeParser<T> parser, T value) {
|
||||||
@ -35,10 +35,18 @@ public class EntryReference<T> implements Castable, AutoCloseable {
|
|||||||
public long getIndex() {
|
public long getIndex() {
|
||||||
return entryIndex;
|
return entryIndex;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public long calculateHash() {
|
||||||
|
return parser.calculateHash(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Note that this method won't be called when closing without saving
|
||||||
|
* @throws IOException
|
||||||
|
*/
|
||||||
public void save() throws IOException {
|
public void save() throws IOException {
|
||||||
if (!closed) {
|
if (!closed) {
|
||||||
db.indices.set(entryIndex, parser.getWriter(value));
|
db.getIndexManager().set(entryIndex, parser.getWriter(value));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -57,8 +65,23 @@ public class EntryReference<T> implements Castable, AutoCloseable {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
db.removeEntryReference(entryIndex);
|
|
||||||
save();
|
save();
|
||||||
|
db.removeEntryReference(entryIndex);
|
||||||
|
|
||||||
|
closed = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void closeWithoutSaving() {
|
||||||
|
if (closed) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
synchronized (closeLock) {
|
||||||
|
if (closed) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
db.removeEntryReference(entryIndex);
|
||||||
|
|
||||||
closed = true;
|
closed = true;
|
||||||
}
|
}
|
||||||
|
@ -78,11 +78,11 @@ public class FileIndexManager implements IndexManager {
|
|||||||
public <T> void set(long index, DBDataOutput<T> data) throws IOException {
|
public <T> void set(long index, DBDataOutput<T> data) throws IOException {
|
||||||
checkClosed();
|
checkClosed();
|
||||||
final IndexDetails indexDetails = getIndexMetadataUnsafe(index);
|
final IndexDetails indexDetails = getIndexMetadataUnsafe(index);
|
||||||
if (indexDetails == null || indexDetails.getSize() < data.getSize()) {
|
if (indexDetails == null || indexDetails.getSize() != data.getSize()) { // TODO: should be indexDetails.getSize() < data.getSize(). Need to create a method to mark memory free if the size is bigger than the needed, instead of allocating a new space.
|
||||||
allocateAndWrite(index, data);
|
allocateAndWrite(index, data);
|
||||||
} else {
|
} else {
|
||||||
if (indexDetails.getSize() > data.getSize()) {
|
if (indexDetails.getSize() > data.getSize()) {
|
||||||
editIndex(index, indexDetails.getOffset(), data.getSize(), indexDetails.getType());
|
editIndex(index, indexDetails.getOffset(), data.getSize(), indexDetails.getType(), data.calculateHash());
|
||||||
fileAllocator.markFree(indexDetails.getOffset()+data.getSize(), data.getSize());
|
fileAllocator.markFree(indexDetails.getOffset()+data.getSize(), data.getSize());
|
||||||
}
|
}
|
||||||
writeExact(indexDetails, data);
|
writeExact(indexDetails, data);
|
||||||
@ -95,7 +95,8 @@ public class FileIndexManager implements IndexManager {
|
|||||||
final int size = data.getSize();
|
final int size = data.getSize();
|
||||||
final long offset = fileAllocator.allocate(size);
|
final long offset = fileAllocator.allocate(size);
|
||||||
final int type = data.getType();
|
final int type = data.getType();
|
||||||
final IndexDetails indexDetails = new IndexDetails(offset, size, type);
|
final long hash = data.calculateHash();
|
||||||
|
final IndexDetails indexDetails = new IndexDetails(offset, size, type, hash);
|
||||||
final long index = createIndexMetadata(indexDetails);
|
final long index = createIndexMetadata(indexDetails);
|
||||||
writeExact(indexDetails, data);
|
writeExact(indexDetails, data);
|
||||||
return index;
|
return index;
|
||||||
@ -123,8 +124,9 @@ public class FileIndexManager implements IndexManager {
|
|||||||
private void allocateAndWrite(final long index, DBDataOutput<?> w) throws IOException {
|
private void allocateAndWrite(final long index, DBDataOutput<?> w) throws IOException {
|
||||||
final int size = w.getSize();
|
final int size = w.getSize();
|
||||||
final int type = w.getType();
|
final int type = w.getType();
|
||||||
|
final long hash = w.calculateHash();
|
||||||
final long offset = fileAllocator.allocate(size);
|
final long offset = fileAllocator.allocate(size);
|
||||||
IndexDetails details = editIndex(index, offset, size, type);
|
IndexDetails details = editIndex(index, offset, size, type, hash);
|
||||||
writeExact(details, w);
|
writeExact(details, w);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -181,8 +183,8 @@ public class FileIndexManager implements IndexManager {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private IndexDetails editIndex(long index, long offset, int size, int type) {
|
private IndexDetails editIndex(long index, long offset, int size, int type, long hash) {
|
||||||
IndexDetails indexDetails = new IndexDetails(offset, size, type);
|
IndexDetails indexDetails = new IndexDetails(offset, size, type, hash);
|
||||||
editIndex(index, indexDetails);
|
editIndex(index, indexDetails);
|
||||||
return indexDetails;
|
return indexDetails;
|
||||||
}
|
}
|
||||||
@ -226,9 +228,13 @@ public class FileIndexManager implements IndexManager {
|
|||||||
// If it's not deleted continue
|
// If it's not deleted continue
|
||||||
if ((metadataByteBuffer.getInt() & IndexDetails.MASK_DELETED) == 0) {
|
if ((metadataByteBuffer.getInt() & IndexDetails.MASK_DELETED) == 0) {
|
||||||
final long offset = metadataByteBuffer.getLong();
|
final long offset = metadataByteBuffer.getLong();
|
||||||
|
// final long sizeAndType = metadataByteBuffer.getLong();
|
||||||
|
// final int size = (int)(sizeAndType >> 32);
|
||||||
|
// final int type = (int)sizeAndType;
|
||||||
final int size = metadataByteBuffer.getInt();
|
final int size = metadataByteBuffer.getInt();
|
||||||
final int type = metadataByteBuffer.getInt();
|
final int type = metadataByteBuffer.getInt();
|
||||||
final IndexDetails indexDetails = new IndexDetails(offset, size, type);
|
final long hash = metadataByteBuffer.getLong();
|
||||||
|
final IndexDetails indexDetails = new IndexDetails(offset, size, type, hash);
|
||||||
editIndex(index, indexDetails);
|
editIndex(index, indexDetails);
|
||||||
return indexDetails;
|
return indexDetails;
|
||||||
}
|
}
|
||||||
@ -284,11 +290,17 @@ public class FileIndexManager implements IndexManager {
|
|||||||
|
|
||||||
private void writeIndexDetails(SeekableByteChannel position, IndexDetails indexDetails) throws IOException {
|
private void writeIndexDetails(SeekableByteChannel position, IndexDetails indexDetails) throws IOException {
|
||||||
synchronized (metadataByteBufferLock) {
|
synchronized (metadataByteBufferLock) {
|
||||||
|
final int size = indexDetails.getSize();
|
||||||
|
final int type = indexDetails.getType();
|
||||||
|
final long offset = indexDetails.getOffset();
|
||||||
|
final long hash = indexDetails.getHash();
|
||||||
metadataByteBuffer.rewind();
|
metadataByteBuffer.rewind();
|
||||||
metadataByteBuffer.putInt(0);
|
metadataByteBuffer.putInt(0);
|
||||||
metadataByteBuffer.putLong(indexDetails.getOffset());
|
metadataByteBuffer.putLong(offset);
|
||||||
metadataByteBuffer.putInt(indexDetails.getSize());
|
metadataByteBuffer.putInt(size);
|
||||||
metadataByteBuffer.putInt(indexDetails.getType());
|
metadataByteBuffer.putInt(type);
|
||||||
|
//metadataByteBuffer.putLong((long)size << 32 | type & 0xFFFFFFFFL);
|
||||||
|
metadataByteBuffer.putLong(hash);
|
||||||
metadataByteBuffer.rewind();
|
metadataByteBuffer.rewind();
|
||||||
position.write(metadataByteBuffer);
|
position.write(metadataByteBuffer);
|
||||||
}
|
}
|
||||||
|
@ -10,22 +10,26 @@ public class IndexDetails {
|
|||||||
public static final int OFFSET_BYTES = Long.BYTES;
|
public static final int OFFSET_BYTES = Long.BYTES;
|
||||||
public static final int DATA_SIZE_BYTES = Integer.BYTES;
|
public static final int DATA_SIZE_BYTES = Integer.BYTES;
|
||||||
public static final int TYPE_BYTES = Integer.BYTES;
|
public static final int TYPE_BYTES = Integer.BYTES;
|
||||||
public static final int TOTAL_BYTES = BITMASK_SIZE + OFFSET_BYTES + DATA_SIZE_BYTES + TYPE_BYTES;
|
public static final int HASH_BYTES = Long.BYTES;
|
||||||
|
public static final int TOTAL_BYTES = BITMASK_SIZE + OFFSET_BYTES + DATA_SIZE_BYTES + TYPE_BYTES + HASH_BYTES;
|
||||||
public static final int MASK_DELETED = 0b00000001;
|
public static final int MASK_DELETED = 0b00000001;
|
||||||
private final long offset;
|
private final long offset;
|
||||||
private final int size;
|
private final int size;
|
||||||
private final int type;
|
private final int type;
|
||||||
|
private final long hash;
|
||||||
|
|
||||||
public IndexDetails(long offset, int size, int type) {
|
public IndexDetails(long offset, int size, int type, long hash) {
|
||||||
this.offset = offset;
|
this.offset = offset;
|
||||||
this.size = size;
|
this.size = size;
|
||||||
this.type = type;
|
this.type = type;
|
||||||
|
this.hash = hash;
|
||||||
}
|
}
|
||||||
|
|
||||||
public IndexDetails(IndexDetails indexDetails) {
|
public IndexDetails(IndexDetails indexDetails) {
|
||||||
this.offset = indexDetails.offset;
|
this.offset = indexDetails.offset;
|
||||||
this.size = indexDetails.size;
|
this.size = indexDetails.size;
|
||||||
this.type = indexDetails.type;
|
this.type = indexDetails.type;
|
||||||
|
this.hash = indexDetails.hash;
|
||||||
}
|
}
|
||||||
|
|
||||||
public long getOffset() {
|
public long getOffset() {
|
||||||
@ -39,29 +43,46 @@ public class IndexDetails {
|
|||||||
public int getType() {
|
public int getType() {
|
||||||
return type;
|
return type;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
public long getHash() {
|
||||||
public boolean equals(Object o) {
|
return hash;
|
||||||
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
|
@Override
|
||||||
public int hashCode() {
|
public int hashCode() {
|
||||||
return Objects.hash(offset);
|
final int prime = 31;
|
||||||
|
int result = 1;
|
||||||
|
result = prime * result + (int) (hash ^ (hash >>> 32));
|
||||||
|
result = prime * result + (int) (offset ^ (offset >>> 32));
|
||||||
|
result = prime * result + size;
|
||||||
|
result = prime * result + type;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object obj) {
|
||||||
|
if (this == obj)
|
||||||
|
return true;
|
||||||
|
if (obj == null)
|
||||||
|
return false;
|
||||||
|
if (getClass() != obj.getClass())
|
||||||
|
return false;
|
||||||
|
IndexDetails other = (IndexDetails) obj;
|
||||||
|
if (hash != other.hash)
|
||||||
|
return false;
|
||||||
|
if (offset != other.offset)
|
||||||
|
return false;
|
||||||
|
if (size != other.size)
|
||||||
|
return false;
|
||||||
|
if (type != other.type)
|
||||||
|
return false;
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return "IndexDetails{" +
|
return "IndexDetails [offset=" + offset + ", size=" + size + ", type=" + type + ", hash=" + hash + "]";
|
||||||
"offset=" + offset +
|
|
||||||
", size=" + size +
|
|
||||||
", type=" + type +
|
|
||||||
'}';
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -8,6 +8,8 @@ import java.util.ArrayList;
|
|||||||
import it.unimi.dsi.fastutil.longs.Long2ObjectLinkedOpenHashMap;
|
import it.unimi.dsi.fastutil.longs.Long2ObjectLinkedOpenHashMap;
|
||||||
import it.unimi.dsi.fastutil.longs.Long2ObjectMap;
|
import it.unimi.dsi.fastutil.longs.Long2ObjectMap;
|
||||||
import it.unimi.dsi.fastutil.longs.Long2ObjectMap.Entry;
|
import it.unimi.dsi.fastutil.longs.Long2ObjectMap.Entry;
|
||||||
|
import it.unimi.dsi.fastutil.longs.LongArrayList;
|
||||||
|
import it.unimi.dsi.fastutil.objects.ObjectIterator;
|
||||||
|
|
||||||
public class JCWDatabase implements AutoCloseable, Cleanable {
|
public class JCWDatabase implements AutoCloseable, Cleanable {
|
||||||
public final static long MAX_LOADED_REFERENCES = 10;
|
public final static long MAX_LOADED_REFERENCES = 10;
|
||||||
@ -39,11 +41,15 @@ public class JCWDatabase implements AutoCloseable, Cleanable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public <T> EntryReference<LightList<T>> getRoot() throws IOException {
|
public <T> EntryReference<LightList<T>> getRoot() throws IOException {
|
||||||
|
return getRoot(Object.class).cast();
|
||||||
|
}
|
||||||
|
|
||||||
|
public <T> EntryReference<LightList<T>> getRoot(Class<T> clazz) throws IOException {
|
||||||
checkClosed();
|
checkClosed();
|
||||||
if (exists(0)) {
|
if (exists(0)) {
|
||||||
return get(0);
|
return get(0);
|
||||||
} else {
|
} else {
|
||||||
LightList<T> newRoot = new LightList<T>(this, new ArrayList<>());
|
LightList<T> newRoot = new LightList<T>(this, new LongArrayList(), new LongArrayList());
|
||||||
return set(0, newRoot);
|
return set(0, newRoot);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -130,7 +136,9 @@ public class JCWDatabase implements AutoCloseable, Cleanable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
synchronized (referencesAccessLock) {
|
synchronized (referencesAccessLock) {
|
||||||
for (WeakReference<EntryReference<?>> referenceRef : references.values()) {
|
ObjectIterator<WeakReference<EntryReference<?>>> it = references.values().iterator();
|
||||||
|
while (it.hasNext()) {
|
||||||
|
WeakReference<EntryReference<?>> referenceRef = it.next();
|
||||||
EntryReference<?> reference = referenceRef.get();
|
EntryReference<?> reference = referenceRef.get();
|
||||||
if (reference != null) {
|
if (reference != null) {
|
||||||
reference.close();
|
reference.close();
|
||||||
@ -187,4 +195,17 @@ public class JCWDatabase implements AutoCloseable, Cleanable {
|
|||||||
}
|
}
|
||||||
return removedReferences;
|
return removedReferences;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
protected <T> long calculateHash(T o) {
|
||||||
|
return ((DBTypeParser<T>) typesManager.get(o.getClass())).calculateHash(o);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @return indexManager
|
||||||
|
*/
|
||||||
|
public IndexManager getIndexManager() {
|
||||||
|
return indices;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,14 +2,20 @@ package org.warp.jcwdb;
|
|||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
import java.util.function.Predicate;
|
||||||
|
|
||||||
|
import it.unimi.dsi.fastutil.longs.LongArrayList;
|
||||||
|
import it.unimi.dsi.fastutil.objects.ObjectArrayList;
|
||||||
|
|
||||||
public class LightList<T> implements List<T> {
|
public class LightList<T> implements List<T> {
|
||||||
|
|
||||||
public final ArrayList<Long> internalList;
|
public final LongArrayList internalList;
|
||||||
|
public final LongArrayList hashes;
|
||||||
private final transient JCWDatabase db;
|
private final transient JCWDatabase db;
|
||||||
|
|
||||||
public LightList(JCWDatabase db, ArrayList<Long> internalList) {
|
public LightList(JCWDatabase db, LongArrayList internalList, LongArrayList hashes) {
|
||||||
this.internalList = internalList;
|
this.internalList = internalList;
|
||||||
|
this.hashes = hashes;
|
||||||
this.db = db;
|
this.db = db;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -27,8 +33,9 @@ public class LightList<T> implements List<T> {
|
|||||||
public boolean contains(Object o) {
|
public boolean contains(Object o) {
|
||||||
if (o != null) {
|
if (o != null) {
|
||||||
for (Long element : internalList) {
|
for (Long element : internalList) {
|
||||||
|
EntryReference<T> ref = null;
|
||||||
try {
|
try {
|
||||||
EntryReference<T> ref = db.get(element);
|
ref = db.get(element);
|
||||||
if (o.equals(ref.value)) {
|
if (o.equals(ref.value)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -40,6 +47,7 @@ public class LightList<T> implements List<T> {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
@Override
|
@Override
|
||||||
public Iterator<T> iterator() {
|
public Iterator<T> iterator() {
|
||||||
final ArrayList<T> elements = new ArrayList<>();
|
final ArrayList<T> elements = new ArrayList<>();
|
||||||
@ -53,12 +61,13 @@ public class LightList<T> implements List<T> {
|
|||||||
return elements.iterator();
|
return elements.iterator();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
@Override
|
@Override
|
||||||
public T[] toArray() {
|
public T[] toArray() {
|
||||||
final T[] elements = (T[]) new Objects[internalList.size()];
|
final T[] elements = (T[]) new Objects[internalList.size()];
|
||||||
for (int i = 0; i < elements.length; i++) {
|
for (int i = 0; i < elements.length; i++) {
|
||||||
try {
|
try {
|
||||||
elements[i] = (T) db.get(internalList.get(i)).value;
|
elements[i] = (T) db.get(internalList.getLong(i)).value;
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
@ -66,12 +75,13 @@ public class LightList<T> implements List<T> {
|
|||||||
return elements;
|
return elements;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
@Override
|
@Override
|
||||||
public <T1> T1[] toArray(T1[] a) {
|
public <T1> T1[] toArray(T1[] a) {
|
||||||
final T1[] elements = (T1[]) new Objects[internalList.size()];
|
final T1[] elements = (T1[]) new Objects[internalList.size()];
|
||||||
for (int i = 0; i < elements.length; i++) {
|
for (int i = 0; i < elements.length; i++) {
|
||||||
try {
|
try {
|
||||||
elements[i] = (T1) db.get(internalList.get(i)).value;
|
elements[i] = (T1) db.get(internalList.getLong(i)).value;
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
@ -81,117 +91,284 @@ public class LightList<T> implements List<T> {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean add(T o) {
|
public boolean add(T o) {
|
||||||
EntryReference<T> ref;
|
EntryReference<T> ref = addEntry(o);
|
||||||
try {
|
return ref != null;
|
||||||
ref = db.add(o);
|
}
|
||||||
} catch (IOException e) {
|
|
||||||
throw (NullPointerException) new NullPointerException().initCause(e);
|
public EntryReference<T> addEntry(T o) {
|
||||||
|
EntryReference<T> ref = addToDatabase(o);
|
||||||
|
if (internalList.add(ref.getIndex())) {
|
||||||
|
hashes.add(ref.getParser().calculateHash(ref.value));
|
||||||
|
} else {
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
return internalList.add(ref.getIndex());
|
return ref;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean remove(Object o) {
|
public boolean remove(Object o) {
|
||||||
EntryReference<T> ref;
|
int removeIndex = indexOf(o);
|
||||||
try {
|
if (removeIndex >= 0) {
|
||||||
ref = db.add((T) o);
|
internalList.removeLong(removeIndex);
|
||||||
} catch (IOException e) {
|
hashes.removeLong(removeIndex);
|
||||||
throw (NullPointerException) new NullPointerException().initCause(e);
|
return true;
|
||||||
}
|
}
|
||||||
return internalList.remove(ref.getIndex());
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean remove(EntryReference<T> ref) {
|
||||||
|
int removeIndex = indexOfEntry(ref);
|
||||||
|
if (removeIndex >= 0) {
|
||||||
|
internalList.removeLong(removeIndex);
|
||||||
|
hashes.removeLong(removeIndex);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean containsAll(Collection<?> c) {
|
public boolean containsAll(Collection<?> c) {
|
||||||
// TODO: implement
|
for (Object o : c) {
|
||||||
return false;
|
int objIndex = indexOf(o);
|
||||||
|
if (objIndex < 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
@Override
|
@Override
|
||||||
public boolean addAll(Collection<? extends T> c) {
|
public boolean addAll(Collection<? extends T> c) {
|
||||||
// TODO: implement
|
boolean result = false;
|
||||||
return false;
|
for (Object o : c) {
|
||||||
|
result |= add((T) o);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
@Override
|
@Override
|
||||||
public boolean addAll(int index, Collection<? extends T> c) {
|
public boolean addAll(int index, Collection<? extends T> c) {
|
||||||
// TODO: implement
|
boolean result = false;
|
||||||
return false;
|
int delta = 0;
|
||||||
|
for (Object o : c) {
|
||||||
|
add(index + delta, (T) o);
|
||||||
|
result = true;
|
||||||
|
delta++;
|
||||||
|
}
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
@Override
|
@Override
|
||||||
public boolean removeAll(Collection<?> c) {
|
public boolean removeAll(Collection<?> c) {
|
||||||
// TODO: implement
|
boolean result = false;
|
||||||
return false;
|
for (Object o : c) {
|
||||||
|
result |= remove((T) o);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean retainAll(Collection<?> c) {
|
public boolean retainAll(Collection<?> c) {
|
||||||
// TODO: implement
|
boolean result = false;
|
||||||
return false;
|
LongArrayList collectionHashes = new LongArrayList();
|
||||||
|
ObjectArrayList<Object> collection = new ObjectArrayList<>();
|
||||||
|
collection.addAll(c);
|
||||||
|
for (Object o : c) {
|
||||||
|
collectionHashes.add(db.calculateHash(o));
|
||||||
|
}
|
||||||
|
for (int i = 0; i < internalList.size(); i++) {
|
||||||
|
long hash = internalList.getLong(i);
|
||||||
|
int positionInCollection = collectionHashes.indexOf(hash);
|
||||||
|
if (positionInCollection == -1) {
|
||||||
|
remove(collection.get(positionInCollection));
|
||||||
|
result = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void clear() {
|
public void clear() {
|
||||||
// TODO: implement
|
internalList.clear();
|
||||||
|
hashes.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
@Override
|
@Override
|
||||||
public T get(int index) {
|
public T get(int index) {
|
||||||
try {
|
try {
|
||||||
return (T) db.get(internalList.get(index)).value;
|
return (T) db.get(internalList.getLong(index)).value;
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
@Override
|
@Override
|
||||||
public T set(int index, T element) {
|
public T set(int index, T element) {
|
||||||
// TODO: implement
|
EntryReference<T> ref = addToDatabase(element);
|
||||||
return null;
|
long oldIndex = internalList.set(index, ref.getIndex());
|
||||||
|
hashes.set(index, ref.calculateHash());
|
||||||
|
try {
|
||||||
|
ref.close();
|
||||||
|
return ((EntryReference<T>) (db.get(oldIndex))).value;
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw (NullPointerException) new NullPointerException().initCause(e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void add(int index, T element) {
|
public void add(int index, T element) {
|
||||||
// TODO: implement
|
EntryReference<T> ref = addToDatabase(element);
|
||||||
|
internalList.add(index, ref.getIndex());
|
||||||
|
hashes.add(index, ref.getParser().calculateHash(ref.value));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
@Override
|
@Override
|
||||||
public T remove(int index) {
|
public T remove(int index) {
|
||||||
// TODO: implement
|
long oldIndex = internalList.removeLong(index);
|
||||||
return null;
|
hashes.removeLong(index);
|
||||||
|
try {
|
||||||
|
return ((EntryReference<T>) (db.get(oldIndex))).value;
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw (NullPointerException) new NullPointerException().initCause(e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int indexOf(Object o) {
|
public int indexOf(Object o) {
|
||||||
// TODO: implement
|
EntryReference<?> ref = addToDatabase(o);
|
||||||
return 0;
|
long objToRemoveHash = ref.calculateHash();
|
||||||
|
|
||||||
|
for (int i = 0; i < hashes.size(); i++) {
|
||||||
|
long hash = hashes.getLong(i);
|
||||||
|
if (objToRemoveHash == hash) {
|
||||||
|
try {
|
||||||
|
if (ref.equals(db.get(internalList.getLong(i)))) {
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw (NullPointerException) new NullPointerException().initCause(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int indexOfEntry(EntryReference<T> ref) {
|
||||||
|
long objToRemoveHash = ref.calculateHash();
|
||||||
|
|
||||||
|
for (int i = 0; i < hashes.size(); i++) {
|
||||||
|
long hash = hashes.getLong(i);
|
||||||
|
if (objToRemoveHash == hash) {
|
||||||
|
try {
|
||||||
|
if (ref.equals(db.get(internalList.getLong(i)))) {
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw (NullPointerException) new NullPointerException().initCause(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int lastIndexOf(Object o) {
|
public int lastIndexOf(Object o) {
|
||||||
// TODO: implement
|
EntryReference<?> ref = addToDatabase(o);
|
||||||
return 0;
|
long objToRemoveHash = ref.calculateHash();
|
||||||
|
|
||||||
|
int lastValue = -1;
|
||||||
|
|
||||||
|
for (int i = 0; i < hashes.size(); i++) {
|
||||||
|
long hash = hashes.getLong(i);
|
||||||
|
if (objToRemoveHash == hash) {
|
||||||
|
try {
|
||||||
|
if (ref.equals(db.get(internalList.getLong(i)))) {
|
||||||
|
lastValue = i;
|
||||||
|
}
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw (NullPointerException) new NullPointerException().initCause(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return lastValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Deprecated
|
||||||
@Override
|
@Override
|
||||||
public ListIterator<T> listIterator() {
|
public ListIterator<T> listIterator() {
|
||||||
// TODO: implement
|
// TODO: implement
|
||||||
return null;
|
throw new RuntimeException("Not implemented!");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Deprecated
|
||||||
@Override
|
@Override
|
||||||
public ListIterator<T> listIterator(int index) {
|
public ListIterator<T> listIterator(int index) {
|
||||||
// TODO: implement
|
// TODO: implement
|
||||||
return null;
|
throw new RuntimeException("Not implemented!");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Deprecated
|
||||||
@Override
|
@Override
|
||||||
public List<T> subList(int fromIndex, int toIndex) {
|
public List<T> subList(int fromIndex, int toIndex) {
|
||||||
// TODO: implement
|
// TODO: implement
|
||||||
return null;
|
throw new RuntimeException("Not implemented!");
|
||||||
|
}
|
||||||
|
|
||||||
|
private <U> EntryReference<U> addToDatabase(U obj) {
|
||||||
|
EntryReference<U> ref;
|
||||||
|
try {
|
||||||
|
ref = db.add(obj);
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw (NullPointerException) new NullPointerException().initCause(e);
|
||||||
|
}
|
||||||
|
return ref;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Deprecated
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
final int prime = 31;
|
||||||
|
int result = 1;
|
||||||
|
result = prime * result + ((hashes == null) ? 0 : hashes.hashCode());
|
||||||
|
result = prime * result + ((internalList == null) ? 0 : internalList.hashCode());
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public long hashCodeLong() {
|
||||||
|
final int prime = 31;
|
||||||
|
int result1 = prime + ((hashes == null) ? 0 : hashes.hashCode());
|
||||||
|
int result2 = prime + ((internalList == null) ? 0 : internalList.hashCode());
|
||||||
|
long result = (((long) result1) << 32) | (result2 & 0xffffffffL);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
@Override
|
||||||
|
public boolean removeIf(Predicate<? super T> filter) {
|
||||||
|
Objects.requireNonNull(filter);
|
||||||
|
boolean removed = false;
|
||||||
|
for (int i = 0; i < internalList.size(); ) {
|
||||||
|
T obj;
|
||||||
|
try {
|
||||||
|
obj = ((EntryReference<T>) (db.get(internalList.getLong(i)).cast())).value;
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw (NullPointerException) new NullPointerException().initCause(e);
|
||||||
|
}
|
||||||
|
if (filter.test(obj)) {
|
||||||
|
internalList.removeLong(i);
|
||||||
|
hashes.removeLong(i);
|
||||||
|
removed = true;
|
||||||
|
} else {
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return removed;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
9
src/main/java/org/warp/jcwdb/exampleimpl/Animal.java
Normal file
9
src/main/java/org/warp/jcwdb/exampleimpl/Animal.java
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
package org.warp.jcwdb.exampleimpl;
|
||||||
|
|
||||||
|
public abstract class Animal {
|
||||||
|
protected int legsCount;
|
||||||
|
|
||||||
|
public static boolean hasFourLegs(Animal a) {
|
||||||
|
return a.legsCount == 4;
|
||||||
|
}
|
||||||
|
}
|
@ -4,8 +4,12 @@ import org.warp.jcwdb.EntryReference;
|
|||||||
import org.warp.jcwdb.JCWDatabase;
|
import org.warp.jcwdb.JCWDatabase;
|
||||||
import org.warp.jcwdb.LightList;
|
import org.warp.jcwdb.LightList;
|
||||||
|
|
||||||
|
import it.unimi.dsi.fastutil.objects.ObjectArrayList;
|
||||||
|
import it.unimi.dsi.fastutil.objects.ObjectList;
|
||||||
|
|
||||||
import java.nio.file.Files;
|
import java.nio.file.Files;
|
||||||
import java.nio.file.Paths;
|
import java.nio.file.Paths;
|
||||||
|
import java.util.function.Predicate;
|
||||||
|
|
||||||
public class App {
|
public class App {
|
||||||
public static void main(String[] args) throws Exception {
|
public static void main(String[] args) throws Exception {
|
||||||
@ -19,29 +23,55 @@ public class App {
|
|||||||
long time01 = System.currentTimeMillis();
|
long time01 = System.currentTimeMillis();
|
||||||
System.out.println("Time elapsed: " + (time01 - time0));
|
System.out.println("Time elapsed: " + (time01 - time0));
|
||||||
System.out.println("Loading root...");
|
System.out.println("Loading root...");
|
||||||
LightList<String> root = ((EntryReference<LightList<String>>) db.getRoot().cast()).value;
|
EntryReference<LightList<Animal>> rootRef = db.getRoot(Animal.class);
|
||||||
|
LightList<Animal> root = rootRef.value;
|
||||||
long time1 = System.currentTimeMillis();
|
long time1 = System.currentTimeMillis();
|
||||||
System.out.println("Time elapsed: " + (time1 - time01));
|
System.out.println("Time elapsed: " + (time1 - time01));
|
||||||
|
System.out.println("Root size: " + root.size());
|
||||||
System.out.println("Root:");
|
System.out.println("Root:");
|
||||||
// for (int i = 0; i < root.size(); i++) {
|
// for (int i = 0; i < root.size(); i++) {
|
||||||
// System.out.println(" - " + root.get(i));
|
// System.out.println(" - " + root.get(i));
|
||||||
// }
|
// }
|
||||||
long prectime = System.currentTimeMillis();
|
long prectime = System.currentTimeMillis();
|
||||||
for (int i = 0; i < 2/*2000000*/; i++) {
|
for (int i = 0; i < 2000000000/* 2000000 */; i++) {
|
||||||
root.add("Test " + i);
|
Animal animal = new StrangeAnimal(i % 40);
|
||||||
|
root.add(animal);
|
||||||
if (i > 0 && i % 200000 == 0) {
|
if (i > 0 && i % 200000 == 0) {
|
||||||
long precprectime = prectime;
|
long precprectime = prectime;
|
||||||
prectime = System.currentTimeMillis();
|
prectime = System.currentTimeMillis();
|
||||||
System.out.println("Element "+i + " ("+(prectime-precprectime)+"ms)");
|
System.out.println("Element " + i + " (" + (prectime - precprectime) + "ms)");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
long time2 = System.currentTimeMillis();
|
long time2 = System.currentTimeMillis();
|
||||||
System.out.println("Root size: "+root.size());
|
System.out.println("Root size: " + root.size());
|
||||||
System.out.println("Time elapsed: " + (time2 - time1));
|
System.out.println("Time elapsed: " + (time2 - time1));
|
||||||
System.out.println("Used memory: " + ((Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory()) / 1024 / 1024) + "MB");
|
System.out.println("Used memory: "
|
||||||
|
+ ((Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory()) / 1024 / 1024) + "MB");
|
||||||
|
long time2_0 = System.currentTimeMillis();
|
||||||
|
System.out.println("Filtering strings...");
|
||||||
|
//root.removeIf(Animal::hasFourLegs);
|
||||||
|
long time2_1 = System.currentTimeMillis();
|
||||||
|
System.out.println("Time elapsed: " + (time2_1 - time2_0));
|
||||||
|
ObjectList<Animal> results = new ObjectArrayList<>();
|
||||||
|
|
||||||
|
root.forEach((value) -> {
|
||||||
|
if (Animal.hasFourLegs(value)) {
|
||||||
|
results.add(value);
|
||||||
|
}
|
||||||
|
//System.out.println("val:" + value);
|
||||||
|
});
|
||||||
|
long time2_2 = System.currentTimeMillis();
|
||||||
|
System.out.println("Time elapsed: " + (time2_2 - time2_1));
|
||||||
|
System.out.println("Used memory: "
|
||||||
|
+ ((Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory()) / 1024 / 1024) + "MB");
|
||||||
System.out.println("Saving database...");
|
System.out.println("Saving database...");
|
||||||
|
System.out.println("Root size: " + root.size());
|
||||||
db.close();
|
db.close();
|
||||||
long time3 = System.currentTimeMillis();
|
long time3 = System.currentTimeMillis();
|
||||||
System.out.println("Time elapsed: " + (time3 - time2));
|
System.out.println("Time elapsed: " + (time3 - time2_2));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static <T> Predicate<T> not(Predicate<T> t) {
|
||||||
|
return t.negate();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
12
src/main/java/org/warp/jcwdb/exampleimpl/Cat.java
Normal file
12
src/main/java/org/warp/jcwdb/exampleimpl/Cat.java
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
package org.warp.jcwdb.exampleimpl;
|
||||||
|
|
||||||
|
public class Cat extends Animal {
|
||||||
|
public Cat() {
|
||||||
|
this.legsCount = 12;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "Cat [legsCount=" + legsCount + "]";
|
||||||
|
}
|
||||||
|
}
|
12
src/main/java/org/warp/jcwdb/exampleimpl/Dog.java
Normal file
12
src/main/java/org/warp/jcwdb/exampleimpl/Dog.java
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
package org.warp.jcwdb.exampleimpl;
|
||||||
|
|
||||||
|
public class Dog extends Animal {
|
||||||
|
public Dog() {
|
||||||
|
this.legsCount = 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "Dog [legsCount=" + legsCount + "]";
|
||||||
|
}
|
||||||
|
}
|
15
src/main/java/org/warp/jcwdb/exampleimpl/StrangeAnimal.java
Normal file
15
src/main/java/org/warp/jcwdb/exampleimpl/StrangeAnimal.java
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
package org.warp.jcwdb.exampleimpl;
|
||||||
|
|
||||||
|
public class StrangeAnimal extends Animal {
|
||||||
|
public StrangeAnimal() {
|
||||||
|
super();
|
||||||
|
}
|
||||||
|
public StrangeAnimal(int legs) {
|
||||||
|
super();
|
||||||
|
this.legsCount = legs;
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "StrangeAnimal [legsCount=" + legsCount + "]";
|
||||||
|
}
|
||||||
|
}
|
@ -115,31 +115,4 @@ public class AppTest
|
|||||||
Files.delete(path);
|
Files.delete(path);
|
||||||
Files.delete(idx);
|
Files.delete(idx);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @throws IOException
|
|
||||||
*/
|
|
||||||
@Test
|
|
||||||
public void shouldActAsAnArrayListWithDifferentObjects() throws IOException
|
|
||||||
{
|
|
||||||
Path path = Files.createTempFile("", ".db"), idx = Files.createTempFile("", ".idx");
|
|
||||||
JCWDatabase db = new JCWDatabase(path, idx);
|
|
||||||
EntryReference<LightList<String>> ref = db.getRoot();
|
|
||||||
LightList<String> list1 = ref.value;
|
|
||||||
ArrayList<String> list2 = new ArrayList<String>();
|
|
||||||
for (int i = 0; i < 10; i++) {
|
|
||||||
String s = String.valueOf(i);
|
|
||||||
list1.add(s);
|
|
||||||
list2.add(s);
|
|
||||||
}
|
|
||||||
assertTrue(list1.size() == list2.size());
|
|
||||||
for (int i = 0; i < 10; i++) {
|
|
||||||
assertTrue(list1.get(i) == list2.get(i));
|
|
||||||
assertTrue(list2.get(i) == list1.get(i));
|
|
||||||
}
|
|
||||||
db.close();
|
|
||||||
Files.delete(path);
|
|
||||||
Files.delete(idx);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user