/* * Concept profile generation tool suite * Copyright (C) 2015 Biosemantics Group, Erasmus University Medical Center, * Rotterdam, The Netherlands * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as published * by the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see <http://www.gnu.org/licenses/> */ package org.erasmusmc.databases.integersetstore; import java.io.File; import java.util.Collection; import java.util.Comparator; import java.util.Iterator; import java.util.Map; import java.util.regex.Matcher; import java.util.regex.Pattern; import org.erasmusmc.collections.SortedIntListSet; import org.erasmusmc.storecaching.StoreMapCaching; import com.sleepycat.bind.EntryBinding; import com.sleepycat.bind.tuple.TupleBinding; import com.sleepycat.je.Cursor; import com.sleepycat.je.Database; import com.sleepycat.je.DatabaseConfig; import com.sleepycat.je.DatabaseEntry; import com.sleepycat.je.DatabaseException; import com.sleepycat.je.DatabaseStats; import com.sleepycat.je.Environment; import com.sleepycat.je.EnvironmentConfig; import com.sleepycat.je.LockMode; import com.sleepycat.je.OperationStatus; public class IntegerSetStore extends StoreMapCaching<Integer, SortedIntListSet> { protected String databaseName = "IntegerSetStore"; protected EnvironmentConfig environmentConfig; protected Environment environment; protected DatabaseConfig databaseConfig; protected Database integerToSetOfIntegersStore; protected EntryBinding myIntegerBinding; protected EntryBinding myDataBinding; protected IntegerSetStoreShutdown sh; public IntegerSetStore(String foldername){ File file = new File(foldername); if (!file.exists()) file.mkdir(); init(file); } public IntegerSetStore(File datadir) { init(datadir); } private void init(File datadir){ try { environmentConfig = new EnvironmentConfig(); environmentConfig.setAllowCreate(true); environmentConfig.setTransactional(true); environmentConfig.setCacheSize(30240000); environment = new Environment(datadir, environmentConfig); databaseConfig = new DatabaseConfig(); databaseConfig.setAllowCreate(true); databaseConfig.setTransactional(true); openDB(); myIntegerBinding = TupleBinding.getPrimitiveBinding(Integer.class); myDataBinding = new IntegerToSetOfIntegersBinding(); sh = new IntegerSetStoreShutdown(); sh.g = this; Runtime.getRuntime().addShutdownHook(sh); } catch (DatabaseException e) { e.printStackTrace(); } } public void openDB() { try { this.integerToSetOfIntegersStore = environment.openDatabase(null, this.databaseName, this.databaseConfig); // environment.removeDatabase(null,this.dbName); } catch (DatabaseException e) { // TODO Auto-generated catch block e.printStackTrace(); } } @Override public int size() { int size = 0; try { DatabaseStats stats = integerToSetOfIntegersStore.getStats(null); Pattern p = Pattern.compile("numLeafNodes=([0-9]+)"); Matcher m = p.matcher(stats.toString()); if (m.find()) { size = Integer.parseInt(m.group(1)); } } catch (DatabaseException e) { // TODO Auto-generated catch block e.printStackTrace(); } return size; } public Iterator<Integer2IntegerSet> iterator() { return new DBIterator(); } private void closeDatabase() { try { if (integerToSetOfIntegersStore != null) { integerToSetOfIntegersStore.close(); } if (environment != null) { environment.cleanLog(); // Clean the log before closing environment.close(); } } catch (DatabaseException e) { e.printStackTrace(); } } public void close(){ closeDatabase(); Runtime.getRuntime().removeShutdownHook(sh); } protected void finalize() { close(); } public static Comparator<Integer> getAscendingIntegerComparator() { return new Comparator<Integer>() { public int compare(Integer arg0, Integer arg1) { return arg0 - arg1; } }; } @Override protected void setEntryInStore(Integer id, SortedIntListSet value) { try { DatabaseEntry databaseKey = new DatabaseEntry(); myIntegerBinding.objectToEntry(id, databaseKey); DatabaseEntry databaseValue = new DatabaseEntry(); myDataBinding.objectToEntry(value, databaseValue); integerToSetOfIntegersStore.put(null, databaseKey, databaseValue); } catch (DatabaseException e) { e.printStackTrace(); } } @Override protected Map<Integer, SortedIntListSet> getEntriesFromStoreWithIDs(Collection<Integer> ids) { // TODO Auto-generated method stub return null; } @Override protected SortedIntListSet getEntryFromStoreWithID(Integer id) { SortedIntListSet result = null; try { DatabaseEntry databaseKey = new DatabaseEntry(); DatabaseEntry databaseValue = new DatabaseEntry(); myIntegerBinding.objectToEntry(id, databaseKey); integerToSetOfIntegersStore.get(null, databaseKey, databaseValue, LockMode.DEFAULT); if (databaseValue.getSize() != 0) { result = (SortedIntListSet) myDataBinding.entryToObject(databaseValue); } } catch (DatabaseException e) { e.printStackTrace(); } return result; } protected class DBIterator implements Iterator<Integer2IntegerSet> { Cursor myCursor; DatabaseEntry foundKey = new DatabaseEntry(); DatabaseEntry foundData = new DatabaseEntry(); Integer2IntegerSet next = null; Boolean nextHasBeenRetrieved = false; public DBIterator() { try { myCursor = integerToSetOfIntegersStore.openCursor(null, null); } catch (DatabaseException e) { e.printStackTrace(); } } public boolean hasNext() { Boolean result = false; if (myCursor != null) { try { if (!nextHasBeenRetrieved) { if (myCursor.getNext(foundKey, foundData, LockMode.DEFAULT) == OperationStatus.SUCCESS) { Integer key = (Integer) myIntegerBinding.entryToObject(foundKey); SortedIntListSet set = (SortedIntListSet) myDataBinding.entryToObject(foundData); next = new Integer2IntegerSet(key, set); nextHasBeenRetrieved = true; result = true; } else { nextHasBeenRetrieved = true; next = null; myCursor.close(); } } else { result = true; } } catch (DatabaseException e) { e.printStackTrace(); } } return result; } public Integer2IntegerSet next() { Integer2IntegerSet result = null; if (myCursor != null) { if (nextHasBeenRetrieved) { result = next; } else { try { if (myCursor.getNext(foundKey, foundData, LockMode.DEFAULT) == OperationStatus.SUCCESS) { Integer key = (Integer) myIntegerBinding.entryToObject(foundKey); SortedIntListSet set = (SortedIntListSet) myDataBinding.entryToObject(foundData); result = new Integer2IntegerSet(key, set); } } catch (DatabaseException e) { e.printStackTrace(); } } } nextHasBeenRetrieved = false; return result; } public void remove() { // not implemented System.out.println("Remove is not implemented for ConceptToConceptVectorIndexIterator iterator!"); } } protected class IntegerSetStoreShutdown extends Thread { public IntegerSetStore g; public void run() { g.closeDatabase(); } } }