/** 5) Release the snapshot object for RocksDB and clean up. */ public void releaseSnapshotResources(boolean canceled) { if (null != kvStateIterators) { for (Tuple2<RocksIterator, Integer> kvStateIterator : kvStateIterators) { kvStateIterator.f0.close(); } kvStateIterators = null; } if (null != snapshot) { if (null != stateBackend.db) { stateBackend.db.releaseSnapshot(snapshot); } snapshot.close(); snapshot = null; } if (null != readOptions) { readOptions.close(); readOptions = null; } if (canceled) { try { if (null != snapshotResultStateHandle) { snapshotResultStateHandle.discardState(); } } catch (Exception ignored) { LOG.warn("Exception occurred during snapshot state handle cleanup: " + ignored); } } }
private void writeKVStateMetaData() throws IOException, InterruptedException { // write number of k/v states outputView.writeInt(stateBackend.kvStateInformation.size()); int kvStateId = 0; // iterate all column families, where each column family holds one k/v state, to write the // metadata for (Map.Entry<String, Tuple2<ColumnFamilyHandle, StateDescriptor<?, ?>>> column : stateBackend.kvStateInformation.entrySet()) { // be cooperative and check for interruption from time to time in the hot loop checkInterrupted(); // write StateDescriptor for this k/v state InstantiationUtil.serializeObject(outStream, column.getValue().f1); // retrieve iterator for this k/v states readOptions = new ReadOptions(); readOptions.setSnapshot(snapshot); RocksIterator iterator = stateBackend.db.newIterator(column.getValue().f0, readOptions); kvStateIterators.add(new Tuple2<>(iterator, kvStateId)); ++kvStateId; } }
@Test public void snapshots() throws RocksDBException { RocksDB db = null; Options options = null; ReadOptions readOptions = null; try { options = new Options(); options.setCreateIfMissing(true); db = RocksDB.open(options, dbFolder.getRoot().getAbsolutePath()); db.put("key".getBytes(), "value".getBytes()); // Get new Snapshot of database Snapshot snapshot = db.getSnapshot(); readOptions = new ReadOptions(); // set snapshot in ReadOptions readOptions.setSnapshot(snapshot); // retrieve key value pair assertThat(new String(db.get("key".getBytes()))).isEqualTo("value"); // retrieve key value pair created before // the snapshot was made assertThat(new String(db.get(readOptions, "key".getBytes()))).isEqualTo("value"); // add new key/value pair db.put("newkey".getBytes(), "newvalue".getBytes()); // using no snapshot the latest db entries // will be taken into account assertThat(new String(db.get("newkey".getBytes()))).isEqualTo("newvalue"); // snapshopot was created before newkey assertThat(db.get(readOptions, "newkey".getBytes())).isNull(); // Retrieve snapshot from read options Snapshot sameSnapshot = readOptions.snapshot(); readOptions.setSnapshot(sameSnapshot); // results must be the same with new Snapshot // instance using the same native pointer assertThat(new String(db.get(readOptions, "key".getBytes()))).isEqualTo("value"); // update key value pair to newvalue db.put("key".getBytes(), "newvalue".getBytes()); // read with previously created snapshot will // read previous version of key value pair assertThat(new String(db.get(readOptions, "key".getBytes()))).isEqualTo("value"); // read for newkey using the snapshot must be // null assertThat(db.get(readOptions, "newkey".getBytes())).isNull(); // setting null to snapshot in ReadOptions leads // to no Snapshot being used. readOptions.setSnapshot(null); assertThat(new String(db.get(readOptions, "newkey".getBytes()))).isEqualTo("newvalue"); // release Snapshot db.releaseSnapshot(snapshot); } finally { if (db != null) { db.close(); } if (options != null) { options.dispose(); } if (readOptions != null) { readOptions.dispose(); } } }