java writer works. reader needs a fix still

This commit is contained in:
Troy D. Hanson
2012-03-26 23:29:45 -04:00
parent 8284237c7a
commit 00c575bb35
6 changed files with 276 additions and 1 deletions

200
kvjava/KVJava.c Normal file
View File

@@ -0,0 +1,200 @@
#include <limits.h>
#include <jni.h>
#include "KVJava.h"
#include "kvspool.h"
typedef struct {
void *spr;
void *spw;
void *set;
char dir[PATH_MAX];
} kvsp_handle_t;
/* retrieve the handle from the object, creating it if need be */
static kvsp_handle_t *get_handle(JNIEnv *env, jobject obj) {
jclass cls = (*env)->GetObjectClass(env, obj);
jfieldID id = (*env)->GetFieldID(env, cls, "kvsp_handle", "J");
jlong kvsp_handle_jlong = (*env)->GetLongField(env, obj, id);
kvsp_handle_t *kvsp_handle = (kvsp_handle_t*)kvsp_handle_jlong;
if (kvsp_handle == NULL) {
kvsp_handle = calloc(1, sizeof(kvsp_handle_t));
kvsp_handle->set = kv_set_new();
(*env)->SetLongField(env, obj, id, (long)kvsp_handle);
}
return kvsp_handle;
}
static const char *get_dir(JNIEnv *env, jobject obj) {
kvsp_handle_t *handle = get_handle(env, obj);
jclass cls = (*env)->GetObjectClass(env, obj);
jfieldID id = (*env)->GetFieldID(env, cls, "dir", "Ljava/lang/String;");
jstring dirj = (jstring) (*env)->GetObjectField(env, obj, id);
kvsp_handle_t *h = get_handle(env, obj);
const char* dir = (*env)->GetStringUTFChars(env, dirj, 0);
strncpy(h->dir, dir, sizeof(h->dir));
(*env)->ReleaseStringUTFChars(env, dirj, dir);
return h->dir;
}
static unsigned char get_blocking(JNIEnv *env, jobject obj) {
jclass cls = (*env)->GetObjectClass(env, obj);
jfieldID id = (*env)->GetFieldID(env, cls, "blocking", "Z");
jboolean blockingj = (jboolean) (*env)->GetBooleanField(env, obj, id);
unsigned char blocking = (unsigned char)blockingj;
return blocking;
}
jint throwFileNotFound(JNIEnv *env, char* message) {
jclass exClass;
char *className = "java/io/IOException";
exClass = (*env)->FindClass(env, className);
if (exClass == NULL) {
//return throwNoClassDefError(env, className);
return -1;
}
return (*env)->ThrowNew(env, exClass, message);
}
jobject kvs_to_map(JNIEnv* env, void *set) {
jclass mapClass = NULL;
static jmethodID init = NULL;
static jmethodID put = NULL;
//if (mapClass == NULL) {
mapClass = (*env)->FindClass(env, "java/util/HashMap");
//}
if (mapClass == NULL) {
return NULL;
}
jsize map_len = kv_len(set);
if (init == NULL) {
init = (*env)->GetMethodID(env, mapClass, "<init>", "(I)V");
}
jobject obj = (*env)->NewObject(env, mapClass, init, map_len);
if (put == NULL) {
put = (*env)->GetMethodID(env, mapClass, "put", "(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;");
}
kv_t *kv = NULL;
while ((kv = kv_next(set, kv))) {
jstring key = (*env)->NewStringUTF(env, kv->key);
jstring val = (*env)->NewStringUTF(env, kv->val);
(*env)->CallObjectMethod(env, obj, put, key, val);
}
return obj;
}
JNIEXPORT jobject JNICALL Java_KVJava_read(JNIEnv * env, jobject obj) {
kvsp_handle_t *h = get_handle(env, obj);
jobject ret;
if (h->spr == NULL) {
const char *dir = get_dir(env, obj);
h->spr = kv_spoolreader_new(dir);
if (h->spr == NULL) {
throwFileNotFound(env,"Failed to open spool");
return NULL;
}
}
int blocking = get_blocking(env, obj);
int rc = kv_spool_read(h->spr, h->set, blocking);
if (rc < 0) {
ret = kvs_to_map(env, h->set);
} else if (rc == 0) {
// TODO non blocking support
} else {
}
return ret;
}
int map_to_kvs(JNIEnv* env, jobject obj, void *set) {
jclass mapClass = NULL;
jclass setClass = NULL;
jclass iteratorClass = NULL;
static jmethodID get = NULL;
static jmethodID keySet = NULL;
static jmethodID iterator = NULL;
static jmethodID hasNext = NULL;
static jmethodID next = NULL;
//if (mapClass == NULL) {
mapClass = (*env)->FindClass(env, "java/util/HashMap");
setClass = (*env)->FindClass(env, "java/util/Set");
iteratorClass = (*env)->FindClass(env, "java/util/Iterator");
//}
if (get == NULL) {
get = (*env)->GetMethodID(env, mapClass, "get", "(Ljava/lang/Object;)Ljava/lang/Object;");
}
if (keySet == NULL) {
keySet = (*env)->GetMethodID(env, mapClass, "keySet", "()Ljava/util/Set;");
}
if (iterator == NULL) {
iterator = (*env)->GetMethodID(env, setClass, "iterator", "()Ljava/util/Iterator;");
}
if (hasNext == NULL) {
hasNext = (*env)->GetMethodID(env, iteratorClass, "hasNext", "()Z");
}
if (next == NULL) {
next = (*env)->GetMethodID(env, iteratorClass, "next", "()Ljava/lang/Object;");
}
jobject sets = (*env)->CallObjectMethod(env, obj, keySet);
jobject iter = (*env)->CallObjectMethod(env, sets, iterator);
jmethodID toStringK = NULL;
jmethodID toStringV = NULL;
jclass cls = NULL;
while ((*env)->CallBooleanMethod(env, iter, hasNext)) {
jobject key = (*env)->CallObjectMethod(env, iter, next);
jobject val = (*env)->CallObjectMethod(env, obj, get, key);
cls = (*env)->GetObjectClass(env, key);
toStringK = (*env)->GetMethodID(env, cls, "toString", "()Ljava/lang/String;");
key = (*env)->CallObjectMethod(env, key, toStringK);
cls = (*env)->GetObjectClass(env, val);
toStringV = (*env)->GetMethodID(env, cls, "toString", "()Ljava/lang/String;");
val = (*env)->CallObjectMethod(env, val, toStringV);
const char* keyc = (*env)->GetStringUTFChars(env, key, 0);
const char* valc = (*env)->GetStringUTFChars(env, val, 0);
kv_add(set, keyc, (*env)->GetStringUTFLength(env, key), valc, (*env)->GetStringUTFLength(env, val));
(*env)->ReleaseStringUTFChars(env, key, keyc);
(*env)->ReleaseStringUTFChars(env, val, valc);
}
//return obj;
return -1;
}
JNIEXPORT void JNICALL Java_KVJava_write(JNIEnv *env, jobject obj, jobject map) {
kvsp_handle_t *h = get_handle(env, obj);
if (h->spw == NULL) {
const char *dir = get_dir(env, obj);
h->spw = kv_spoolwriter_new(dir);
if (h->spw == NULL) {
throwFileNotFound(env,"Failed to open spool");
return;
}
}
map_to_kvs(env, map, h->set);
kv_spool_write(h->spw, h->set);
}
JNIEXPORT void JNICALL Java_KVJava_close(JNIEnv *env, jobject obj) {
jclass cls = (*env)->GetObjectClass(env, obj);
jfieldID kvsp_handle_id = (*env)->GetFieldID(env, cls, "kvsp_handle", "J");
jlong kvsp_handle_jlong = (*env)->GetLongField(env, obj, kvsp_handle_id);
kvsp_handle_t *kvsp_handle = (kvsp_handle_t*)kvsp_handle_jlong;
if (kvsp_handle == NULL) return;
if (kvsp_handle->set) kv_set_free(kvsp_handle->set);
if (kvsp_handle->spr) kv_spoolreader_free(kvsp_handle->spr);
if (kvsp_handle->spw) kv_spoolwriter_free(kvsp_handle->spw);
(*env)->SetLongField(env, obj, kvsp_handle_id, 0);
}

31
kvjava/KVJava.java Normal file
View File

@@ -0,0 +1,31 @@
/* the KVJava object has methods implemented as JNI. This file is the Java
* part of the class, which is compiled as usual with javac, then a
* C header is generated from it (using javah -jni) for the JNI functions.
* The implementation of the JNI functions in C is in KVJava.c. This gets
* built into a shared library (which must be installed to a place the
* dynamic linker can find it at runtime).
*/
import java.util.HashMap;
import java.lang.String;
public class KVJava {
static {
System.loadLibrary("KVJava"); // dynamically load native libKVJava.so
}
public boolean blocking;
private String dir; /* the spool directory */
private long kvsp_handle; /* a C structure address, opaque to Java */
public KVJava(String _dir) {
dir = _dir;
blocking = true;
}
public native HashMap<String,String> read();
public native void write(HashMap<String,String> map);
public native void close();
}

15
kvjava/Makefile Normal file
View File

@@ -0,0 +1,15 @@
all: KVJava.class libKVJava.so
JNIINC=/usr/lib/jvm/java-6-openjdk/include/
JNILIB=/usr/lib/jvm/java-6-openjdk/jre/lib/i386/
KVJava.class: KVJava.java
javac $<
libKVJava.so: KVJava.class KVJava.c
javah -jni KVJava
$(CC) -o $@ -fPIC -shared -I. -I${JNIINC} -I../include KVJava.c -L../src/ -L.. -lkvspool -L${JNILIB} -ljava -static-libgcc
.PHONY: clean
clean:
rm -f KVJava.class KVJava.h

View File

@@ -1 +0,0 @@
This Java interface to kvspool is not yet integrated into the build.

5
kvjava/TODO Normal file
View File

@@ -0,0 +1,5 @@
JNIINC and JNILIB need to be done in autoconf test
the spool writer works but there's a bug in the reader hash map construction
javac TestKJava.java
java TestKVJava
should be included in build process

25
kvjava/TestKVJava.java Normal file
View File

@@ -0,0 +1,25 @@
import java.util.HashMap;
import java.util.Map;
import java.util.Iterator;
import java.lang.String;
public class TestKVJava {
static {
System.loadLibrary("KVJava");
}
public static void main(String args[]) {
KVJava kv = new KVJava("/tmp/spool");
HashMap h = new HashMap();
h.put("user", "troy");
h.put("id", new Integer(10));
kv.write(h);
HashMap m = kv.read();
for (Map.Entry<String, String> entry : m.entrySet()) {
String key = entry.getKey();
String val = entry.getValue();
System.out.println(key + ": " + val);
}
}
}