changeset 725:7e1fa27b67ee

* Full status support * Insert support (not fully tested) * Unit tests for create + initial insert
author mas01mj
date Wed, 21 Jul 2010 14:27:07 +0000
parents 11fd16e1d8b3
children fe2282b9bfb0 0d1a7e4ed6cf
files bindings/java/build.xml bindings/java/ext/libAudioDB_JNI.c bindings/java/lib/junit.jar bindings/java/src/org/omras2/AudioDB.java bindings/java/src/org/omras2/Status.java bindings/java/test/TestCreate.java bindings/java/test/TestInsert.java bindings/java/test/TestQuery.java bindings/java/testfiles/testfeature
diffstat 9 files changed, 325 insertions(+), 44 deletions(-) [+]
line wrap: on
line diff
--- a/bindings/java/build.xml	Wed Jul 14 17:21:24 2010 +0000
+++ b/bindings/java/build.xml	Wed Jul 21 14:27:07 2010 +0000
@@ -6,7 +6,18 @@
 	<property name="src" location="src" />
 	<property name="ext" location="ext" />
 	<property name="gen" location="gen" />
+	<property name="test" location="test" />
 	<property name="build" location="build" />
+	
+	<path id="classpath.base">
+		<pathelement location="${build}" />
+	</path>
+
+	<path id="classpath.test">
+		<pathelement location="lib/junit.jar" />
+		<pathelement location="${test}" />
+		<path refid="classpath.base" />
+	</path>
 
 	<target name="init">
 		<tstamp />
@@ -14,7 +25,7 @@
 		<mkdir dir="${gen}" />
 	</target>
 
-	<target name="clean" depends="init">
+	<target name="clean" depends="init,clean-test">
 		<delete dir="${build}" />
 		<delete dir="${gen}" />
 	</target>
@@ -32,6 +43,7 @@
 				<linkerarg value="-fPIC" />
 				<linkerarg value="-G" />
 				<linkerarg value="-laudioDB" />
+				<linkerarg value="-lc" />
 				<linkerarg value="-o AudioDB_JNI.so" />
 			</linker>
 			<fileset dir="${ext}" includes="libAudioDB_JNI.c" />
@@ -43,5 +55,28 @@
 			</includepath>
 		</cpptasks:cc>
 	</target>
+
+
+	<target name="compile-test" depends="compile">
+		<javac srcdir="${test}">
+			<classpath refid="classpath.test"/>
+		</javac>
+	</target>
+	<target name="clean-test">
+		<delete>
+			<fileset dir="${test}" includes="**/*.class" />
+		</delete>
+	</target>
+
+	<target name="test" depends="compile-test">
+		<junit fork="yes">
+			<jvmarg value="-Djava.library.path=build" />
+			<classpath refid="classpath.test" />
+			<formatter type="brief" usefile="false" />
+			<test name="TestCreate" />
+			<test name="TestInsert" />
+			<test name="TestQuery" />
+		</junit>
+	</target>
 </project>
 
--- a/bindings/java/ext/libAudioDB_JNI.c	Wed Jul 14 17:21:24 2010 +0000
+++ b/bindings/java/ext/libAudioDB_JNI.c	Wed Jul 21 14:27:07 2010 +0000
@@ -1,8 +1,34 @@
+#include <sys/stat.h>
 #include "org_omras2_AudioDB.h"
 #include "org_omras2_AudioDB_Mode.h"
 #include <jni.h>
 #include "audioDB_API.h"
 #include <stdlib.h>
+#include <fcntl.h>
+
+// Following Ben's lead here!
+#define ADB_HEADER_FLAG_L2NORM 0x1
+#define ADB_HEADER_FLAG_POWER 0x4
+#define ADB_HEADER_FLAG_TIMES 0x20
+#define ADB_HEADER_FLAG_REFERENCES 0x40
+
+
+adb_t* get_handle(JNIEnv *env, jobject obj)
+{
+	// Fetch the adb pointer
+
+	adb_t *handle;
+	
+	jclass adbClass = (*env)->GetObjectClass(env, obj);
+	jfieldID fid = (*env)->GetFieldID(env, adbClass, "adbHandle", "J");
+	if(fid == NULL) {
+		return;
+	}
+	
+	handle = (adb_t*)((*env)->GetLongField(env, obj, fid)); 
+	(*env)->DeleteLocalRef(env, adbClass);
+	return handle;	
+}
 
 JNIEXPORT jboolean JNICALL Java_org_omras2_AudioDB_audiodb_1create (JNIEnv *env, jobject obj, jstring path, jint datasize, jint ntracks, jint datadim)
 {
@@ -17,6 +43,37 @@
 	if(!handle)
 		return JNI_FALSE;
 	
+	(*env)->ReleaseStringUTFChars(env, path, str);
+	return JNI_TRUE;
+}
+
+JNIEXPORT jboolean JNICALL Java_org_omras2_AudioDB_audiodb_1open (JNIEnv *env, jobject obj, jstring path, jobject mode)
+{
+	// TODO: If we have a handle, close the old one.
+	if(get_handle(env, obj))
+	{
+		return;
+	}
+
+	jclass modeClass = (*env)->FindClass(env, "org/omras2/AudioDB$Mode");
+	jmethodID getNameMethod = (*env)->GetMethodID(env, modeClass, "name", "()Ljava/lang/String;");
+	jstring value = (jstring)(*env)->CallObjectMethod(env, mode, getNameMethod);
+	const char* openMode = (*env)->GetStringUTFChars(env, value, 0);
+	const char* pathVal = (*env)->GetStringUTFChars(env, path, 0);
+	int modeVal = 0;
+	if(strcmp(openMode, "O_RDWR") == 0)
+	{
+		modeVal = O_RDWR;
+	}
+	else if(strcmp(openMode, "O_RDONLY") == 0)
+	{
+		modeVal = O_RDONLY;
+	}
+	else
+		return;
+
+	adb_t *handle;
+	handle = audiodb_open(pathVal, modeVal);
 	jclass adbClass = (*env)->GetObjectClass(env, obj);
 	jfieldID fid = (*env)->GetFieldID(env, adbClass, "adbHandle", "J");
 	if(fid == NULL) {
@@ -24,22 +81,56 @@
 	}
 	(*env)->SetLongField(env, obj, fid, (long)handle);
 	(*env)->DeleteLocalRef(env, adbClass);
-	(*env)->ReleaseStringUTFChars(env, path, str);
-	return JNI_TRUE;
-}
-
-JNIEXPORT jboolean JNICALL Java_org_omras2_AudioDB_audiodb_1open (JNIEnv *env, jobject obj, jstring path, jobject mode)
-{
-	jclass modeClass = (*env)->FindClass(env, "org/omras2/AudioDB$Mode");
-	jmethodID getNameMethod = (*env)->GetMethodID(env, modeClass, "name", "()Ljava/lang/String;");
-	jstring value = (jstring)(*env)->CallObjectMethod(env, mode, getNameMethod);
-	const char* openMode = (*env)->GetStringUTFChars(env, value, 0);
 
 	return JNI_TRUE;
 }
 
-JNIEXPORT void JNICALL Java_org_omras2_AudioDB_insert(JNIEnv *env, jobject obj)
+JNIEXPORT void JNICALL Java_org_omras2_AudioDB_audiodb_1close (JNIEnv *env, jobject obj)
 {
+	adb_t *handle = get_handle(env, obj);
+	if(!handle)
+		return;
+
+	audiodb_close(handle);
+	
+	jclass adbClass = (*env)->GetObjectClass(env, obj);
+	jfieldID fid = (*env)->GetFieldID(env, adbClass, "adbHandle", "J");
+	
+	if(fid == NULL) {
+		return;
+	}
+
+	(*env)->SetLongField(env, obj, fid, 0);
+	(*env)->DeleteLocalRef(env, adbClass);
+}
+
+JNIEXPORT jboolean JNICALL Java_org_omras2_AudioDB_audiodb_1insert_1path(JNIEnv *env, jobject obj, jstring key, jstring features, jstring power, jstring times)
+{
+	adb_t *handle = get_handle(env, obj);
+	if(!handle)
+		return JNI_FALSE;
+	
+	adb_insert_t* ins = (adb_insert_t *)malloc(sizeof(adb_insert_t));
+	ins->key = NULL;
+	ins->features = NULL;
+	ins->power = NULL;
+	ins->times = NULL;
+
+	if(key)
+		ins->key = (*env)->GetStringUTFChars(env, key, 0);
+	if(features)
+		ins->features = (*env)->GetStringUTFChars(env, features, 0);
+	if(power)
+		ins->power = (*env)->GetStringUTFChars(env, power, 0);
+	if(times)
+		ins->times = (*env)->GetStringUTFChars(env, times, 0);
+
+	int result = audiodb_insert(handle, ins);
+
+	if(result)
+		return JNI_FALSE;
+	
+	return JNI_TRUE;
 }
 
 JNIEXPORT void JNICALL Java_org_omras2_AudioDB_query(JNIEnv *env, jobject obj)
@@ -48,20 +139,9 @@
 
 JNIEXPORT jobject JNICALL Java_org_omras2_AudioDB_audiodb_1status(JNIEnv *env, jobject obj)
 {
-
-	// Fetch the adb pointer
-
-	adb_t *handle;
-	
-	jclass adbClass = (*env)->GetObjectClass(env, obj);
-	jfieldID fid = (*env)->GetFieldID(env, adbClass, "adbHandle", "J");
-	if(fid == NULL) {
-		return;
-	}
-	
-	handle = (adb_t*)((*env)->GetLongField(env, obj, fid)); 
-	(*env)->DeleteLocalRef(env, adbClass);
-	
+	adb_t *handle = get_handle(env, obj);
+	if(!handle)
+		return NULL;
 	adb_status_t *status;
 	status = (adb_status_t *)malloc(sizeof(adb_status_t));
 	int flags = audiodb_status(handle, status);	
@@ -77,11 +157,48 @@
 
 	jobject result = (*env)->NewObject(env, statusClass, cid);
 
-	fid = (*env)->GetFieldID(env, statusClass, "numFiles", "I");
-	if(fid == NULL) {
-		return;
-	}
+	// This needs a macro!
+	jfieldID fid = (*env)->GetFieldID(env, statusClass, "numFiles", "I");
+	if(fid == NULL) return;
 	(*env)->SetIntField(env, result, fid, status->numFiles);
+	
+	fid = (*env)->GetFieldID(env, statusClass, "dim", "I");
+	if(fid == NULL) return;
+	(*env)->SetIntField(env, result, fid, status->dim);
+	
+	fid = (*env)->GetFieldID(env, statusClass, "dudCount", "I");
+	if(fid == NULL) return;
+	(*env)->SetIntField(env, result, fid, status->dudCount);
+	
+	fid = (*env)->GetFieldID(env, statusClass, "nullCount", "I");
+	if(fid == NULL) return;
+	(*env)->SetIntField(env, result, fid, status->nullCount);
+	
+	fid = (*env)->GetFieldID(env, statusClass, "length", "I");
+	if(fid == NULL) return;
+	(*env)->SetIntField(env, result, fid, status->length);
+	
+	fid = (*env)->GetFieldID(env, statusClass, "dataRegionSize", "I");
+	if(fid == NULL) return;
+	(*env)->SetIntField(env, result, fid, status->data_region_size);
+
+	// Flags
+	
+	fid = (*env)->GetFieldID(env, statusClass, "isL2Normed", "Z");
+	if(fid == NULL) return;
+	(*env)->SetBooleanField(env, result, fid, (status->flags & ADB_HEADER_FLAG_L2NORM));
+	
+	fid = (*env)->GetFieldID(env, statusClass, "hasPower", "Z");
+	if(fid == NULL) return;
+	(*env)->SetBooleanField(env, result, fid, (status->flags & ADB_HEADER_FLAG_POWER));
+	
+	fid = (*env)->GetFieldID(env, statusClass, "hasTimes", "Z");
+	if(fid == NULL) return;
+	(*env)->SetBooleanField(env, result, fid, (status->flags & ADB_HEADER_FLAG_TIMES));
+	
+	fid = (*env)->GetFieldID(env, statusClass, "hasReferences", "Z");
+	if(fid == NULL) return;
+	(*env)->SetBooleanField(env, result, fid, (status->flags & ADB_HEADER_FLAG_REFERENCES));
 
 	(*env)->DeleteLocalRef(env, statusClass);
 
Binary file bindings/java/lib/junit.jar has changed
--- a/bindings/java/src/org/omras2/AudioDB.java	Wed Jul 14 17:21:24 2010 +0000
+++ b/bindings/java/src/org/omras2/AudioDB.java	Wed Jul 21 14:27:07 2010 +0000
@@ -6,12 +6,12 @@
 {
 	public native boolean audiodb_create(String path, int datasize, int ntracks, int datadim);
 	public native boolean audiodb_open(String path, Mode mode);
+	public native void audiodb_close();
 	public native Status audiodb_status();
-
-//	public native void insert();
+	public native boolean audiodb_insert_path(String key, String features, String power, String times);
 //	public native void query();
 
-	public enum Mode { O_RDONLY, O_RDRW }
+	public enum Mode { O_RDONLY, O_RDWR }
 
 	private File path;
 	private long adbHandle;
@@ -21,6 +21,27 @@
 		this.path = path;
 	}
 
+	public void close()
+	{
+		audiodb_close();
+	}
+
+	public boolean insert(File features)
+	{
+		return audiodb_insert_path(null, features.getPath(), null, null);
+	}
+	
+	public boolean insert(String key, File features)
+	{
+		return audiodb_insert_path(key, features.getPath(), null, null);
+	}
+	
+	public boolean insert(String key, File features, File power, File times)
+	{
+		return audiodb_insert_path(key, features.getPath(), (power == null ? null : power.getPath()), (times == null ? null : times.getPath()));
+	}
+	
+
 	public boolean create(int datasize, int ntracks, int datadim)
 	{
 		return audiodb_create(path.toString(), datasize, ntracks, datadim);
@@ -45,9 +66,11 @@
 	{
 		AudioDB testDB = new AudioDB(new File("test.adb"));
 		testDB.create(5, 5, 12);
-//		testDB.open(Mode.O_RDRW);
+		testDB.open(Mode.O_RDWR);
+		testDB.insert(new File("testfiles/testfeature"));
 		Status status = testDB.getStatus();
 		System.out.println("Num files: "+status.getNumFiles());
+		testDB.close();
 	}
 }
 
--- a/bindings/java/src/org/omras2/Status.java	Wed Jul 14 17:21:24 2010 +0000
+++ b/bindings/java/src/org/omras2/Status.java	Wed Jul 21 14:27:07 2010 +0000
@@ -4,14 +4,14 @@
 
 public class Status
 {
-	@Getter @Setter private int numFiles;
-	@Getter @Setter private int dims;
-	@Getter @Setter private int dudCount;
-	@Getter @Setter private int nullCount;
-	@Getter @Setter private int length;
-	@Getter @Setter private int dataRegionSize;
-	@Getter @Setter private boolean isL2Normed;
-	@Getter @Setter private boolean hasPower;
-	@Getter @Setter private boolean hasTimes;
-	@Getter @Setter private boolean hasRefs;
+	@Getter private int numFiles;
+	@Getter private int dim;
+	@Getter private int dudCount;
+	@Getter private int nullCount;
+	@Getter private int length;
+	@Getter private int dataRegionSize;
+	@Getter private boolean isL2Normed;
+	@Getter private boolean hasPower;
+	@Getter private boolean hasTimes;
+	@Getter private boolean hasReferences;
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/bindings/java/test/TestCreate.java	Wed Jul 21 14:27:07 2010 +0000
@@ -0,0 +1,35 @@
+import junit.framework.*;
+import java.io.File;
+import org.omras2.*;
+
+public class TestCreate extends TestCase
+{
+	File testDBFile;
+
+	protected void setUp()
+	{
+		testDBFile = new File("testfiles/test.adb");
+		if(testDBFile.exists())
+			testDBFile.delete();
+	}
+
+	public void testCreateNew()
+	{
+		AudioDB testDB = new AudioDB(testDBFile);
+		assertTrue("DB created", testDB.create(5, 5, 12));
+		assertTrue("Test DB created on FS", testDBFile.exists());
+		assertTrue("Test DB has length > 0", testDBFile.length() > 0);
+	}
+
+	public void testReplaceExisting()
+	{
+		AudioDB testDB = new AudioDB(testDBFile);
+		assertTrue("DB created", testDB.create(5, 5, 12));
+
+		// Try to create again
+		testDB = new AudioDB(testDBFile);
+		assertFalse("DB not created", testDB.create(5, 5, 12));
+		assertTrue("Test DB still exists on FS", testDBFile.exists());
+		assertTrue("Test DB still has length > 0", testDBFile.length() > 0);
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/bindings/java/test/TestInsert.java	Wed Jul 21 14:27:07 2010 +0000
@@ -0,0 +1,39 @@
+import junit.framework.*;
+import java.io.File;
+import org.omras2.*;
+
+public class TestInsert extends TestCase
+{
+	File testDBFile;
+	File testFeatureFile;
+	protected void setUp()
+	{
+		testDBFile = new File("testfiles/test.adb");
+		testFeatureFile = new File("testfiles/testfeature");
+		if(testDBFile.exists())
+			testDBFile.delete();
+	}
+
+	public void testInsertFile()
+	{
+		AudioDB testDB = new AudioDB(testDBFile);
+		assertTrue("DB created", testDB.create(1, 1, 1));
+		testDB.open(AudioDB.Mode.O_RDWR);
+		assertTrue("Insert feature file", testDB.insert(testFeatureFile));
+		Status status = testDB.getStatus();
+		assertEquals("One feature in db", 1, status.getNumFiles());
+		assertEquals("1D Feature", 1, status.getDim());
+		System.out.println(status.hasReferences());
+		System.out.println(status.isL2Normed());
+		System.out.println(status.hasPower());
+		System.out.println(status.hasTimes());
+	}
+
+	public void testInsertFileReadOnly()
+	{
+		AudioDB testDB = new AudioDB(testDBFile);
+		assertTrue("DB created", testDB.create(1, 1, 1));
+		testDB.open(AudioDB.Mode.O_RDONLY);
+		assertFalse("Insert feature file", testDB.insert(testFeatureFile));
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/bindings/java/test/TestQuery.java	Wed Jul 21 14:27:07 2010 +0000
@@ -0,0 +1,32 @@
+import junit.framework.*;
+import java.io.File;
+import org.omras2.*;
+
+public class TestQuery extends TestCase
+{
+	File testDBFile;
+	File testFeatureFile;
+	protected void setUp()
+	{
+		testDBFile = new File("testfiles/test.adb");
+		testFeatureFile = new File("testfiles/testfeature");
+		if(testDBFile.exists())
+			testDBFile.delete();
+	}
+
+	public void testQuery()
+	{
+		// Insert the same feature twice
+		AudioDB testDB = new AudioDB(testDBFile);
+		assertTrue("DB created", testDB.create(1, 2, 1));
+		testDB.open(AudioDB.Mode.O_RDWR);
+		assertTrue("Insert feature file", testDB.insert("feat1", testFeatureFile));
+		assertTrue("Insert feature file again", testDB.insert("feat2", testFeatureFile));
+		testDB.close();
+
+		testDB.open(AudioDB.Mode.O_RDONLY);
+		Status status = testDB.getStatus();
+		assertEquals("Two features", 2, status.getNumFiles());
+	}
+
+}
Binary file bindings/java/testfiles/testfeature has changed