Mercurial > hg > audiodb
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);
--- 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()); + } + +}