package org.deephacks.confit.internal.berkeley; import com.google.common.base.Optional; import com.sleepycat.je.DatabaseEntry; import com.sleepycat.je.Environment; import com.sleepycat.je.ForeignKeyDeleteAction; import com.sleepycat.je.SecondaryConfig; import com.sleepycat.je.SecondaryDatabase; import com.sleepycat.je.SecondaryKeyCreator; import com.sleepycat.je.Transaction; import org.deephacks.confit.internal.berkeley.BerkeleyBeanManager.FastKeyComparator; import org.deephacks.confit.internal.berkeley.TxDatabase.ForEachKey; import org.deephacks.confit.model.BeanId; import org.deephacks.confit.model.BeanId.BinaryBeanId; import org.deephacks.confit.model.Schema; import org.deephacks.confit.serialization.UniqueIds; import org.deephacks.confit.serialization.ValueSerialization; import org.deephacks.confit.serialization.ValueSerialization.ValueReader; import org.deephacks.confit.spi.SchemaManager; import java.util.ArrayList; import java.util.Collection; import static org.deephacks.confit.internal.berkeley.BerkeleyBeanManager.BERKELEY_DB_REFERENCES; public class BerkeleyDb { private final TxDatabase db; private final SecondaryDatabase secondaryDatabase; private static final ThreadLocal<Transaction> TX = new ThreadLocal<>(); public BerkeleyDb(TxDatabase db) { this.db = db; SecondaryConfig secondaryConfig = new SecondaryConfig(); secondaryConfig.setAllowCreate(true); secondaryConfig.setTransactional(true); secondaryConfig.setKeyPrefixing(true); secondaryConfig.setBtreeComparator(new FastKeyComparator()); secondaryConfig.setForeignKeyDeleteAction(ForeignKeyDeleteAction.ABORT); secondaryConfig.setKeyCreator(new KeyCreator()); secondaryDatabase = db.getEnv().openSecondaryDatabase(null, BERKELEY_DB_REFERENCES, db.getDb(), secondaryConfig); } public Environment getEnv() { return db.getEnv(); } public boolean put(byte[] key, byte[] value) { return db.put(key, value); } public Optional<byte[]> get(byte[] key) { return db.get(key); } public void list(final String schemaName, final ForEachBean forEach) { byte[] min = BinaryBeanId.getMinId(schemaName).getKey(); byte[] max = BinaryBeanId.getMaxId(schemaName).getKey(); db.list(min, max, new ForEachKey() { @Override public boolean match(byte[] key, byte[] data) { return forEach.match(BeanId.create(key), data); } }); } public void commit() { db.commit(); } public void abort() { db.abort(); } public static interface ForEachBean { public boolean match(BeanId id, byte[] data); } public static class KeyCreator implements SecondaryKeyCreator { public static SchemaManager schemaManager = SchemaManager.lookup(); private final ValueSerialization serialization; private static final UniqueIds uniqueIds = UniqueIds.lookup(); public KeyCreator() { this.serialization = new ValueSerialization(); } @Override public boolean createSecondaryKey(SecondaryDatabase secondary, DatabaseEntry key, DatabaseEntry data, DatabaseEntry result) { BeanId beanId = BeanId.read(key.getData()); Schema schema = schemaManager.getSchema(beanId.getSchemaName()); ValueReader reader = new ValueReader(data.getData()); for (String referenceName : schema.getReferenceNames()) { long refId = uniqueIds.getSchemaId(referenceName); Object value = reader.getValue((int) refId); if (value != null) { ArrayList<String> values = new ArrayList<>(); if (value instanceof Collection) { values.addAll((Collection<String>) value); } else { values.add(value.toString()); } System.out.println(value); } } System.out.println(beanId + " " + schema); System.out.println(key + " " + data); return false; } } }