To retrieve the machine-readable status, the following Python code works on my FDB cluster:
import fdb
import json
fab.api_version(600)
db=fdb.open()
status = json.loads(db[’\xff\xff/status/json’])
print status
Then I have the following Java code to try to retrieve the same status:
public class FoundationDBClusterStatus {
private static final FDB fdb;
private static final Database db;
static {
fdb = FDB.selectAPIVersion(600);
db = fdb.open("/<path>/fdb.cluster");
}
public static void main(String[] args) throws InterruptedException {
String statusInJson = db.run(tr -> {
TransactionOptions options = tr.options();
options.setReadSystemKeys();
byte[] result = tr.get(Tuple.from((byte)0xff, (byte)0xff, "/status/json".getBytes()).pack()).join();
if (result != null) {
System.out.println("result is not null");
return Tuple.fromBytes(result).getString(0);
}
else{
System.out.println("result is null");
return "";
}
});
System.out.println("status in json is: " + statusInJson);
}
}
I am able to get the database object, but always get the null byte result, even though I tried to set that the key access is a system key access. Do I miss something on encoding the key?
You might have to form the key directly as a byte, without involving Tuple layer. Tuple layer encoding would create a byte array that is different from \xff\xff/status/json
Thank you for the suggestion. After I changed the code to manually construct the byte for \xff\xff/status/json, I was able to retrieve correctly the status information. The returned byte result also should not pass through the Tuple layer for String unmarshalling. The following is the code that works:
public static byte[] stringToBytesASCII(String str) {
char[] buffer = str.toCharArray();
byte[] b = new byte[buffer.length];
for (int i = 0; i < b.length; i++) {
b[i] = (byte) buffer[i];
}
return b;
}
public static void main(String[] args) throws InterruptedException {
// we have to build the byte array and not using the Tuple layer APIs.
String statusInJson = db.run(tr -> {
TransactionOptions options = tr.options();
options.setReadSystemKeys();
byte[] stringPartOfKey= stringToBytesASCII("/status/json");
byte[] fullKey =new byte[stringPartOfKey.length +2];
fullKey[0] = (byte)0xff;
fullKey[1] = (byte)0xff;
for (int i=2; i<fullKey.length; i++) {
fullKey[i] = stringPartOfKey[i-2];
}
//same to the output of the key value that we should not rely on the Tuple layer APIs.
byte[] result = tr.get(fullKey).join();
try {
String str = new String(result, "UTF-8");
return str;
}
catch (Exception ex) {
System.out.println("encounter exception: " + ex.getMessage());
return "";
}
});
System.out.println("status in json is: " + statusInJson);
}
Perhaps a simplified version of the above using ByteBuffers instead:
public String getStatus() {
return db.run(tr -> {
TransactionOptions options = tr.options();
options.setReadSystemKeys();
// we have to build the byte array and not using the Tuple layer APIs.
//same to the output of the key value that we should not rely on the Tuple layer APIs.
ByteBuffer bb = ByteBuffer.allocate("/status/json" + 2);
bb.put((byte)0xff);
bb.put((byte)0xff);
bb.put("/status/json".getBytes(Charset.defaultCharset()));
byte[] result = tr.get(bb.array()).join();
try {
String str = new String(result, "UTF-8");
return str;
} catch (Exception ex) {
return null;
}
});
}