/* * com_e4graph_Storage.cpp -- * * This file contains implementations of the natives of the * class com.e4graph.Storage. * * NOTE: At the end of this file, there is one native for the class * com_e4graph_StorageIterator. It is in this file so that it can use * the file-static cache data structures. * * Copyright (c) 2000-2003, JYL Software Inc. * * Permission is hereby granted, free of charge, to any person obtaining * a copy of this software and associated documentation files (the * "Software"), to deal in the Software without restriction, including * without limitation the rights to use, copy, modify, merge, publish, * distribute, sublicense, and/or sell copies of the Software, and to * permit persons to whom the Software is furnished to do so, subject to * the following conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE, EVEN IF * JYL SOFTWARE INC. IS MADE AWARE OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "e4graph.h" #include "j4graph.h" #define STATIC_STORAGE_SIZE 128 typedef struct StorageCacheRecord { e4_Storage s; int generation; } StorageCacheRecord; static StorageCacheRecord staticStorages[STATIC_STORAGE_SIZE]; static int storageSize = STATIC_STORAGE_SIZE; StorageCacheRecord *storages = staticStorages; static int generation = 0; /* * Object used to lock storage cache. */ jobject storageLock = NULL; /* * These classes represent exception types. */ jclass clsStorageCreationException = NULL; jclass clsStorageIsNotOpenException = NULL; jclass clsIncorrectVertexTypeException = NULL; jclass clsInvalidPositionException = NULL; jclass clsNoSuchNodeException = NULL; jclass clsNoSuchVertexException = NULL; jmethodID storageCreationExceptionCMID = NULL; jmethodID storageIsNotOpenExceptionCMID = NULL; jmethodID incorrectVertexTypeExceptionCMID = NULL; jmethodID invalidPositionExceptionCMID = NULL; jmethodID noSuchNodeExceptionCMID = NULL; jmethodID noSuchVertexExceptionCMID = NULL; /* * Class objects for Storage, Node, Value and Vertex, and method IDs * for their constructors: */ jclass clsStorage = NULL; jclass clsNode = NULL; jclass clsValue = NULL; jclass clsVertex = NULL; jmethodID storageCMID = NULL; jmethodID nodeCMID = NULL; jmethodID valueCMID = NULL; jmethodID vertexCMID = NULL; /* * These field IDs are for access to the fields of Storage, Node and Vertex. */ jfieldID sIndexID = NULL; jfieldID nIndexID = NULL; jfieldID nsIndexID = NULL; jfieldID vIndexID = NULL; jfieldID vsIndexID = NULL; /* * These field IDs are for access to the various fields of Value. */ jfieldID typeID = NULL; jfieldID integerValueID = NULL; jfieldID doubleValueID = NULL; jfieldID stringValueID = NULL; jfieldID bytesValueID = NULL; jfieldID nodeValueID = NULL; /* * Lock access to the storage cache. */ static void LockStorages(JNIEnv *envp) { envp->MonitorEnter(storageLock); } /* * Unlock access to the storage cache. */ static void ReleaseStorages(JNIEnv *envp) { envp->MonitorExit(storageLock); } /* * Check that a given index represents a legal storage. */ bool GetValidStorage(JNIEnv *envp, int i, int g, e4_Storage &ss) { if (i < 0) { envp->ThrowNew(clsStorageIsNotOpenException, "negative index"); return false; } LockStorages(envp); if (i >= storageSize) { envp->ThrowNew(clsStorageIsNotOpenException, "index out of range"); ReleaseStorages(envp); return false; } if (!storages[i].s.IsValid()) { envp->ThrowNew(clsStorageIsNotOpenException, "invalid storage"); ReleaseStorages(envp); return false; } if (storages[i].generation != g) { envp->ThrowNew(clsStorageIsNotOpenException, "incorrect generation counter"); ReleaseStorages(envp); return false; } ss = storages[i].s; ReleaseStorages(envp); return true; } /* * Allocate cache space for a storage. */ static int AllocStorageIndex(JNIEnv *envp, e4_Storage s) { StorageCacheRecord *newStorages; int i, newStorageSize; /* * Locate a space in the current cache. */ LockStorages(envp); for (i = 0; i < storageSize; i++) { if (!storages[i].s.IsValid()) { storages[i].s = s; storages[i].generation = generation++; ReleaseStorages(envp); return i; } } /* * Reallocate the cache to a bigger cache. */ newStorageSize = storageSize + STATIC_STORAGE_SIZE; newStorages = new StorageCacheRecord [newStorageSize]; for (i = 0; i < storageSize; i++) { newStorages[i] = storages[i]; storages[i].s = invalidStorage; } for (i = storageSize; i < newStorageSize; i++) { newStorages[i].s = invalidStorage; } if (storages != staticStorages) { delete [] storages; } storages = newStorages; storageSize = newStorageSize; /* * Locate a space in the current cache. */ for (i = 0; i < storageSize; i++) { if (!storages[i].s.IsValid()) { storages[i].s = s; storages[i].generation = generation++; ReleaseStorages(envp); return i; } } /* * Still cannot find space in the cache, abort. */ ReleaseStorages(envp); envp->ThrowNew(clsStorageCreationException, "cannot allocate cache for storage"); return -1; } /* * Set the i'th storage with the given generation to the supplied storage. * * This is used most often to set a given storage to invalidStorage, to * release our reference to the underlying e4Graph storage. */ void SetValidStorage(JNIEnv *envp, jint index, jint g, e4_Storage ns) { if (index < 0) { envp->ThrowNew(clsStorageIsNotOpenException, "negative index"); return; } LockStorages(envp); if (index >= storageSize) { envp->ThrowNew(clsStorageIsNotOpenException, "index out of range"); ReleaseStorages(envp); return; } if (!storages[index].s.IsValid()) { envp->ThrowNew(clsStorageIsNotOpenException, "invalid storage"); ReleaseStorages(envp); return; } if (storages[index].generation != g) { envp->ThrowNew(clsStorageIsNotOpenException, "incorrect generation counter"); ReleaseStorages(envp); return; } storages[index].s = ns; ReleaseStorages(envp); } /* * Retrieve a node from its storage. */ bool GetValidNode(JNIEnv *envp, int sindex, int gen, int nindex, e4_Node &nn) { e4_NodeUniqueID nuid; e4_Storage s; if (!GetValidStorage(envp, sindex, gen, s)) { return false; } nuid.SetID(nindex); nuid.SetSP(s.GetTemporaryUID()); if (s.GetNodeFromID(nuid, nn)) { return true; } envp->ThrowNew(clsNoSuchNodeException, "invalid node ID"); return false; } /* * Retrieve a vertex from its storage. */ bool GetValidVertex(JNIEnv *envp, int sindex, int gen, int vindex, e4_Vertex &vv) { e4_VertexUniqueID vuid; e4_Storage s; if (!GetValidStorage(envp, sindex, gen, s)) { return false; } vuid.SetID(vindex); vuid.SetSP(s.GetTemporaryUID()); if (s.GetVertexFromID(vuid, vv)) { return true; } envp->ThrowNew(clsNoSuchVertexException, "invalid vertex ID"); return false; } /* * Initialize all the classes, jmethodIDs and jfieldIDs used by the * natives in this package. */ JNIEXPORT void JNICALL Java_com_e4graph_Storage_initNativeIDs(JNIEnv *envp, jclass cls) { static bool initialized = false; jclass clsObject = NULL; jmethodID objectCMID = NULL; int i; /* * Do only once. */ if (initialized) { return; } initialized = true; /* * Initialize the array of storages. */ for (i = 0; i < STATIC_STORAGE_SIZE; i++) { storages[i].s = invalidStorage; } generation = 0; /* * Initialize all classes, field IDs and method IDs. */ clsStorage = envp->FindClass("com/e4graph/Storage"); if (clsStorage == NULL) { goto error; } clsNode = envp->FindClass("com/e4graph/Node"); if (clsNode == NULL) { goto error; } clsVertex = envp->FindClass("com/e4graph/Vertex"); if (clsVertex == NULL) { goto error; } clsValue = envp->FindClass("com/e4graph/Value"); if (clsValue == NULL) { goto error; } clsStorageCreationException = envp->FindClass("com/e4graph/StorageCreationException"); if (clsStorageCreationException == NULL) { goto error; } storageCreationExceptionCMID = envp->GetStaticMethodID(clsStorageCreationException, "", "()V"); if (storageCreationExceptionCMID == NULL) { goto error; } clsStorageIsNotOpenException = envp->FindClass("com/e4graph/StorageIsNotOpenException"); if (clsStorageIsNotOpenException == NULL) { goto error; } storageIsNotOpenExceptionCMID = envp->GetStaticMethodID(clsStorageIsNotOpenException, "", "()V"); if (storageIsNotOpenExceptionCMID == NULL) { goto error; } clsIncorrectVertexTypeException = envp->FindClass("com/e4graph/IncorrectVertexTypeException"); if (clsIncorrectVertexTypeException == NULL) { goto error; } incorrectVertexTypeExceptionCMID = envp->GetStaticMethodID(clsIncorrectVertexTypeException, "", "()V"); if (incorrectVertexTypeExceptionCMID == NULL) { goto error; } clsInvalidPositionException = envp->FindClass("com/e4graph/InvalidPositionException"); if (clsInvalidPositionException == NULL) { goto error; } invalidPositionExceptionCMID = envp->GetStaticMethodID(clsInvalidPositionException, "", "()V"); if (invalidPositionExceptionCMID == NULL) { goto error; } clsNoSuchNodeException = envp->FindClass("com/e4graph/NoSuchNodeException"); if (clsNoSuchNodeException == NULL) { goto error; } noSuchNodeExceptionCMID = envp->GetStaticMethodID(clsNoSuchNodeException, "", "()V"); if (noSuchNodeExceptionCMID == NULL) { goto error; } clsNoSuchVertexException = envp->FindClass("com/e4graph/NoSuchVertexException"); if (clsNoSuchVertexException == NULL) { goto error; } noSuchVertexExceptionCMID = envp->GetStaticMethodID(clsNoSuchVertexException, "", "()V"); if (noSuchVertexExceptionCMID == NULL) { goto error; } sIndexID = envp->GetFieldID(clsStorage, "index", "I"); if (sIndexID == NULL) { goto error; } nIndexID = envp->GetFieldID(clsNode, "nodeIndex", "I"); if (nIndexID == NULL) { goto error; } nsIndexID = envp->GetFieldID(clsNode, "storageIndex", "I"); if (nsIndexID == NULL) { goto error; } vIndexID = envp->GetFieldID(clsVertex, "vertexIndex", "I"); if (vIndexID == NULL) { goto error; } vsIndexID = envp->GetFieldID(clsVertex, "storageIndex", "I"); if (vsIndexID == NULL) { goto error; } typeID = envp->GetFieldID(clsValue, "vertexType", "I"); if (typeID == NULL) { goto error; } integerValueID = envp->GetFieldID(clsValue, "integerValue", "I"); if (integerValueID == NULL) { goto error; } doubleValueID = envp->GetFieldID(clsValue, "doubleValue", "D"); if (doubleValueID == NULL) { goto error; } stringValueID = envp->GetFieldID(clsValue, "stringValue", "Ljava/lang/String;"); if (stringValueID == NULL) { goto error; } bytesValueID = envp->GetFieldID(clsValue, "bytesValue", "[B"); if (bytesValueID == NULL) { goto error; } nodeValueID = envp->GetFieldID(clsValue, "nodeValue", "Lcom/e4graph/Node;"); if (nodeValueID == NULL) { goto error; } nodeCMID = envp->GetStaticMethodID(clsNode, "", "(III)V"); if (nodeCMID == NULL) { goto error; } vertexCMID = envp->GetStaticMethodID(clsVertex, "", "(III)V"); if (vertexCMID == NULL) { goto error; } storageCMID = envp->GetStaticMethodID(clsStorage, "", "(II)V"); if (storageCMID == NULL) { goto error; } valueCMID = envp->GetStaticMethodID(clsValue, "", "()V"); if (valueCMID == NULL) { goto error; } /* * Create the object used to synchronize access to the storage cache. */ clsObject = envp->FindClass("java/lang/Object"); if (clsObject == NULL) { goto error; } objectCMID = envp->GetStaticMethodID(clsObject, "", "()V"); if (objectCMID == NULL) { goto error; } storageLock = envp->NewObject(clsObject, objectCMID); if (storageLock == NULL) { goto error; } /* * All done, return. */ return; error: /* * If there's already an exception lodged in the env, leave it there. */ if (envp->ExceptionOccurred()) { return; } /* * No exception is present, so lodge a fatal error. */ envp->FatalError("j4graph: fatal exception during initialization"); } JNIEXPORT jint JNICALL Java_com_e4graph_Storage_createStorage(JNIEnv *envp, jclass cls, jstring name, jstring driver, jint state) { jboolean ncopy, dcopy; const char *nchars = envp->GetStringUTFChars(name, &ncopy); const char *dchars = envp->GetStringUTFChars(driver, &dcopy); e4_Storage s(nchars, dchars, state); if (ncopy) { envp->ReleaseStringUTFChars(name, nchars); } if (dcopy) { envp->ReleaseStringUTFChars(driver, dchars); } if (!s.IsValid()) { envp->ThrowNew(clsStorageCreationException, "invalid storage"); return -1; } return AllocStorageIndex(envp, s); } /* * Given a storage index that represents a valid storage, retrieve the * generation for that storage. */ JNIEXPORT jint JNICALL Java_com_e4graph_Storage_getStorageGeneration(JNIEnv *envp, jclass cls, jint i) { if (i < 0) { envp->ThrowNew(clsStorageIsNotOpenException, "negative index"); return -1; } LockStorages(envp); if (i >= storageSize) { envp->ThrowNew(clsStorageIsNotOpenException, "index out of range"); ReleaseStorages(envp); return -1; } if (!storages[i].s.IsValid()) { envp->ThrowNew(clsStorageIsNotOpenException, "invalid storage"); ReleaseStorages(envp); return -1; } return storages[i].generation; } /* * Given a storage index and generation, retrieve the string name of the * storage. */ JNIEXPORT jstring JNICALL Java_com_e4graph_Storage_getNameOfStorage(JNIEnv *envp, jclass cls, jint i, jint g) { e4_Storage s; if (!GetValidStorage(envp, i, g, s)) { return NULL; } return envp->NewStringUTF(s.GetName()); } /* * Given a storage index and generation, retrieve the string name of the * driver of this storage. */ JNIEXPORT jstring JNICALL Java_com_e4graph_Storage_getDriverOfStorage(JNIEnv *envp, jclass cls, jint i, jint g) { e4_Storage s; if (!GetValidStorage(envp, i, g, s)) { return NULL; } return envp->NewStringUTF(s.GetDriver()); } JNIEXPORT jobject JNICALL Java_com_e4graph_Storage_getStorage(JNIEnv *envp, jclass cls, jint i, jint g) { e4_Storage s; if (!GetValidStorage(envp, i, g, s)) { return NULL; } return envp->NewObject(clsStorage, storageCMID, i, g); } JNIEXPORT jstring JNICALL Java_com_e4graph_Storage_version(JNIEnv *envp, jclass cls) { return envp->NewStringUTF(e4_Storage::version()); } JNIEXPORT jboolean JNICALL Java_com_e4graph_Storage_isValid1(JNIEnv *envp, jobject me, jint i, jint g) { e4_Storage s; if (!GetValidStorage(envp, i, g, s)) { envp->ExceptionClear(); return JNI_FALSE; } return JNI_TRUE; } JNIEXPORT jint JNICALL Java_com_e4graph_Storage_setState1(JNIEnv *envp, jobject me, jint index, jint g, jint newstate) { e4_Storage s; if (!GetValidStorage(envp, index, g, s)) { return -1; } return s.SetState(newstate); } JNIEXPORT jint JNICALL Java_com_e4graph_Storage_getState1(JNIEnv *envp, jobject me, jint index, jint g) { e4_Storage s; if (!GetValidStorage(envp, index, g, s)) { return -1; } return s.GetState(); } JNIEXPORT jboolean JNICALL Java_com_e4graph_Storage_commit1(JNIEnv *envp, jobject me, jint index, jint g) { e4_Storage s; if (!GetValidStorage(envp, index, g, s)) { return JNI_FALSE; } if (s.Commit()) { return JNI_TRUE; } return JNI_FALSE; } JNIEXPORT void JNICALL Java_com_e4graph_Storage_close1(JNIEnv *envp, jobject me, jint index, jint g) { SetValidStorage(envp, index, g, invalidStorage); } JNIEXPORT jboolean JNICALL Java_com_e4graph_Storage_copyTo1(JNIEnv *envp, jobject me, jint myindex, jint myg, jint hisindex, jint hisg, jboolean forceCommit) { e4_Storage mys, hiss; if (!GetValidStorage(envp, myindex, myg, mys) || !GetValidStorage(envp, hisindex, hisg, hiss)) { return JNI_FALSE; } if (mys.CopyTo(hiss, (forceCommit == JNI_TRUE) ? true : false)) { return JNI_TRUE; } return JNI_FALSE; } JNIEXPORT jboolean JNICALL Java_com_e4graph_Storage_Delete1(JNIEnv *envp, jobject me, jint index, jint g) { e4_Storage s; if (!GetValidStorage(envp, index, g, s)) { return JNI_FALSE; } if (s.Delete()) { SetValidStorage(envp, index, g, invalidStorage); return JNI_TRUE; } return JNI_TRUE; } JNIEXPORT jobject JNICALL Java_com_e4graph_Storage_getRoot1(JNIEnv *envp, jobject me, jint index, jint g) { e4_Storage s; e4_Node n; e4_NodeUniqueID nuid; if (!GetValidStorage(envp, index, g, s)) { return NULL; } if (!s.GetRootNode(n)) { envp->ThrowNew(clsNoSuchNodeException, "cannot retrieve root node"); return NULL; } (void) n.GetUniqueID(nuid); return envp->NewObject(clsNode, nodeCMID, index, g, nuid.GetUniqueID()); } JNIEXPORT jboolean JNICALL Java_com_e4graph_Storage_setRoot1(JNIEnv *envp, jobject me, jint index, jint g, jint nindex, jint nsindex) { e4_Storage s; e4_Node n; e4_NodeUniqueID nuid; if (index != nsindex) { envp->ThrowNew(clsNoSuchNodeException, "new root node not in same storage"); return JNI_FALSE; } if (!GetValidStorage(envp, index, g, s)) { return JNI_FALSE; } nuid.SetID(nindex); nuid.SetSP(s.GetTemporaryUID()); if (!s.GetNodeFromID(nuid, n)) { envp->ThrowNew(clsNoSuchNodeException, "invalid node ID"); return JNI_FALSE; } if (!s.SetRootNode(n)) { envp->ThrowNew(clsNoSuchNodeException, "cannot set new root node"); return JNI_FALSE; } return JNI_TRUE; } JNIEXPORT jboolean JNICALL Java_com_e4graph_Storage_isStable1(JNIEnv *envp, jobject me, jint index, jint g) { e4_Storage s; if (!GetValidStorage(envp, index, g, s)) { return JNI_FALSE; } return (s.IsStable()) ? JNI_TRUE: JNI_FALSE; } JNIEXPORT void JNICALL Java_com_e4graph_Storage_markUnstable1(JNIEnv *envp, jobject me, jint index, jint g) { e4_Storage s; if (!GetValidStorage(envp, index, g, s)) { return; } s.MarkUnstable(); } JNIEXPORT jobject JNICALL Java_com_e4graph_Storage_getNode1(JNIEnv *envp, jobject me, jint index, jint g) { e4_Storage s; e4_Node n; e4_NodeUniqueID nuid; if (!GetValidStorage(envp, index, g, s)) { return NULL; } if (!s.CreateDetachedNode(n)) { return NULL; } (void) n.GetUniqueID(nuid); return envp->NewObject(clsNode, nodeCMID, index, g, nuid.GetUniqueID()); } JNIEXPORT jobject JNICALL Java_com_e4graph_Storage_getNodeVertex1(JNIEnv *envp, jobject me, jint index, jint g, jstring name, jint nindex, jint nsindex) { e4_Storage s; e4_Node n; e4_NodeUniqueID nuid; e4_Vertex v; e4_VertexUniqueID vuid; jboolean copy; const char *vn; if (index != nsindex) { envp->ThrowNew(clsNoSuchNodeException, "node not in same storage"); return NULL; } if (!GetValidStorage(envp, index, g, s)) { return NULL; } nuid.SetID(nindex); nuid.SetSP(s.GetTemporaryUID()); if (!s.GetNodeFromID(nuid, n)) { envp->ThrowNew(clsNoSuchNodeException, "invalid node"); return NULL; } vn = envp->GetStringUTFChars(name, ©); if (!s.CreateDetachedVertex(vn, n, v)) { if (copy) { envp->ReleaseStringUTFChars(name, vn); } envp->ThrowNew(clsNoSuchVertexException, "could not create vertex"); return NULL; } if (copy) { envp->ReleaseStringUTFChars(name, vn); } (void) v.GetUniqueID(vuid); return envp->NewObject(clsVertex, vertexCMID, index, g, vuid.GetUniqueID()); } JNIEXPORT jobject JNICALL Java_com_e4graph_Storage_getIntVertex1(JNIEnv *envp, jobject me, jint index, jint g, jstring name, jint i) { e4_Storage s; e4_Vertex v; e4_VertexUniqueID vuid; jboolean copy; const char *vn; if (!GetValidStorage(envp, index, g, s)) { return NULL; } vn = envp->GetStringUTFChars(name, ©); if (!s.CreateDetachedVertex(vn, (int) i, v)) { if (copy) { envp->ReleaseStringUTFChars(name, vn); } envp->ThrowNew(clsNoSuchVertexException, "could not create vertex"); return NULL; } if (copy) { envp->ReleaseStringUTFChars(name, vn); } (void) v.GetUniqueID(vuid); return envp->NewObject(clsVertex, vertexCMID, index, g, vuid.GetUniqueID()); } JNIEXPORT jobject JNICALL Java_com_e4graph_Storage_getDoubleVertex1(JNIEnv *envp, jobject me, jint index, jint g, jstring name, jdouble d) { e4_Storage s; e4_Vertex v; e4_VertexUniqueID vuid; jboolean copy; const char *vn; if (!GetValidStorage(envp, index, g, s)) { return NULL; } vn = envp->GetStringUTFChars(name, ©); if (!s.CreateDetachedVertex(vn, d, v)) { if (copy) { envp->ReleaseStringUTFChars(name, vn); } envp->ThrowNew(clsNoSuchVertexException, "could not create vertex"); return NULL; } if (copy) { envp->ReleaseStringUTFChars(name, vn); } (void) v.GetUniqueID(vuid); return envp->NewObject(clsVertex, vertexCMID, index, g, vuid.GetUniqueID()); } JNIEXPORT jobject JNICALL Java_com_e4graph_Storage_getStringVertex1(JNIEnv *envp, jobject me, jint index, jint g, jstring name, jstring val) { e4_Storage s; e4_Vertex v; e4_VertexUniqueID vuid; jboolean ncopy, vcopy; const char *vn, *vv; if (!GetValidStorage(envp, index, g, s)) { return NULL; } vn = envp->GetStringUTFChars(name, &ncopy); vv = envp->GetStringUTFChars(val, &vcopy); if (!s.CreateDetachedVertex(vn, vv, v)) { if (ncopy) { envp->ReleaseStringUTFChars(name, vn); } if (vcopy) { envp->ReleaseStringUTFChars(val, vv); } envp->ThrowNew(clsNoSuchVertexException, "could not create vertex"); return NULL; } if (ncopy) { envp->ReleaseStringUTFChars(name, vn); } if (vcopy) { envp->ReleaseStringUTFChars(val, vv); } (void) v.GetUniqueID(vuid); return envp->NewObject(clsVertex, vertexCMID, index, g, vuid.GetUniqueID()); } JNIEXPORT jobject JNICALL Java_com_e4graph_Storage_getBytesVertex1(JNIEnv *envp, jobject me, jint index, jint g, jstring name, jbyteArray jbytes) { e4_Storage s; e4_Vertex v; e4_VertexUniqueID vuid; jboolean ncopy, bcopy; const char *vn; jbyte *thebytes; int len; if (!GetValidStorage(envp, index, g, s)) { return NULL; } vn = envp->GetStringUTFChars(name, &ncopy); thebytes = envp->GetByteArrayElements(jbytes, &bcopy); len = envp->GetArrayLength(jbytes); if (!s.CreateDetachedVertex(vn, thebytes, len, v)) { if (ncopy) { envp->ReleaseStringUTFChars(name, vn); } if (bcopy) { envp->ReleaseByteArrayElements(jbytes, thebytes, 0); } envp->ThrowNew(clsNoSuchVertexException, "could not create vertex"); return NULL; } if (ncopy) { envp->ReleaseStringUTFChars(name, vn); } if (bcopy) { envp->ReleaseByteArrayElements(jbytes, thebytes, 0); } (void) v.GetUniqueID(vuid); return envp->NewObject(clsVertex, vertexCMID, index, g, vuid.GetUniqueID()); } JNIEXPORT void JNICALL Java_com_e4graph_Storage_doGC1(JNIEnv *envp, jobject me, jint index, jint g) { e4_Storage s; if (!GetValidStorage(envp, index, g, s)) { return; } s.DoGC(); } JNIEXPORT jboolean JNICALL Java_com_e4graph_Storage_needsGC1(JNIEnv *envp, jobject me, jint index, jint g) { e4_Storage s; if (!GetValidStorage(envp, index, g, s)) { return JNI_FALSE; } return (s.NeedsGC()) ? JNI_TRUE : JNI_FALSE; } /* * This native is for the com.e4graph.StorageIterator class. It is in this * file so that it will be able to use the file-static storage cache data * structures. */ JNIEXPORT jobject JNICALL Java_com_e4graph_StorageIterator_computeNext(JNIEnv *envp, jclass cls, jint i) { jobject obj; LockStorages(envp); for (i++; i < storageSize; i++) { if (storages[i].s.IsValid()) { obj = envp->NewObject(clsStorage, storageCMID, i, storages[i].generation); ReleaseStorages(envp); return obj; } } ReleaseStorages(envp); return NULL; }