Add Status to RocksDBException so that meaningful function result Status from the C++ API isn't lost (#1273)
parent
ecf9003860
commit
ffdf6eee19
@ -0,0 +1,78 @@ |
|||||||
|
// Copyright (c) 2011-present, 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.
|
||||||
|
|
||||||
|
#include <jni.h> |
||||||
|
|
||||||
|
#include "include/org_rocksdb_RocksDBExceptionTest.h" |
||||||
|
|
||||||
|
#include "rocksdb/slice.h" |
||||||
|
#include "rocksdb/status.h" |
||||||
|
#include "rocksjni/portal.h" |
||||||
|
|
||||||
|
/*
|
||||||
|
* Class: org_rocksdb_RocksDBExceptionTest |
||||||
|
* Method: raiseException |
||||||
|
* Signature: ()V |
||||||
|
*/ |
||||||
|
void Java_org_rocksdb_RocksDBExceptionTest_raiseException(JNIEnv* env, |
||||||
|
jobject jobj) { |
||||||
|
rocksdb::RocksDBExceptionJni::ThrowNew(env, std::string("test message")); |
||||||
|
} |
||||||
|
|
||||||
|
/*
|
||||||
|
* Class: org_rocksdb_RocksDBExceptionTest |
||||||
|
* Method: raiseExceptionWithStatusCode |
||||||
|
* Signature: ()V |
||||||
|
*/ |
||||||
|
void Java_org_rocksdb_RocksDBExceptionTest_raiseExceptionWithStatusCode( |
||||||
|
JNIEnv* env, jobject jobj) { |
||||||
|
rocksdb::RocksDBExceptionJni::ThrowNew(env, "test message", |
||||||
|
rocksdb::Status::NotSupported()); |
||||||
|
} |
||||||
|
|
||||||
|
/*
|
||||||
|
* Class: org_rocksdb_RocksDBExceptionTest |
||||||
|
* Method: raiseExceptionNoMsgWithStatusCode |
||||||
|
* Signature: ()V |
||||||
|
*/ |
||||||
|
void Java_org_rocksdb_RocksDBExceptionTest_raiseExceptionNoMsgWithStatusCode( |
||||||
|
JNIEnv* env, jobject jobj) { |
||||||
|
rocksdb::RocksDBExceptionJni::ThrowNew(env, rocksdb::Status::NotSupported()); |
||||||
|
} |
||||||
|
|
||||||
|
/*
|
||||||
|
* Class: org_rocksdb_RocksDBExceptionTest |
||||||
|
* Method: raiseExceptionWithStatusCodeSubCode |
||||||
|
* Signature: ()V |
||||||
|
*/ |
||||||
|
void Java_org_rocksdb_RocksDBExceptionTest_raiseExceptionWithStatusCodeSubCode( |
||||||
|
JNIEnv* env, jobject jobj) { |
||||||
|
rocksdb::RocksDBExceptionJni::ThrowNew( |
||||||
|
env, "test message", |
||||||
|
rocksdb::Status::TimedOut(rocksdb::Status::SubCode::kLockTimeout)); |
||||||
|
} |
||||||
|
|
||||||
|
/*
|
||||||
|
* Class: org_rocksdb_RocksDBExceptionTest |
||||||
|
* Method: raiseExceptionNoMsgWithStatusCodeSubCode |
||||||
|
* Signature: ()V |
||||||
|
*/ |
||||||
|
void Java_org_rocksdb_RocksDBExceptionTest_raiseExceptionNoMsgWithStatusCodeSubCode( |
||||||
|
JNIEnv* env, jobject jobj) { |
||||||
|
rocksdb::RocksDBExceptionJni::ThrowNew( |
||||||
|
env, rocksdb::Status::TimedOut(rocksdb::Status::SubCode::kLockTimeout)); |
||||||
|
} |
||||||
|
|
||||||
|
/*
|
||||||
|
* Class: org_rocksdb_RocksDBExceptionTest |
||||||
|
* Method: raiseExceptionWithStatusCodeState |
||||||
|
* Signature: ()V |
||||||
|
*/ |
||||||
|
void Java_org_rocksdb_RocksDBExceptionTest_raiseExceptionWithStatusCodeState( |
||||||
|
JNIEnv* env, jobject jobj) { |
||||||
|
rocksdb::Slice state("test state"); |
||||||
|
rocksdb::RocksDBExceptionJni::ThrowNew(env, "test message", |
||||||
|
rocksdb::Status::NotSupported(state)); |
||||||
|
} |
@ -0,0 +1,113 @@ |
|||||||
|
// Copyright (c) 2011-present, 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; |
||||||
|
|
||||||
|
/** |
||||||
|
* Represents the status returned by a function call in RocksDB. |
||||||
|
* |
||||||
|
* Currently only used with {@link RocksDBException} when the |
||||||
|
* status is not {@link Code#Ok} |
||||||
|
*/ |
||||||
|
public class Status { |
||||||
|
private final Code code; |
||||||
|
/* @Nullable */ private final SubCode subCode; |
||||||
|
/* @Nullable */ private final String state; |
||||||
|
|
||||||
|
public Status(final Code code, final SubCode subCode, final String state) { |
||||||
|
this.code = code; |
||||||
|
this.subCode = subCode; |
||||||
|
this.state = state; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Intentionally private as this will be called from JNI |
||||||
|
*/ |
||||||
|
private Status(final byte code, final byte subCode, final String state) { |
||||||
|
this.code = Code.getCode(code); |
||||||
|
this.subCode = SubCode.getSubCode(subCode); |
||||||
|
this.state = state; |
||||||
|
} |
||||||
|
|
||||||
|
public Code getCode() { |
||||||
|
return code; |
||||||
|
} |
||||||
|
|
||||||
|
public SubCode getSubCode() { |
||||||
|
return subCode; |
||||||
|
} |
||||||
|
|
||||||
|
public String getState() { |
||||||
|
return state; |
||||||
|
} |
||||||
|
|
||||||
|
public String getCodeString() { |
||||||
|
final StringBuilder builder = new StringBuilder() |
||||||
|
.append(code.name()); |
||||||
|
if(subCode != null && subCode != SubCode.None) { |
||||||
|
builder.append("(") |
||||||
|
.append(subCode.name()) |
||||||
|
.append(")"); |
||||||
|
} |
||||||
|
return builder.toString(); |
||||||
|
} |
||||||
|
|
||||||
|
public enum Code { |
||||||
|
Ok( (byte)0x0), |
||||||
|
NotFound( (byte)0x1), |
||||||
|
Corruption( (byte)0x2), |
||||||
|
NotSupported( (byte)0x3), |
||||||
|
InvalidArgument( (byte)0x4), |
||||||
|
IOError( (byte)0x5), |
||||||
|
MergeInProgress( (byte)0x6), |
||||||
|
Incomplete( (byte)0x7), |
||||||
|
ShutdownInProgress( (byte)0x8), |
||||||
|
TimedOut( (byte)0x9), |
||||||
|
Aborted( (byte)0xA), |
||||||
|
Busy( (byte)0xB), |
||||||
|
Expired( (byte)0xC), |
||||||
|
TryAgain( (byte)0xD); |
||||||
|
|
||||||
|
private final byte value; |
||||||
|
|
||||||
|
Code(final byte value) { |
||||||
|
this.value = value; |
||||||
|
} |
||||||
|
|
||||||
|
public static Code getCode(final byte value) { |
||||||
|
for (final Code code : Code.values()) { |
||||||
|
if (code.value == value){ |
||||||
|
return code; |
||||||
|
} |
||||||
|
} |
||||||
|
throw new IllegalArgumentException( |
||||||
|
"Illegal value provided for Code."); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
public enum SubCode { |
||||||
|
None( (byte)0x0), |
||||||
|
MutexTimeout( (byte)0x1), |
||||||
|
LockTimeout( (byte)0x2), |
||||||
|
LockLimit( (byte)0x3), |
||||||
|
MaxSubCode( (byte)0xFE); |
||||||
|
|
||||||
|
private final byte value; |
||||||
|
|
||||||
|
SubCode(final byte value) { |
||||||
|
this.value = value; |
||||||
|
} |
||||||
|
|
||||||
|
public static SubCode getSubCode(final byte value) { |
||||||
|
for (final SubCode subCode : SubCode.values()) { |
||||||
|
if (subCode.value == value){ |
||||||
|
return subCode; |
||||||
|
} |
||||||
|
} |
||||||
|
throw new IllegalArgumentException( |
||||||
|
"Illegal value provided for SubCode."); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,115 @@ |
|||||||
|
// Copyright (c) 2011-present, 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; |
||||||
|
|
||||||
|
import org.junit.Test; |
||||||
|
|
||||||
|
import org.rocksdb.Status.Code; |
||||||
|
import org.rocksdb.Status.SubCode; |
||||||
|
import static org.assertj.core.api.Assertions.assertThat; |
||||||
|
import static org.junit.Assert.fail; |
||||||
|
|
||||||
|
public class RocksDBExceptionTest { |
||||||
|
|
||||||
|
@Test |
||||||
|
public void exception() { |
||||||
|
try { |
||||||
|
raiseException(); |
||||||
|
} catch(final RocksDBException e) { |
||||||
|
assertThat(e.getStatus()).isNull(); |
||||||
|
assertThat(e.getMessage()).isEqualTo("test message"); |
||||||
|
return; |
||||||
|
} |
||||||
|
fail(); |
||||||
|
} |
||||||
|
|
||||||
|
@Test |
||||||
|
public void exceptionWithStatusCode() { |
||||||
|
try { |
||||||
|
raiseExceptionWithStatusCode(); |
||||||
|
} catch(final RocksDBException e) { |
||||||
|
assertThat(e.getStatus()).isNotNull(); |
||||||
|
assertThat(e.getStatus().getCode()).isEqualTo(Code.NotSupported); |
||||||
|
assertThat(e.getStatus().getSubCode()).isEqualTo(SubCode.None); |
||||||
|
assertThat(e.getStatus().getState()).isNull(); |
||||||
|
assertThat(e.getMessage()).isEqualTo("test message"); |
||||||
|
return; |
||||||
|
} |
||||||
|
fail(); |
||||||
|
} |
||||||
|
|
||||||
|
@Test |
||||||
|
public void exceptionNoMsgWithStatusCode() { |
||||||
|
try { |
||||||
|
raiseExceptionNoMsgWithStatusCode(); |
||||||
|
} catch(final RocksDBException e) { |
||||||
|
assertThat(e.getStatus()).isNotNull(); |
||||||
|
assertThat(e.getStatus().getCode()).isEqualTo(Code.NotSupported); |
||||||
|
assertThat(e.getStatus().getSubCode()).isEqualTo(SubCode.None); |
||||||
|
assertThat(e.getStatus().getState()).isNull(); |
||||||
|
assertThat(e.getMessage()).isEqualTo(Code.NotSupported.name()); |
||||||
|
return; |
||||||
|
} |
||||||
|
fail(); |
||||||
|
} |
||||||
|
|
||||||
|
@Test |
||||||
|
public void exceptionWithStatusCodeSubCode() { |
||||||
|
try { |
||||||
|
raiseExceptionWithStatusCodeSubCode(); |
||||||
|
} catch(final RocksDBException e) { |
||||||
|
assertThat(e.getStatus()).isNotNull(); |
||||||
|
assertThat(e.getStatus().getCode()).isEqualTo(Code.TimedOut); |
||||||
|
assertThat(e.getStatus().getSubCode()) |
||||||
|
.isEqualTo(Status.SubCode.LockTimeout); |
||||||
|
assertThat(e.getStatus().getState()).isNull(); |
||||||
|
assertThat(e.getMessage()).isEqualTo("test message"); |
||||||
|
return; |
||||||
|
} |
||||||
|
fail(); |
||||||
|
} |
||||||
|
|
||||||
|
@Test |
||||||
|
public void exceptionNoMsgWithStatusCodeSubCode() { |
||||||
|
try { |
||||||
|
raiseExceptionNoMsgWithStatusCodeSubCode(); |
||||||
|
} catch(final RocksDBException e) { |
||||||
|
assertThat(e.getStatus()).isNotNull(); |
||||||
|
assertThat(e.getStatus().getCode()).isEqualTo(Code.TimedOut); |
||||||
|
assertThat(e.getStatus().getSubCode()).isEqualTo(SubCode.LockTimeout); |
||||||
|
assertThat(e.getStatus().getState()).isNull(); |
||||||
|
assertThat(e.getMessage()).isEqualTo(Code.TimedOut.name() + |
||||||
|
"(" + SubCode.LockTimeout.name() + ")"); |
||||||
|
return; |
||||||
|
} |
||||||
|
fail(); |
||||||
|
} |
||||||
|
|
||||||
|
@Test |
||||||
|
public void exceptionWithStatusCodeState() { |
||||||
|
try { |
||||||
|
raiseExceptionWithStatusCodeState(); |
||||||
|
} catch(final RocksDBException e) { |
||||||
|
assertThat(e.getStatus()).isNotNull(); |
||||||
|
assertThat(e.getStatus().getCode()).isEqualTo(Code.NotSupported); |
||||||
|
assertThat(e.getStatus().getSubCode()).isEqualTo(SubCode.None); |
||||||
|
assertThat(e.getStatus().getState()).isNotNull(); |
||||||
|
assertThat(e.getMessage()).isEqualTo("test message"); |
||||||
|
return; |
||||||
|
} |
||||||
|
fail(); |
||||||
|
} |
||||||
|
|
||||||
|
private native void raiseException() throws RocksDBException; |
||||||
|
private native void raiseExceptionWithStatusCode() throws RocksDBException; |
||||||
|
private native void raiseExceptionNoMsgWithStatusCode() throws RocksDBException; |
||||||
|
private native void raiseExceptionWithStatusCodeSubCode() |
||||||
|
throws RocksDBException; |
||||||
|
private native void raiseExceptionNoMsgWithStatusCodeSubCode() |
||||||
|
throws RocksDBException; |
||||||
|
private native void raiseExceptionWithStatusCodeState() |
||||||
|
throws RocksDBException; |
||||||
|
} |
Loading…
Reference in new issue