experimental java language bindings

This commit is contained in:
Sears Russell 2011-11-07 22:46:32 +00:00
parent 7650e5ab53
commit cb97772aa6
8 changed files with 668 additions and 0 deletions

View file

@ -68,6 +68,10 @@ CHECK_FUNCTION_EXISTS(posix_fallocate HAVE_POSIX_FALLOCATE)
CHECK_FUNCTION_EXISTS(fdatasync HAVE_FDATASYNC)
CHECK_FUNCTION_EXISTS(tdestroy HAVE_TDESTROY)
FIND_PACKAGE(JNI)
FIND_PACKAGE(PERL)
FIND_PACKAGE(RUBY)
FIND_LIBRARY(DBUG_TEST dbug-stubs /home/sears/local/dbug/lib/)
if(NOT DBUG_TEST)
message(STATUS "dbug not found. proceeding with normal build")

View file

@ -1,2 +1,3 @@
SUBDIRS(perl)
SUBDIRS(ruby)
SUBDIRS(java)

17
lang/java/CMakeLists.txt Normal file
View file

@ -0,0 +1,17 @@
IF(JNI_FOUND)
ADD_CUSTOM_COMMAND(
OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/org/stasis/Stasis.class
COMMAND javac -d ${CMAKE_CURRENT_BINARY_DIR}
-sourcepath ${CMAKE_CURRENT_SOURCE_DIR}
${CMAKE_CURRENT_SOURCE_DIR}/org/stasis/Stasis.java
)
ADD_CUSTOM_COMMAND(
OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/org_stasis_Stasis.h
COMMAND javah -classpath ${CMAKE_CURRENT_BINARY_DIR} -jni
-d ${CMAKE_CURRENT_BINARY_DIR} org.stasis.Stasis
DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/org/stasis/Stasis.class
)
#INCLUDE_DIRECTORIES(${CMAKE_CURRENT_BINARY_DIR} /usr/lib/jvm/java-6-openjdk/include/ ${INCLUDE_DIRECTORIES})
INCLUDE_DIRECTORIES(${CMAKE_CURRENT_BINARY_DIR} ${JAVA_INCLUDE_PATH} ${INCLUDE_DIRECTORIES})
ADD_LIBRARY(stasisjni ${CMAKE_CURRENT_SOURCE_DIR}/org_stasis_Stasis.c)
ENDIF(JNI_FOUND)

4
lang/java/build.xml Normal file
View file

@ -0,0 +1,4 @@
<?xml version="1.0" encoding="UTF-8"?>
<project name="stasis" default="compile" basedir=".">
</project>

View file

@ -0,0 +1,193 @@
package stasis.jni;
import java.util.Arrays;
import java.util.Iterator;
import jol.core.Runtime;
import jol.types.basic.Tuple;
import jol.types.basic.TupleSet;
import jol.types.exception.BadKeyException;
import jol.types.exception.UpdateException;
import jol.types.table.Key;
import jol.types.table.StasisTable;
import jol.types.table.TableName;
public class LinearHashNTA extends StasisTable {
static LinearHashNTA catalog = null;
protected final Tuple header;
private final long[] rid;
protected Tuple registerTable(TableName name, Key key, Class[] type) throws UpdateException {
Tuple header = new Tuple(rid[0], rid[1], key, attributeTypes);
Tuple nameTup = new Tuple(name);
Tuple row = catalog.key().reconstruct(nameTup, header);
catalog.insert(row);
return row;
}
protected LinearHashNTA(Runtime context) throws UpdateException {
super(context, CATALOG_NAME, CATALOG_KEY, CATALOG_COLTYPES);
key = new Key(0);
long[] rootRid = Stasis.root_record();
synchronized (xactTable) {
long type = Stasis.record_type(ts.xid, rootRid);
if(type == -1) {
ts.dirty = true;
rid = Stasis.hash_create(ts.xid);
if(rid[0] != rootRid[0] || rid[1] != rootRid[1]) {
throw new IllegalStateException();
}
} else {
rid = new long[3];
rid[0] = rootRid[0];
rid[1] = rootRid[1];
}
header = CATALOG_SCHEMA;
}
}
public LinearHashNTA(Runtime context, TableName name, Key key,
Class[] attributeTypes) throws UpdateException {
super(context, name, key, attributeTypes);
int port = context.getPort();
if(catalog == null) {
catalog = new LinearHashNTA(context); // open catalog based on recordid
catalog.registerTable(CATALOG_NAME, CATALOG_KEY, CATALOG_COLTYPES);
}
TableName n = new TableName(port + ":" + name.scope, name.name);
TupleSet headerSet;
try {
headerSet = catalog.primary().lookupByKey(n);
} catch (BadKeyException e) {
throw new IllegalStateException(e);
}
Tuple catalogEntry;
synchronized (xactTable) {
if(headerSet.isEmpty()) {
ts.dirty = true;
rid = Stasis.hash_create(ts.xid);
// System.out.println("Alloced stasis table: " + n + ", " + key);
catalogEntry = registerTable(n, key, attributeTypes);
} else {
catalogEntry = headerSet.iterator().next();
rid = new long[3];
}
}
header = catalog.primary().key().projectValue(catalogEntry);
rid[0] = (Long)header.value(0);
rid[1] = (Long)header.value(1);
}
@Override
protected boolean add(byte[] keybytes, byte[] valbytes)
throws UpdateException {
synchronized (xactTable) {
ts.dirty = true;
byte[] oldvalbytes = Stasis.hash_insert(ts.xid, rid, keybytes, valbytes);
if(oldvalbytes != null) {
return (!Arrays.equals(valbytes, oldvalbytes));
}
return oldvalbytes == null;
}
}
@Override
public Long cardinality() {
return Stasis.hash_cardinality(-1, rid);
}
@Override
protected boolean remove(byte[] keybytes, byte[] valbytes)
throws UpdateException {
synchronized (xactTable) {
// 'bug for bug' compatible w/ BasicTable
byte[] oldvalbytes = lookup(keybytes);
if(oldvalbytes == null || ! Arrays.equals(oldvalbytes, valbytes)) {
return false;
} else {
Stasis.hash_remove(ts.xid, rid, keybytes);
ts.dirty = true;
return true;
}
// preferred implementation follows.
/*byte[] oldvalbytes = Stasis.hash_remove(ts.xid, rid, keybytes);
if(oldvalbytes != null && ! Arrays.equals(valbytes, oldvalbytes)) {
throw new UpdateException("attempt to remove non-existant tuple");
}
ts.dirty = true;
return oldvalbytes != null; */
}
}
@Override
protected byte[] lookup(byte[] keybytes) {
if(keybytes == null) throw new NullPointerException("keybytes is null!");
if(rid == null) throw new NullPointerException("rid is null!");
return Stasis.hash_lookup(-1, rid, keybytes);
}
@Override
protected Iterator<byte[][]> tupleBytes() {
return new Iterator<byte[][]>() {
private byte[] it = Stasis.hash_iterator(-1, rid);
private byte[][] current = new byte[2][];
private byte[][] next = new byte[2][];
private boolean hadNext = true;
Iterator<byte[][]> init() {
hadNext = Stasis.iterator_next(-1, it);
if(hadNext) {
next[0] = Stasis.iterator_key(-1,it);
next[1] = Stasis.iterator_value(-1, it);
Stasis.iterator_tuple_done(-1, it);
} else {
Stasis.iterator_close(-1, it);
}
return this;
}
public boolean hasNext() {
return hadNext;
}
public byte[][] next() {
if(hadNext) {
current = next;
next = new byte[2][];
hadNext = Stasis.iterator_next(-1,it);
if(hadNext) {
next[0] = Stasis.iterator_key(-1,it);
next[1] = Stasis.iterator_value(-1,it);
Stasis.iterator_tuple_done(-1,it);
} else {
Stasis.iterator_close(-1, it);
}
return current;
} else {
throw new IllegalStateException("next() called after end of iterator");
}
}
public void remove() {
throw new UnsupportedOperationException("No support for removal via table iterators yet...");
}
@Override
protected void finalize() throws Throwable {
try {
if(hadNext)
throw new IllegalStateException("detected non-exhausted iterator in finalize()");
} finally {
super.finalize();
}
}
}.init();
}
}

View file

@ -0,0 +1,65 @@
package org.stasis;
public class Stasis {
// Stasis operations
public static native int init();
public static native void deinit();
public static native long[] root_record();
public static boolean recordid_equals(long[] a, long[] b) { return a[0]==b[0]&&a[1]==b[1]; }
// Transaction initiation
public static native long begin();
public static native void commit(long xid);
public static native void abort(long xid);
public static native void prepare(long xid);
// Record operations
public static native long record_type(long xid, long[] rid);
// LinearHashNTA
public static native long[] hash_create(long xid);
public static native void hash_delete(long xid, long[] rid); // TODO need way to drop tables from lincoln...
public static native long hash_cardinality(long xid, long[] rid);
public static native byte[] hash_insert(long xid, long[] rid, byte[] keybytes, byte[] valbytes);
public static native byte[] hash_remove(long xid, long[] rid, byte[] keybytes);
public static native byte[] hash_lookup(long xid, long[] rid, byte[] keybytes);
public static native byte[] hash_iterator(long xid, long[] rid);
// Generic iterator interface
public static native void iterator_close(long xid, byte[] it);
public static native boolean iterator_next(long xid, byte[] it);
public static native byte[] iterator_key(long xid, byte[] it);
public static native byte[] iterator_value(long xid, byte[] it);
public static native void iterator_tuple_done(long xid, byte[] it);
public static void loadLibrary() {
System.loadLibrary("stasisjni");
}
public static void main(String[] arg) {
loadLibrary();
System.out.println("Tinit()");
init();
System.out.println("Stasis is running");
System.out.println("Tbegin()");
long xid = begin();
long[] root = root_record();
long rootType = record_type(xid,root);
System.out.println("Root record (page: " + root[0] + ", slot: " + root[1] + ") type is " + rootType);
if(rootType == -1) {
System.out.println("Uninitialized store");
System.out.println("Creating root record");
long[] hashRec = hash_create(xid);
if(!recordid_equals(hashRec,root)) {
throw new IllegalStateException("Bootstrapping didn't set the root record!!");
}
}
System.out.println("Tcommit()");
commit(xid);
deinit();
System.out.println("Successfully shut down. Exiting.");
}
}

View file

@ -0,0 +1,211 @@
#include "org_stasis_Stasis.h"
#include <stasis/transactional.h>
#include <stasis/page.h>
static jlongArray jlongArray_recordid(JNIEnv *e, recordid rid) {
jlong l[3] = {rid.page, rid.slot, rid.size};
jlongArray jla = (*e)->NewLongArray(e, 3);
if((*e)->ExceptionOccurred(e)) return 0;
(*e)->SetLongArrayRegion(e, jla, 0, 3, (jlong*)&l);
if((*e)->ExceptionOccurred(e)) return 0;
return jla;
}
static recordid recordid_jlongArray(JNIEnv *e, jlongArray jla) {
jlong l[3];
(*e)->GetLongArrayRegion(e, jla, 0, 3, (jlong*)&l);
if((*e)->ExceptionOccurred(e))
return NULLRID;
recordid ret = {l[0], l[1], l[2]};
return ret;
}
static byte * bytes_jbyteArray(JNIEnv *e, jbyteArray jba, size_t * sz) {
*sz = (*e)->GetArrayLength(e, jba) * sizeof(byte);
if((*e)->ExceptionOccurred(e)) return 0;
assert(sizeof(jbyte) == 1);
jbyte * ret = malloc(*sz);
(*e)->GetByteArrayRegion(e, jba, 0, *sz, (jbyte*)ret);
if((*e)->ExceptionOccurred(e)) return 0;
return (byte*)ret;
}
static jbyteArray jbyteArray_bytes(JNIEnv *e, byte* b, size_t sz) {
jbyteArray jba = (*e)->NewByteArray(e, sz);
(*e)->SetByteArrayRegion(e, jba, 0, sz, (jbyte*)b);
if((*e)->ExceptionOccurred(e)) return 0;
return jba;
}
static int initted = 0;
JNIEXPORT jint JNICALL Java_stasis_jni_Stasis_init
(JNIEnv *e, jclass c) {
if(!initted) {
Tinit();
}
initted++;
return initted;
}
JNIEXPORT void JNICALL Java_stasis_jni_Stasis_deinit
(JNIEnv *e, jclass c) {
initted--;
if(!initted) {
Tdeinit();
}
}
JNIEXPORT jlongArray JNICALL Java_stasis_jni_Stasis_root_1record
(JNIEnv *e, jclass c) {
return jlongArray_recordid(e, ROOT_RECORD);
}
JNIEXPORT jlong JNICALL Java_stasis_jni_Stasis_begin
(JNIEnv *e, jclass c) {
assert(initted);
jlong xid = (jlong) Tbegin();
return xid;
}
JNIEXPORT void JNICALL Java_stasis_jni_Stasis_commit
(JNIEnv *e, jclass c, jlong xid) {
printf("commiting %d\n", xid);
Tcommit((int)xid);
}
JNIEXPORT void JNICALL Java_stasis_jni_Stasis_abort
(JNIEnv *e, jclass c, jlong xid) {
Tabort((int)xid);
}
JNIEXPORT void JNICALL Java_stasis_jni_Stasis_prepare
(JNIEnv *e, jclass c, jlong xid) {
Tprepare((int)xid);
}
JNIEXPORT jlong JNICALL Java_stasis_jni_Stasis_record_1type
(JNIEnv *e, jclass c, jlong xid, jlongArray jlaRid) {
recordid rid = recordid_jlongArray(e, jlaRid);
if((*e)->ExceptionOccurred(e)) return 0;
return (jlong)TrecordType(xid, rid);
}
JNIEXPORT jlongArray JNICALL Java_stasis_jni_Stasis_hash_1create
(JNIEnv *e, jclass c, jlong xid) {
return jlongArray_recordid(e,ThashCreate(xid, VARIABLE_LENGTH, VARIABLE_LENGTH));
}
/* // ThashDelete is unimplemented...
JNIEXPORT void JNICALL Java_stasis_jni_Stasis_hash_1delete
(JNIEnv *e, jclass c, jlong xid, jlongArray jlaRid) {
ThashDelete(xid, recordid_jlongArray(e, jlaRid));
} */
/* // no equivalent call in stasis api
JNIEXPORT jlong JNICALL Java_stasis_jni_Stasis_hash_1cardinality
(JNIEnv *, jclass, jlong, jlongArray);
*/
JNIEXPORT jbyteArray JNICALL Java_stasis_jni_Stasis_hash_1insert
(JNIEnv *e, jclass c, jlong xid, jlongArray jbarid, jbyteArray jbakey, jbyteArray jbaval) {
recordid rid = recordid_jlongArray(e,jbarid);
if((*e)->ExceptionOccurred(e)) return 0;
size_t keylen;
byte * key = bytes_jbyteArray(e,jbakey, &keylen);
if((*e)->ExceptionOccurred(e)) return 0;
size_t vallen;
byte * val = bytes_jbyteArray(e,jbaval, &vallen);
if((*e)->ExceptionOccurred(e)) return 0;
byte * ret;
int retsize = ThashLookup((int)xid,rid,key,keylen,&ret);
jbyteArray jbaret;
if(retsize == -1) {
jbaret = 0;
} else {
jbaret = jbyteArray_bytes(e,ret,retsize);
}
if((*e)->ExceptionOccurred(e)) return 0;
// printf("Calling insert %lld %lld %lld %lx %lld %lx %lld (retsize %lld)", (long long)xid, (long long)rid.page, (long long)rid.slot, (unsigned long)key, (long long) keylen, (unsigned long)val, (long long) keylen, (long long)retsize); fflush(0);
ThashInsert((int)xid, rid, key, keylen, val, vallen);
// printf("Returned from insert"); fflush(0);
return jbaret;
}
JNIEXPORT jbyteArray JNICALL Java_stasis_jni_Stasis_hash_1remove
(JNIEnv *e, jclass c, jlong xid, jlongArray jbarid, jbyteArray jbakey) {
recordid rid = recordid_jlongArray(e, jbarid);
if((*e)->ExceptionOccurred(e)) return 0;
size_t keylen;
byte * key = bytes_jbyteArray(e,jbakey,&keylen);
if((*e)->ExceptionOccurred(e)) return 0;
byte * ret;
int retsize = ThashLookup((int)xid,rid,key,keylen,&ret);
jbyteArray jbaret;
if(retsize == -1) {
jbaret = 0;
} else {
jbaret = jbyteArray_bytes(e,ret,retsize);
}
if((*e)->ExceptionOccurred(e)) return 0;
ThashRemove((int)xid,rid,key,keylen);
return jbaret;
}
JNIEXPORT jbyteArray JNICALL Java_stasis_jni_Stasis_hash_1lookup
(JNIEnv *e, jclass c, jlong xid, jlongArray jbarid, jbyteArray jbakey) {
// printf("in lookup");
recordid rid = recordid_jlongArray(e, jbarid);
if((*e)->ExceptionOccurred(e)) return 0;
size_t keylen;
byte * key = bytes_jbyteArray(e,jbakey,&keylen);
if((*e)->ExceptionOccurred(e)) return 0;
byte * ret;
// printf("calling thashlookup");
int retsize = ThashLookup((int)xid,rid,key,keylen,&ret);
// printf("returned thashlookup");
jbyteArray jbaret;
if(retsize == -1) {
jbaret = 0;
} else {
jbaret = jbyteArray_bytes(e,ret,retsize);
}
if((*e)->ExceptionOccurred(e)) return 0;
return jbaret;
}
JNIEXPORT jbyteArray JNICALL Java_stasis_jni_Stasis_hash_1iterator
(JNIEnv *e, jclass c, jlong xid, jlongArray rid) {
lladdIterator_t * it = ThashGenericIterator(xid, recordid_jlongArray(e,rid));
return jbyteArray_bytes(e,(byte*)&it,sizeof(it));
}
JNIEXPORT void JNICALL Java_stasis_jni_Stasis_iterator_1close
(JNIEnv *e, jclass c, jlong xid, jbyteArray jbait) {
size_t sz;
lladdIterator_t** it = (lladdIterator_t**)bytes_jbyteArray(e,jbait,&sz);
Titerator_close(xid,*it);
}
JNIEXPORT jboolean JNICALL Java_stasis_jni_Stasis_iterator_1next
(JNIEnv *e, jclass c, jlong xid, jbyteArray jbait) {
size_t sz;
lladdIterator_t** it = (lladdIterator_t**)bytes_jbyteArray(e,jbait,&sz);
return (jboolean)Titerator_next((int)xid, *it);
}
JNIEXPORT jbyteArray JNICALL Java_stasis_jni_Stasis_iterator_1key
(JNIEnv *e, jclass c, jlong xid, jbyteArray jbait) {
size_t sz;
lladdIterator_t** it = (lladdIterator_t**)bytes_jbyteArray(e,jbait,&sz);
byte * key;
sz = Titerator_key(xid, *it, &key);
return jbyteArray_bytes(e,key,sz);
}
JNIEXPORT jbyteArray JNICALL Java_stasis_jni_Stasis_iterator_1value
(JNIEnv *e, jclass c, jlong xid, jbyteArray jbait) {
size_t sz;
lladdIterator_t** it = (lladdIterator_t**)bytes_jbyteArray(e,jbait,&sz);
byte * val;
sz = Titerator_value(xid, *it, &val);
return jbyteArray_bytes(e,val,sz);
}
JNIEXPORT void JNICALL Java_stasis_jni_Stasis_iterator_1tuple_1done
(JNIEnv *e, jclass c, jlong xid, jbyteArray jbait) {
size_t sz;
lladdIterator_t** it = (lladdIterator_t**)bytes_jbyteArray(e,jbait,&sz);
Titerator_tupleDone(xid, *it);
}

View file

@ -0,0 +1,173 @@
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class org_stasis_Stasis */
#ifndef _Included_org_stasis_Stasis
#define _Included_org_stasis_Stasis
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: org_stasis_Stasis
* Method: init
* Signature: ()I
*/
JNIEXPORT jint JNICALL Java_org_stasis_Stasis_init
(JNIEnv *, jclass);
/*
* Class: org_stasis_Stasis
* Method: deinit
* Signature: ()V
*/
JNIEXPORT void JNICALL Java_org_stasis_Stasis_deinit
(JNIEnv *, jclass);
/*
* Class: org_stasis_Stasis
* Method: root_record
* Signature: ()[J
*/
JNIEXPORT jlongArray JNICALL Java_org_stasis_Stasis_root_1record
(JNIEnv *, jclass);
/*
* Class: org_stasis_Stasis
* Method: begin
* Signature: ()J
*/
JNIEXPORT jlong JNICALL Java_org_stasis_Stasis_begin
(JNIEnv *, jclass);
/*
* Class: org_stasis_Stasis
* Method: commit
* Signature: (J)V
*/
JNIEXPORT void JNICALL Java_org_stasis_Stasis_commit
(JNIEnv *, jclass, jlong);
/*
* Class: org_stasis_Stasis
* Method: abort
* Signature: (J)V
*/
JNIEXPORT void JNICALL Java_org_stasis_Stasis_abort
(JNIEnv *, jclass, jlong);
/*
* Class: org_stasis_Stasis
* Method: prepare
* Signature: (J)V
*/
JNIEXPORT void JNICALL Java_org_stasis_Stasis_prepare
(JNIEnv *, jclass, jlong);
/*
* Class: org_stasis_Stasis
* Method: record_type
* Signature: (J[J)J
*/
JNIEXPORT jlong JNICALL Java_org_stasis_Stasis_record_1type
(JNIEnv *, jclass, jlong, jlongArray);
/*
* Class: org_stasis_Stasis
* Method: hash_create
* Signature: (J)[J
*/
JNIEXPORT jlongArray JNICALL Java_org_stasis_Stasis_hash_1create
(JNIEnv *, jclass, jlong);
/*
* Class: org_stasis_Stasis
* Method: hash_delete
* Signature: (J[J)V
*/
JNIEXPORT void JNICALL Java_org_stasis_Stasis_hash_1delete
(JNIEnv *, jclass, jlong, jlongArray);
/*
* Class: org_stasis_Stasis
* Method: hash_cardinality
* Signature: (J[J)J
*/
JNIEXPORT jlong JNICALL Java_org_stasis_Stasis_hash_1cardinality
(JNIEnv *, jclass, jlong, jlongArray);
/*
* Class: org_stasis_Stasis
* Method: hash_insert
* Signature: (J[J[B[B)[B
*/
JNIEXPORT jbyteArray JNICALL Java_org_stasis_Stasis_hash_1insert
(JNIEnv *, jclass, jlong, jlongArray, jbyteArray, jbyteArray);
/*
* Class: org_stasis_Stasis
* Method: hash_remove
* Signature: (J[J[B)[B
*/
JNIEXPORT jbyteArray JNICALL Java_org_stasis_Stasis_hash_1remove
(JNIEnv *, jclass, jlong, jlongArray, jbyteArray);
/*
* Class: org_stasis_Stasis
* Method: hash_lookup
* Signature: (J[J[B)[B
*/
JNIEXPORT jbyteArray JNICALL Java_org_stasis_Stasis_hash_1lookup
(JNIEnv *, jclass, jlong, jlongArray, jbyteArray);
/*
* Class: org_stasis_Stasis
* Method: hash_iterator
* Signature: (J[J)[B
*/
JNIEXPORT jbyteArray JNICALL Java_org_stasis_Stasis_hash_1iterator
(JNIEnv *, jclass, jlong, jlongArray);
/*
* Class: org_stasis_Stasis
* Method: iterator_close
* Signature: (J[B)V
*/
JNIEXPORT void JNICALL Java_org_stasis_Stasis_iterator_1close
(JNIEnv *, jclass, jlong, jbyteArray);
/*
* Class: org_stasis_Stasis
* Method: iterator_next
* Signature: (J[B)Z
*/
JNIEXPORT jboolean JNICALL Java_org_stasis_Stasis_iterator_1next
(JNIEnv *, jclass, jlong, jbyteArray);
/*
* Class: org_stasis_Stasis
* Method: iterator_key
* Signature: (J[B)[B
*/
JNIEXPORT jbyteArray JNICALL Java_org_stasis_Stasis_iterator_1key
(JNIEnv *, jclass, jlong, jbyteArray);
/*
* Class: org_stasis_Stasis
* Method: iterator_value
* Signature: (J[B)[B
*/
JNIEXPORT jbyteArray JNICALL Java_org_stasis_Stasis_iterator_1value
(JNIEnv *, jclass, jlong, jbyteArray);
/*
* Class: org_stasis_Stasis
* Method: iterator_tuple_done
* Signature: (J[B)V
*/
JNIEXPORT void JNICALL Java_org_stasis_Stasis_iterator_1tuple_1done
(JNIEnv *, jclass, jlong, jbyteArray);
#ifdef __cplusplus
}
#endif
#endif