mirror of
https://github.com/facebook/rocksdb.git
synced 2024-11-26 16:30:56 +00:00
Merge pull request #398 from fyrz/RocksJava-CreateCheckPoint
[RocksJava] Support for stored snapshots
This commit is contained in:
commit
b8136a7d27
|
@ -4,6 +4,7 @@ NATIVE_JAVA_CLASSES = org.rocksdb.AbstractComparator\
|
|||
org.rocksdb.BackupableDBOptions\
|
||||
org.rocksdb.BlockBasedTableConfig\
|
||||
org.rocksdb.BloomFilter\
|
||||
org.rocksdb.Checkpoint\
|
||||
org.rocksdb.ColumnFamilyHandle\
|
||||
org.rocksdb.ColumnFamilyOptions\
|
||||
org.rocksdb.Comparator\
|
||||
|
@ -50,6 +51,7 @@ endif
|
|||
JAVA_TESTS = org.rocksdb.test.BackupableDBOptionsTest\
|
||||
org.rocksdb.test.BackupableDBTest\
|
||||
org.rocksdb.test.BlockBasedTableConfigTest\
|
||||
org.rocksdb.test.CheckPointTest\
|
||||
org.rocksdb.test.ColumnFamilyOptionsTest\
|
||||
org.rocksdb.test.ColumnFamilyTest\
|
||||
org.rocksdb.test.ComparatorOptionsTest\
|
||||
|
|
72
java/org/rocksdb/Checkpoint.java
Normal file
72
java/org/rocksdb/Checkpoint.java
Normal file
|
@ -0,0 +1,72 @@
|
|||
// Copyright (c) 2014, Facebook, Inc. All rights reserved.
|
||||
// This source code is licensed under the BSD-style license found in the
|
||||
// LICENSE file in the root directory of this source tree. An additional grant
|
||||
// of patent rights can be found in the PATENTS file in the same directory.
|
||||
|
||||
package org.rocksdb;
|
||||
|
||||
/**
|
||||
* Provides Checkpoint functionality. Checkpoints
|
||||
* provide persistent snapshots of RocksDB databases.
|
||||
*/
|
||||
public class Checkpoint extends RocksObject {
|
||||
|
||||
/**
|
||||
* Creates a Checkpoint object to be used for creating open-able
|
||||
* snapshots.
|
||||
*
|
||||
* @param db {@link RocksDB} instance.
|
||||
* @return a Checkpoint instance.
|
||||
*
|
||||
* @throws java.lang.IllegalArgumentException if {@link RocksDB}
|
||||
* instance is null.
|
||||
* @throws java.lang.IllegalStateException if {@link RocksDB}
|
||||
* instance is not initialized.
|
||||
*/
|
||||
public static Checkpoint create(RocksDB db) {
|
||||
if (db == null) {
|
||||
throw new IllegalArgumentException(
|
||||
"RocksDB instance shall not be null.");
|
||||
} else if (!db.isInitialized()) {
|
||||
throw new IllegalStateException(
|
||||
"RocksDB instance must be initialized.");
|
||||
}
|
||||
Checkpoint checkpoint = new Checkpoint(db);
|
||||
return checkpoint;
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>Builds an open-able snapshot of RocksDB on the same disk, which
|
||||
* accepts an output directory on the same disk, and under the directory
|
||||
* (1) hard-linked SST files pointing to existing live SST files
|
||||
* (2) a copied manifest files and other files</p>
|
||||
*
|
||||
* @param checkpointPath path to the folder where the snapshot is going
|
||||
* to be stored.
|
||||
* @throws RocksDBException thrown if an error occurs within the native
|
||||
* part of the library.
|
||||
*/
|
||||
public void createCheckpoint(String checkpointPath)
|
||||
throws RocksDBException {
|
||||
createCheckpoint(nativeHandle_, checkpointPath);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void disposeInternal() {
|
||||
disposeInternal(nativeHandle_);
|
||||
}
|
||||
|
||||
private Checkpoint(RocksDB db) {
|
||||
super();
|
||||
nativeHandle_ = newCheckpoint(db.nativeHandle_);
|
||||
db_ = db;
|
||||
}
|
||||
|
||||
RocksDB db_;
|
||||
|
||||
private static native long newCheckpoint(long dbHandle);
|
||||
private native void disposeInternal(long handle);
|
||||
|
||||
private native void createCheckpoint(long handle, String checkpointPath)
|
||||
throws RocksDBException;
|
||||
}
|
101
java/org/rocksdb/test/CheckPointTest.java
Normal file
101
java/org/rocksdb/test/CheckPointTest.java
Normal file
|
@ -0,0 +1,101 @@
|
|||
package org.rocksdb.test;
|
||||
|
||||
|
||||
import org.junit.ClassRule;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.rules.TemporaryFolder;
|
||||
import org.rocksdb.Checkpoint;
|
||||
import org.rocksdb.Options;
|
||||
import org.rocksdb.RocksDB;
|
||||
import org.rocksdb.RocksDBException;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
public class CheckPointTest {
|
||||
|
||||
@ClassRule
|
||||
public static final RocksMemoryResource rocksMemoryResource =
|
||||
new RocksMemoryResource();
|
||||
|
||||
@Rule
|
||||
public TemporaryFolder dbFolder = new TemporaryFolder();
|
||||
|
||||
@Rule
|
||||
public TemporaryFolder checkpointFolder = new TemporaryFolder();
|
||||
|
||||
@Test
|
||||
public void checkPoint() throws RocksDBException {
|
||||
RocksDB db = null;
|
||||
Options options = null;
|
||||
Checkpoint checkpoint = null;
|
||||
try {
|
||||
options = new Options().
|
||||
setCreateIfMissing(true);
|
||||
db = RocksDB.open(options,
|
||||
dbFolder.getRoot().getAbsolutePath());
|
||||
db.put("key".getBytes(), "value".getBytes());
|
||||
checkpoint = Checkpoint.create(db);
|
||||
checkpoint.createCheckpoint(checkpointFolder.
|
||||
getRoot().getAbsolutePath() + "/snapshot1");
|
||||
db.put("key2".getBytes(), "value2".getBytes());
|
||||
checkpoint.createCheckpoint(checkpointFolder.
|
||||
getRoot().getAbsolutePath() + "/snapshot2");
|
||||
db.close();
|
||||
db = RocksDB.open(options,
|
||||
checkpointFolder.getRoot().getAbsolutePath() +
|
||||
"/snapshot1");
|
||||
assertThat(new String(db.get("key".getBytes()))).
|
||||
isEqualTo("value");
|
||||
assertThat(db.get("key2".getBytes())).isNull();
|
||||
db.close();
|
||||
db = RocksDB.open(options,
|
||||
checkpointFolder.getRoot().getAbsolutePath() +
|
||||
"/snapshot2");
|
||||
assertThat(new String(db.get("key".getBytes()))).
|
||||
isEqualTo("value");
|
||||
assertThat(new String(db.get("key2".getBytes()))).
|
||||
isEqualTo("value2");
|
||||
} finally {
|
||||
if (db != null) {
|
||||
db.close();
|
||||
}
|
||||
if (options != null) {
|
||||
options.dispose();
|
||||
}
|
||||
if (checkpoint != null) {
|
||||
checkpoint.dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void failIfDbIsNull() {
|
||||
Checkpoint.create(null);
|
||||
}
|
||||
|
||||
@Test(expected = IllegalStateException.class)
|
||||
public void failIfDbNotInitialized() throws RocksDBException {
|
||||
RocksDB db = RocksDB.open(dbFolder.getRoot().getAbsolutePath());
|
||||
db.dispose();
|
||||
Checkpoint.create(db);
|
||||
}
|
||||
|
||||
@Test(expected = RocksDBException.class)
|
||||
public void failWithIllegalPath() throws RocksDBException {
|
||||
RocksDB db = null;
|
||||
Checkpoint checkpoint = null;
|
||||
try {
|
||||
db = RocksDB.open(dbFolder.getRoot().getAbsolutePath());
|
||||
checkpoint = Checkpoint.create(db);
|
||||
checkpoint.createCheckpoint("/Z:///:\\C:\\TZ/-");
|
||||
} finally {
|
||||
if (db != null) {
|
||||
db.close();
|
||||
}
|
||||
if (checkpoint != null) {
|
||||
checkpoint.dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
61
java/rocksjni/checkpoint.cc
Normal file
61
java/rocksjni/checkpoint.cc
Normal file
|
@ -0,0 +1,61 @@
|
|||
// Copyright (c) 2014, Facebook, Inc. All rights reserved.
|
||||
// This source code is licensed under the BSD-style license found in the
|
||||
// LICENSE file in the root directory of this source tree. An additional grant
|
||||
// of patent rights can be found in the PATENTS file in the same directory.
|
||||
//
|
||||
// This file implements the "bridge" between Java and C++ and enables
|
||||
// calling c++ rocksdb::Checkpoint methods from Java side.
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <jni.h>
|
||||
#include <string>
|
||||
|
||||
#include "include/org_rocksdb_Checkpoint.h"
|
||||
#include "rocksjni/portal.h"
|
||||
#include "rocksdb/db.h"
|
||||
#include "rocksdb/utilities/checkpoint.h"
|
||||
/*
|
||||
* Class: org_rocksdb_Checkpoint
|
||||
* Method: newCheckpoint
|
||||
* Signature: (J)J
|
||||
*/
|
||||
jlong Java_org_rocksdb_Checkpoint_newCheckpoint(JNIEnv* env,
|
||||
jclass jclazz, jlong jdb_handle) {
|
||||
auto db = reinterpret_cast<rocksdb::DB*>(jdb_handle);
|
||||
rocksdb::Checkpoint* checkpoint;
|
||||
rocksdb::Checkpoint::Create(db, &checkpoint);
|
||||
return reinterpret_cast<jlong>(checkpoint);
|
||||
}
|
||||
|
||||
/*
|
||||
* Class: org_rocksdb_Checkpoint
|
||||
* Method: dispose
|
||||
* Signature: (J)V
|
||||
*/
|
||||
void Java_org_rocksdb_Checkpoint_disposeInternal(JNIEnv* env, jobject jobj,
|
||||
jlong jhandle) {
|
||||
auto checkpoint = reinterpret_cast<rocksdb::Checkpoint*>(jhandle);
|
||||
assert(checkpoint);
|
||||
delete checkpoint;
|
||||
}
|
||||
|
||||
/*
|
||||
* Class: org_rocksdb_Checkpoint
|
||||
* Method: createCheckpoint
|
||||
* Signature: (JLjava/lang/String;)V
|
||||
*/
|
||||
void Java_org_rocksdb_Checkpoint_createCheckpoint(
|
||||
JNIEnv* env, jobject jobj, jlong jcheckpoint_handle,
|
||||
jstring jcheckpoint_path) {
|
||||
auto checkpoint = reinterpret_cast<rocksdb::Checkpoint*>(
|
||||
jcheckpoint_handle);
|
||||
const char* checkpoint_path = env->GetStringUTFChars(
|
||||
jcheckpoint_path, 0);
|
||||
rocksdb::Status s = checkpoint->CreateCheckpoint(
|
||||
checkpoint_path);
|
||||
env->ReleaseStringUTFChars(jcheckpoint_path, checkpoint_path);
|
||||
if (!s.ok()) {
|
||||
rocksdb::RocksDBExceptionJni::ThrowNew(env, s);
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue