204 lines
5.2 KiB
Java
204 lines
5.2 KiB
Java
package it.cavallium.strangedb.java.objects.lists;
|
|
|
|
import it.cavallium.strangedb.VariableWrapper;
|
|
import it.cavallium.strangedb.functionalinterfaces.ConsumerWithIO;
|
|
import it.unimi.dsi.fastutil.longs.LongArrayList;
|
|
import it.cavallium.strangedb.java.objects.EnhancedObject;
|
|
import it.cavallium.strangedb.java.database.IDatabaseTools;
|
|
|
|
import java.io.IOError;
|
|
import java.io.IOException;
|
|
import java.util.StringJoiner;
|
|
import java.util.concurrent.*;
|
|
import java.util.concurrent.locks.ReentrantReadWriteLock;
|
|
import java.util.function.Consumer;
|
|
|
|
public abstract class StrangeDbList<T> extends EnhancedObject implements ElementsList<T> {
|
|
|
|
private final ReentrantReadWriteLock readWriteLock = new ReentrantReadWriteLock(false);
|
|
|
|
protected abstract LongArrayList getIndices();
|
|
|
|
public StrangeDbList() {
|
|
|
|
}
|
|
|
|
public StrangeDbList(IDatabaseTools databaseTools) throws IOException {
|
|
super(databaseTools);
|
|
}
|
|
|
|
@Override
|
|
public T get(int index) throws IOException {
|
|
readWriteLock.readLock().lock();
|
|
try {
|
|
long uid = getIndices().getLong(index);
|
|
return loadItem(uid);
|
|
} finally {
|
|
readWriteLock.readLock().unlock();
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public void add(T value) throws IOException {
|
|
long uid = databaseTools.getObjectsIO().newNullObject();
|
|
readWriteLock.writeLock().lock();
|
|
try {
|
|
getIndices().add(uid);
|
|
writeItemToDisk(uid, value);
|
|
} finally {
|
|
readWriteLock.writeLock().unlock();
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public void forEachParallelUnsorted(ConsumerWithIO<T> action) throws IOException {
|
|
readWriteLock.readLock().lock();
|
|
try {
|
|
forEachParallelUnsorted_(action);
|
|
} finally {
|
|
readWriteLock.readLock().unlock();
|
|
}
|
|
}
|
|
|
|
protected void forEachParallelUnsorted_(ConsumerWithIO<T> action) throws IOException {
|
|
try {
|
|
int size = size();
|
|
ExecutorService executorService = Executors.newFixedThreadPool(ForkJoinPool.getCommonPoolParallelism(), (r) -> new Thread(r, "DBList parallel foreach"));
|
|
VariableWrapper<IOException> exceptionVariableWrapper = new VariableWrapper<>(null);
|
|
for (int i = 0; i < size; i++) {
|
|
final int index = i;
|
|
executorService.execute(() -> {
|
|
try {
|
|
T t = get(index);
|
|
action.accept(t);
|
|
} catch (IOException e) {
|
|
if (exceptionVariableWrapper.var == null) exceptionVariableWrapper.var = e;
|
|
}
|
|
});
|
|
}
|
|
executorService.shutdown();
|
|
executorService.awaitTermination(Long.MAX_VALUE, TimeUnit.DAYS);
|
|
if (exceptionVariableWrapper.var != null) {
|
|
throw exceptionVariableWrapper.var;
|
|
}
|
|
executorService.shutdownNow();
|
|
} catch (InterruptedException e) {
|
|
throw new IOException(e);
|
|
} catch (CompletionException e) {
|
|
throw new IOException(e.getCause());
|
|
}
|
|
}
|
|
|
|
public void forEachIndexParallelUnsorted(ConsumerWithIO<Long> action) throws IOException {
|
|
readWriteLock.readLock().lock();
|
|
try {
|
|
forEachIndexParallelUnsorted_(action);
|
|
} finally {
|
|
readWriteLock.readLock().unlock();
|
|
}
|
|
}
|
|
|
|
protected void forEachIndexParallelUnsorted_(ConsumerWithIO<Long> action) throws IOException {
|
|
try {
|
|
this.getIndices().parallelStream().forEach((id) -> {
|
|
try {
|
|
action.accept(id);
|
|
} catch (IOException e) {
|
|
throw new CompletionException(e);
|
|
}
|
|
});
|
|
} catch (CompletionException ex) {
|
|
throw new IOException(ex.getCause());
|
|
}
|
|
}
|
|
|
|
public void forEach(ConsumerWithIO<T> action) throws IOException {
|
|
readWriteLock.readLock().lock();
|
|
try {
|
|
forEach_(action);
|
|
} finally {
|
|
readWriteLock.readLock().unlock();
|
|
}
|
|
}
|
|
|
|
protected void forEach_(ConsumerWithIO<T> action) throws IOException {
|
|
int size = size();
|
|
for (int i = 0; i < size; i++) {
|
|
final int index = i;
|
|
T value = get(index);
|
|
action.accept(value);
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public void update(int index, T value) throws IOException {
|
|
set(index, value);
|
|
}
|
|
|
|
@Override
|
|
public void set(int index, T value) throws IOException {
|
|
long uid = databaseTools.getObjectsIO().newNullObject();
|
|
readWriteLock.writeLock().lock();
|
|
try {
|
|
getIndices().set(index, uid);
|
|
writeItemToDisk(uid, value);
|
|
} finally {
|
|
readWriteLock.writeLock().unlock();
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public void add(int index, T value) throws IOException {
|
|
long uid = databaseTools.getObjectsIO().newNullObject();
|
|
readWriteLock.writeLock().lock();
|
|
try {
|
|
getIndices().add(index, uid);
|
|
writeItemToDisk(uid, value);
|
|
} finally {
|
|
readWriteLock.writeLock().unlock();
|
|
}
|
|
}
|
|
|
|
public T getLast() throws IOException {
|
|
readWriteLock.readLock().lock();
|
|
try {
|
|
if (getIndices().size() > 0) {
|
|
return get(getIndices().size() - 1);
|
|
} else {
|
|
return null;
|
|
}
|
|
} finally {
|
|
readWriteLock.readLock().unlock();
|
|
}
|
|
}
|
|
|
|
public boolean isEmpty() {
|
|
readWriteLock.readLock().lock();
|
|
try {
|
|
return getIndices().size() <= 0;
|
|
} finally {
|
|
readWriteLock.readLock().unlock();
|
|
}
|
|
}
|
|
|
|
public int size() {
|
|
readWriteLock.readLock().lock();
|
|
try {
|
|
return getIndices().size();
|
|
} finally {
|
|
readWriteLock.readLock().unlock();
|
|
}
|
|
}
|
|
|
|
protected abstract T loadItem(long uid) throws IOException;
|
|
|
|
protected abstract void writeItemToDisk(long uid, T item) throws IOException;
|
|
|
|
@Override
|
|
public String toString() {
|
|
return new StringJoiner(", ", StrangeDbList.class.getSimpleName() + "[", "]")
|
|
.add(getIndices().size() + " items")
|
|
.toString();
|
|
}
|
|
}
|