public void init() throws BabuDBException { // load persisted snapshots from disk for (Entry<String, DatabaseInternal> entry : dbs.getDatabaseManager().getDatabasesInternal().entrySet()) { final File snapDir = new File(dbs.getConfig().getBaseDir(), entry.getKey() + "/snapshots"); if (snapDir.exists()) { Map<String, Snapshot> snapMap = new HashMap<String, Snapshot>(); snapshotDBs.put(entry.getKey(), snapMap); boolean compressed = entry.getValue().getLSMDB().getIndex(0).isCompressed(); boolean mmaped = entry.getValue().getLSMDB().getIndex(0).isMMapEnabled(); String[] snapshots = snapDir.list(); for (String snapName : snapshots) { BabuDBView view = new DiskIndexView( snapDir + "/" + snapName, entry.getValue().getComparators(), compressed, mmaped); snapMap.put(snapName, new Snapshot(view, dbs)); } } } }
@Override public void deletePersistentSnapshot(String dbName, String snapshotName) throws BabuDBException { BabuDBRequestResultImpl<Object> result = new BabuDBRequestResultImpl<Object>(dbs.getResponseManager()); dbs.getTransactionManager() .makePersistent( dbs.getDatabaseManager().createTransaction().deleteSnapshot(dbName, snapshotName), result); result.get(); }
/* (non-Javadoc) * @see org.xtreemfs.babudb.api.SnapshotManager#createPersistentSnapshot(java.lang.String, org.xtreemfs.babudb.snapshots.SnapshotConfig) */ @Override public void createPersistentSnapshot(String dbName, SnapshotConfig snap) throws BabuDBException { // synchronously executing the request BabuDBRequestResultImpl<Object> result = new BabuDBRequestResultImpl<Object>(dbs.getResponseManager()); dbs.getTransactionManager() .makePersistent( dbs.getDatabaseManager().createTransaction().createSnapshot(dbName, snap), result); result.get(); }
/* (non-Javadoc) * @see org.xtreemfs.babudb.api.dev.SnapshotManagerInternal#getSnapshotDir(java.lang.String, * java.lang.String) */ @Override public String getSnapshotDir(String dbName, String snapshotName) { return dbs.getConfig().getBaseDir() + dbName + "/" + SnapshotManagerImpl.SNAP_DIR + "/" + (snapshotName == null ? "" : snapshotName); }
/* (non-Javadoc) * @see org.xtreemfs.babudb.api.dev.SnapshotManagerInternal#snapshotComplete(java.lang.String, * org.xtreemfs.babudb.snapshots.SnapshotConfig) */ @Override public void snapshotComplete(String dbName, SnapshotConfig snap) throws BabuDBException { // as soon as the snapshot has been completed, replace the entry in the // snapshot DB map with a disk index-based BabuDB instance if necessary synchronized (snapshotDBs) { DatabaseInternal db = dbs.getDatabaseManager().getDatabase(dbName); boolean compressed = db.getLSMDB().getIndex(0).isCompressed(); boolean mmaped = db.getLSMDB().getIndex(0).isMMapEnabled(); Snapshot s = snapshotDBs.get(dbName).get(snap.getName()); s.setView( new DiskIndexView( getSnapshotDir(dbName, snap.getName()), dbs.getDatabaseManager().getDatabase(dbName).getComparators(), compressed, mmaped)); } }
/* (non-Javadoc) * @see org.xtreemfs.babudb.api.dev.SnapshotManagerInternal#deleteAllSnapshots(java.lang.String) */ @Override public void deleteAllSnapshots(String dbName) throws BabuDBException { final Map<String, Snapshot> snapMap = snapshotDBs.get(dbName); if (snapMap != null) { for (Entry<String, Snapshot> snap : snapMap.entrySet()) { // shut down the view snap.getValue().shutdown(); // if a snapshot materialization request is currently in the // checkpointer queue, remove it dbs.getCheckpointer().removeSnapshotMaterializationRequest(dbName, snap.getKey()); } // remove the map entry snapshotDBs.remove(dbName); } FSUtils.delTree(new File(getSnapshotDir(dbName, null))); // no delete log entries for the snapshots are needed here, since the // method will only be invoked when the database itself is deleted }
/** Feed the transactionManager with the knowledge on how to handle snapshot related requests. */ private void initializeTransactionManager() { dbs.getTransactionManager() .registerInMemoryProcessing( Operation.TYPE_CREATE_SNAP, new InMemoryProcessing() { @Override public Object[] deserializeRequest(ReusableBuffer serialized) throws BabuDBException { ObjectInputStream oin = null; try { oin = new ObjectInputStream(new ByteArrayInputStream(serialized.array())); int dbId = oin.readInt(); SnapshotConfig snap = (SnapshotConfig) oin.readObject(); return new Object[] {dbId, snap}; } catch (Exception e) { throw new BabuDBException( ErrorCode.IO_ERROR, "Could not deserialize operation of type " + Operation.TYPE_CREATE_SNAP + ", because: " + e.getMessage(), e); } finally { try { serialized.flip(); if (oin != null) oin.close(); } catch (IOException ioe) { /* who cares? */ } } } @Override public OperationInternal convertToOperation(Object[] args) { return new BabuDBTransaction.BabuDBOperation( Operation.TYPE_CREATE_SNAP, (String) null, new Object[] {args[0], args[1]}); } @Override public Object process(OperationInternal operation) throws BabuDBException { Object[] args = operation.getParams(); // parse args int dbId = (Integer) args[0]; SnapshotConfig snap = (SnapshotConfig) args[1]; // complete arguments if (dbId == InsertRecordGroup.DB_ID_UNKNOWN && operation.getDatabaseName() != null) { dbId = dbs.getDatabaseManager() .getDatabase(operation.getDatabaseName()) .getLSMDB() .getDatabaseId(); operation.updateParams(new Object[] {dbId, snap}); } else if (operation.getDatabaseName() == null) { operation.updateDatabaseName( dbs.getDatabaseManager().getDatabase(dbId).getName()); } Map<String, Snapshot> snapMap = snapshotDBs.get(operation.getDatabaseName()); if (snapMap == null) { snapMap = new HashMap<String, Snapshot>(); snapshotDBs.put(operation.getDatabaseName(), snapMap); } // if the snapshot already exists ... if (snapMap.containsKey(snap.getName())) { throw new BabuDBException( ErrorCode.SNAP_EXISTS, "snapshot '" + snap.getName() + "' already exists"); } snapMap.put(snap.getName(), new Snapshot(null, dbs)); // first, create new in-memory snapshots of all indices int[] snapIds = null; try { dbs.getTransactionManager().lockService(); // create the snapshot snapIds = dbs.getDatabaseManager() .getDatabase(dbId) .getLSMDB() .createSnapshot(snap.getIndices()); } catch (InterruptedException e) { throw new BabuDBException(ErrorCode.INTERRUPTED, e.getMessage()); } finally { dbs.getTransactionManager().unlockService(); } // then, enqueue a snapshot materialization request in the // checkpointer's queue dbs.getCheckpointer() .addSnapshotMaterializationRequest(operation.getDatabaseName(), snapIds, snap); // as long as the snapshot has not been persisted yet, add a view on // the current snapshot in the original database to the snapshot DB map synchronized (snapshotDBs) { Snapshot s = snapMap.get(snap.getName()); if (s.getView() == null) { s.setView(new InMemoryView(dbs, operation.getDatabaseName(), snap, snapIds)); } } return null; } }); dbs.getTransactionManager() .registerInMemoryProcessing( Operation.TYPE_DELETE_SNAP, new InMemoryProcessing() { @Override public Object[] deserializeRequest(ReusableBuffer serialized) throws BabuDBException { byte[] payload = serialized.array(); int offs = payload[0]; String dbName = new String(payload, 1, offs); String snapName = new String(payload, offs + 1, payload.length - offs - 1); serialized.flip(); return new Object[] {dbName, snapName}; } @Override public OperationInternal convertToOperation(Object[] args) { return new BabuDBTransaction.BabuDBOperation( Operation.TYPE_DELETE_SNAP, (String) args[0], new Object[] {args[1]}); } @Override public Object process(OperationInternal operation) throws BabuDBException { // parse args String snapshotName = (String) operation.getParams()[0]; final Map<String, Snapshot> snapMap = snapshotDBs.get(operation.getDatabaseName()); if (snapMap == null) { throw new BabuDBException( ErrorCode.NO_SUCH_SNAPSHOT, "snapshot '" + snapshotName + "' does not exist"); } final Snapshot snap = snapMap.get(snapshotName); // if the snapshot does not exist ... if (snap == null) { throw new BabuDBException( ErrorCode.NO_SUCH_SNAPSHOT, "snapshot '" + snapshotName + "' does not exist"); } // shut down and remove the view snap.getView().shutdown(); snapMap.remove(snapshotName); // if a snapshot materialization request is currently in the // checkpointer queue, remove it dbs.getCheckpointer() .removeSnapshotMaterializationRequest( operation.getDatabaseName(), snapshotName); // delete the snapshot subdirectory on disk if available FSUtils.delTree( new File(getSnapshotDir(operation.getDatabaseName(), snapshotName))); return null; } }); }