diff --git a/CMakeLists.txt b/CMakeLists.txt
index 0ea22d9..8944201 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -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")
diff --git a/lang/CMakeLists.txt b/lang/CMakeLists.txt
index fa23e0d..c630cfe 100644
--- a/lang/CMakeLists.txt
+++ b/lang/CMakeLists.txt
@@ -1,2 +1,3 @@
SUBDIRS(perl)
SUBDIRS(ruby)
+SUBDIRS(java)
\ No newline at end of file
diff --git a/lang/java/CMakeLists.txt b/lang/java/CMakeLists.txt
new file mode 100644
index 0000000..0b18ebb
--- /dev/null
+++ b/lang/java/CMakeLists.txt
@@ -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)
\ No newline at end of file
diff --git a/lang/java/build.xml b/lang/java/build.xml
new file mode 100644
index 0000000..9dde4e6
--- /dev/null
+++ b/lang/java/build.xml
@@ -0,0 +1,4 @@
+
+
+
+
diff --git a/lang/java/org/stasis/LinearHashNTA.java b/lang/java/org/stasis/LinearHashNTA.java
new file mode 100644
index 0000000..b32b484
--- /dev/null
+++ b/lang/java/org/stasis/LinearHashNTA.java
@@ -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 tupleBytes() {
+ return new Iterator() {
+ 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 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();
+ }
+
+}
diff --git a/lang/java/org/stasis/Stasis.java b/lang/java/org/stasis/Stasis.java
new file mode 100644
index 0000000..4ad478e
--- /dev/null
+++ b/lang/java/org/stasis/Stasis.java
@@ -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.");
+ }
+}
diff --git a/lang/java/org_stasis_Stasis.c b/lang/java/org_stasis_Stasis.c
new file mode 100644
index 0000000..596abc8
--- /dev/null
+++ b/lang/java/org_stasis_Stasis.c
@@ -0,0 +1,211 @@
+#include "org_stasis_Stasis.h"
+#include
+#include
+
+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);
+}
diff --git a/lang/java/org_stasis_Stasis.h b/lang/java/org_stasis_Stasis.h
new file mode 100644
index 0000000..58031b5
--- /dev/null
+++ b/lang/java/org_stasis_Stasis.h
@@ -0,0 +1,173 @@
+/* DO NOT EDIT THIS FILE - it is machine generated */
+#include
+/* 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