package de.hub.emffrag.datastore;
import java.io.InputStream;
import java.math.BigInteger;
import com.google.common.cache.Cache;
import com.google.common.cache.CacheBuilder;
import com.google.common.cache.RemovalCause;
import com.google.common.cache.RemovalListener;
import com.google.common.cache.RemovalNotification;
import de.hub.emffrag.datastore.IScanExtension.ICursor;
public class ScanningDataStore extends AbstractDelegatingDataStore implements RemovalListener<BigInteger, ICursor> {
private final IScanExtension scanExtension;
private final Cache<BigInteger, ICursor> cachedScanCursors = CacheBuilder.newBuilder().maximumSize(100).removalListener(this).build();
public ScanningDataStore(IBaseDataStore baseDataStore, IScanExtension scanExtension) {
super(baseDataStore);
this.scanExtension = scanExtension;
}
@Override
public void onRemoval(RemovalNotification<BigInteger, ICursor> notification) {
if (notification.getCause() == RemovalCause.SIZE) {
notification.getValue().close();
}
}
@Override
public final InputStream openInputStream(byte[] key) {
BigInteger keyAsBigInteger = new BigInteger(key);
ICursor cursor = cachedScanCursors.getIfPresent(keyAsBigInteger);
InputStream is = null;
if (cursor == null) {
cursor = scanExtension.cursor(key);
if (cursor == null || !cursor.hasNext()) {
return null;
}
BigInteger firstScannerKey = new BigInteger(cursor.next());
if (firstScannerKey.equals(keyAsBigInteger)) {
is = cursor.openNextInputStream();
}
} else {
cachedScanCursors.invalidate(keyAsBigInteger);
is = cursor.openNextInputStream();
}
if (cursor.hasNext()) {
cachedScanCursors.put(new BigInteger(cursor.next()), cursor);
}
return is;
}
}