blob: 2cae08824c6e53097d46532ba2aadcda5949703a [file] [log] [blame]
/**
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <jni.h>
#include <mutex>
#undef JNIEXPORT
#if _WIN32
#define JNIEXPORT __declspec(dllexport)
#else
#define JNIEXPORT __attribute__((visibility("default")))
#endif
#include "org_apache_hadoop_hdfs_hdfsdb_DB.h"
#include "org_apache_hadoop_hdfs_hdfsdb_Iterator.h"
#include "org_apache_hadoop_hdfs_hdfsdb_Options.h"
#include "org_apache_hadoop_hdfs_hdfsdb_NativeObject.h"
#include "org_apache_hadoop_hdfs_hdfsdb_ReadOptions.h"
#include "org_apache_hadoop_hdfs_hdfsdb_WriteBatch.h"
#include "org_apache_hadoop_hdfs_hdfsdb_WriteOptions.h"
#include <leveldb/db.h>
#include <leveldb/cache.h>
#include <leveldb/options.h>
#include <leveldb/write_batch.h>
#include <leveldb/cache.h>
static inline uintptr_t uintptr(const void *ptr) {
return reinterpret_cast<uintptr_t>(ptr);
}
static inline jbyteArray ToJByteArray(JNIEnv *env, const leveldb::Slice &slice) {
jbyteArray res = env->NewByteArray(slice.size());
if (!res) {
env->ThrowNew(env->FindClass("java/lang/OutOfMemoryError"), "");
} else {
env->SetByteArrayRegion(res, 0, slice.size(), reinterpret_cast<const jbyte*>(slice.data()));
}
return res;
}
struct GetByteArrayElements {
static jbyte *Get(JNIEnv *env, jbyteArray array) {
return env->GetByteArrayElements(array, NULL);
}
static void Release(JNIEnv *env, jbyteArray array, jbyte *data) {
env->ReleaseByteArrayElements(array, data, JNI_ABORT);
}
};
struct GetByteArrayCritical {
static jbyte *Get(JNIEnv *env, jbyteArray array) {
return reinterpret_cast<jbyte*>(env->GetPrimitiveArrayCritical(array, NULL));
}
static void Release(JNIEnv *env, jbyteArray array, jbyte *data) {
env->ReleasePrimitiveArrayCritical(array, data, JNI_ABORT);
}
};
template <class Trait>
class JNIByteArrayHolder {
public:
JNIByteArrayHolder(JNIEnv *env, jbyteArray array)
: env_(env)
, array_(array)
{
data_ = Trait::Get(env, array);
length_ = env_->GetArrayLength(array);
}
~JNIByteArrayHolder() { Trait::Release(env_, array_, data_); }
const char *data() const { return reinterpret_cast<const char*>(data_); }
int length() const { return length_; }
const leveldb::Slice slice() const { return leveldb::Slice(data(), length()); }
private:
JNIEnv *env_;
jbyteArray array_;
jbyte *data_;
int length_;
};
jlong JNICALL Java_org_apache_hadoop_hdfs_hdfsdb_DB_open(JNIEnv *env, jclass, jlong joptions, jstring path) {
leveldb::DB *db = NULL;
const char *path_str = env->GetStringUTFChars(path, 0);
leveldb::Options *options = reinterpret_cast<leveldb::Options*>(joptions);
leveldb::Status status = leveldb::DB::Open(*options, path_str, &db);
env->ReleaseStringUTFChars(path, path_str);
if (!status.ok()) {
env->ThrowNew(env->FindClass("java/io/IOException"), status.ToString().c_str());
}
return uintptr(db);
}
void JNICALL Java_org_apache_hadoop_hdfs_hdfsdb_DB_close(JNIEnv *, jclass, jlong handle) {
leveldb::DB *db = reinterpret_cast<leveldb::DB*>(handle);
delete db;
}
jbyteArray JNICALL Java_org_apache_hadoop_hdfs_hdfsdb_DB_get(JNIEnv *env, jclass, jlong handle, jlong jread_options, jbyteArray jkey) {
leveldb::DB *db = reinterpret_cast<leveldb::DB*>(handle);
leveldb::ReadOptions *options = reinterpret_cast<leveldb::ReadOptions*>(jread_options);
std::string result;
leveldb::Status status;
{
JNIByteArrayHolder<GetByteArrayElements> key(env, jkey);
status = db->Get(*options, key.slice(), &result);
}
if (status.IsNotFound()) {
return NULL;
} else if (!status.ok()) {
env->ThrowNew(env->FindClass("java/io/IOException"), status.ToString().c_str());
return NULL;
}
return ToJByteArray(env, leveldb::Slice(result));
}
jbyteArray JNICALL Java_org_apache_hadoop_hdfs_hdfsdb_DB_snapshotGet(JNIEnv *env, jclass, jlong handle, jlong jread_options, jbyteArray jkey) {
leveldb::DB *db = reinterpret_cast<leveldb::DB*>(handle);
leveldb::ReadOptions *options = reinterpret_cast<leveldb::ReadOptions*>(jread_options);
jbyteArray res = NULL;
leveldb::Status status;
{
JNIByteArrayHolder<GetByteArrayCritical> key(env, jkey);
status = db->SnapshotGet(*options, key.slice(),
[env,&res](const leveldb::Slice &v) {
res = ToJByteArray(env, v);
});
}
if (status.IsNotFound()) {
return NULL;
} else if (!status.ok()) {
env->ThrowNew(env->FindClass("java/io/IOException"), status.ToString().c_str());
return NULL;
}
return res;
}
void JNICALL Java_org_apache_hadoop_hdfs_hdfsdb_DB_write(JNIEnv *env, jclass, jlong handle, jlong jwrite_options, jlong jbatch) {
leveldb::DB *db = reinterpret_cast<leveldb::DB*>(handle);
leveldb::WriteOptions *options = reinterpret_cast<leveldb::WriteOptions*>(jwrite_options);
leveldb::WriteBatch *batch = reinterpret_cast<leveldb::WriteBatch*>(jbatch);
leveldb::Status status = db->Write(*options, batch);
}
void JNICALL Java_org_apache_hadoop_hdfs_hdfsdb_DB_delete(JNIEnv *env, jclass, jlong handle, jlong jwrite_options, jbyteArray jkey) {
leveldb::DB *db = reinterpret_cast<leveldb::DB*>(handle);
leveldb::WriteOptions *options = reinterpret_cast<leveldb::WriteOptions*>(jwrite_options);
leveldb::Status status;
{
JNIByteArrayHolder<GetByteArrayElements> key(env, jkey);
status = db->Delete(*options, key.slice());
}
}
jlong JNICALL Java_org_apache_hadoop_hdfs_hdfsdb_DB_newIterator(JNIEnv *, jclass, jlong handle, jlong jread_options) {
leveldb::DB *db = reinterpret_cast<leveldb::DB*>(handle);
leveldb::ReadOptions *options = reinterpret_cast<leveldb::ReadOptions*>(jread_options);
uintptr_t res = uintptr(db->NewIterator(*options));
return res;
}
jlong JNICALL Java_org_apache_hadoop_hdfs_hdfsdb_DB_newSnapshot(JNIEnv *, jclass, jlong handle) {
leveldb::DB *db = reinterpret_cast<leveldb::DB*>(handle);
uintptr_t res = uintptr(db->GetSnapshot());
return res;
}
void JNICALL Java_org_apache_hadoop_hdfs_hdfsdb_DB_releaseSnapshot(JNIEnv *, jclass, jlong handle, jlong snapshot) {
leveldb::DB *db = reinterpret_cast<leveldb::DB*>(handle);
leveldb::Snapshot *s = reinterpret_cast<leveldb::Snapshot*>(snapshot);
db->ReleaseSnapshot(s);
}
static std::mutex mutex;
jbyteArray JNICALL Java_org_apache_hadoop_hdfs_hdfsdb_DB_getTest(JNIEnv *env,
jclass, jlong handle, jbyteArray jkey) {
mutex.lock();
JNIByteArrayHolder<GetByteArrayElements> key(env, jkey);
std::string result;
result.resize(100);
mutex.unlock();
return ToJByteArray(env, leveldb::Slice(result));
}
void JNICALL Java_org_apache_hadoop_hdfs_hdfsdb_Iterator_destruct(JNIEnv *, jclass, jlong handle) {
delete reinterpret_cast<leveldb::Iterator*>(handle);
}
void JNICALL Java_org_apache_hadoop_hdfs_hdfsdb_Iterator_seek(JNIEnv *env, jclass, jlong handle, jbyteArray jkey) {
leveldb::Iterator *it = reinterpret_cast<leveldb::Iterator*>(handle);
JNIByteArrayHolder<GetByteArrayElements> key(env, jkey);
it->Seek(key.slice());
}
void JNICALL Java_org_apache_hadoop_hdfs_hdfsdb_Iterator_next(JNIEnv *, jclass, jlong handle) {
leveldb::Iterator *it = reinterpret_cast<leveldb::Iterator*>(handle);
it->Next();
}
jboolean JNICALL Java_org_apache_hadoop_hdfs_hdfsdb_Iterator_valid(JNIEnv *, jclass, jlong handle) {
leveldb::Iterator *it = reinterpret_cast<leveldb::Iterator*>(handle);
return it->Valid();
}
jbyteArray JNICALL Java_org_apache_hadoop_hdfs_hdfsdb_Iterator_key(JNIEnv *env, jclass, jlong handle) {
leveldb::Iterator *it = reinterpret_cast<leveldb::Iterator*>(handle);
return ToJByteArray(env, it->key());
}
jbyteArray JNICALL Java_org_apache_hadoop_hdfs_hdfsdb_Iterator_value(JNIEnv *env, jclass, jlong handle) {
leveldb::Iterator *it = reinterpret_cast<leveldb::Iterator*>(handle);
return ToJByteArray(env, it->value());
}
jlong JNICALL Java_org_apache_hadoop_hdfs_hdfsdb_Options_construct(JNIEnv *, jclass) {
return uintptr(new leveldb::Options());
}
void JNICALL Java_org_apache_hadoop_hdfs_hdfsdb_Options_destruct(JNIEnv *, jclass, jlong handle) {
delete reinterpret_cast<leveldb::Options*>(handle);
}
void JNICALL Java_org_apache_hadoop_hdfs_hdfsdb_Options_createIfMissing(JNIEnv *, jclass, jlong handle, jboolean value) {
leveldb::Options *options = reinterpret_cast<leveldb::Options*>(handle);
options->create_if_missing = value;
}
void JNICALL Java_org_apache_hadoop_hdfs_hdfsdb_Options_compressionType(JNIEnv *, jclass, jlong handle, jint value) {
leveldb::Options *options = reinterpret_cast<leveldb::Options*>(handle);
options->compression = (leveldb::CompressionType)value;
}
void JNICALL Java_org_apache_hadoop_hdfs_hdfsdb_Options_writeBufferSize(JNIEnv *, jclass, jlong handle, jint value) {
leveldb::Options *options = reinterpret_cast<leveldb::Options*>(handle);
options->write_buffer_size = value;
}
void JNICALL Java_org_apache_hadoop_hdfs_hdfsdb_Options_blockSize(JNIEnv *, jclass, jlong handle, jint value) {
leveldb::Options *options = reinterpret_cast<leveldb::Options*>(handle);
options->block_size = value;
}
void JNICALL Java_org_apache_hadoop_hdfs_hdfsdb_Options_blockCacheSize(JNIEnv *, jclass, jlong handle, jlong value) {
leveldb::Options *options = reinterpret_cast<leveldb::Options*>(handle);
if (options->block_cache) {
delete options->block_cache;
}
options->block_cache = leveldb::NewLRUCache(value);
}
jlong JNICALL Java_org_apache_hadoop_hdfs_hdfsdb_ReadOptions_construct(JNIEnv *, jclass) {
return uintptr(new leveldb::ReadOptions());
}
void JNICALL Java_org_apache_hadoop_hdfs_hdfsdb_ReadOptions_destruct(JNIEnv *, jclass, jlong handle) {
delete reinterpret_cast<leveldb::ReadOptions*>(handle);
}
void JNICALL Java_org_apache_hadoop_hdfs_hdfsdb_ReadOptions_snapshot(JNIEnv *, jclass, jlong handle, jlong snapshot) {
leveldb::ReadOptions *o = reinterpret_cast<leveldb::ReadOptions*>(handle);
o->snapshot = reinterpret_cast<leveldb::Snapshot*>(snapshot);
}
jlong JNICALL Java_org_apache_hadoop_hdfs_hdfsdb_WriteOptions_construct(JNIEnv *, jclass) {
return uintptr(new leveldb::WriteOptions());
}
void JNICALL Java_org_apache_hadoop_hdfs_hdfsdb_WriteOptions_sync(JNIEnv *, jclass, jlong handle, jboolean value) {
leveldb::WriteOptions *options = reinterpret_cast<leveldb::WriteOptions*>(handle);
options->sync = value;
}
void JNICALL Java_org_apache_hadoop_hdfs_hdfsdb_WriteOptions_skipWal(JNIEnv *, jclass, jlong handle, jboolean value) {
leveldb::WriteOptions *options = reinterpret_cast<leveldb::WriteOptions*>(handle);
options->skip_wal = value;
}
void JNICALL Java_org_apache_hadoop_hdfs_hdfsdb_WriteOptions_destruct(JNIEnv *, jclass, jlong handle) {
delete reinterpret_cast<leveldb::WriteOptions*>(handle);
}
jlong JNICALL Java_org_apache_hadoop_hdfs_hdfsdb_WriteBatch_construct(JNIEnv *, jclass) {
return uintptr(new leveldb::WriteBatch());
}
void JNICALL Java_org_apache_hadoop_hdfs_hdfsdb_WriteBatch_destruct(JNIEnv *, jclass, jlong handle) {
delete reinterpret_cast<leveldb::WriteBatch*>(handle);
}
void JNICALL Java_org_apache_hadoop_hdfs_hdfsdb_WriteBatch_put(JNIEnv *env, jclass, jlong handle, jbyteArray jkey, jbyteArray jvalue) {
leveldb::WriteBatch *batch = reinterpret_cast<leveldb::WriteBatch*>(handle);
JNIByteArrayHolder<GetByteArrayCritical> key(env, jkey), value(env, jvalue);
batch->Put(key.slice(), value.slice());
}
void JNICALL Java_org_apache_hadoop_hdfs_hdfsdb_WriteBatch_delete(JNIEnv *env, jclass, jlong handle, jbyteArray jkey) {
leveldb::WriteBatch *batch = reinterpret_cast<leveldb::WriteBatch*>(handle);
JNIByteArrayHolder<GetByteArrayCritical> key(env, jkey);
batch->Delete(key.slice());
}
void JNICALL Java_org_apache_hadoop_hdfs_hdfsdb_WriteBatch_clear(JNIEnv *, jclass, jlong handle) {
leveldb::WriteBatch *batch = reinterpret_cast<leveldb::WriteBatch*>(handle);
batch->Clear();
}