1 #include <jni.h>
2 #include <nativehelper/scoped_utf_chars.h>
3
4 #include "leveldb/db.h"
5
6 #ifndef _Included_com_android_providers_media_leveldb_LevelDBInstance
7 #define _Included_com_android_providers_media_leveldb_LevelDBInstance
8 #ifdef __cplusplus
9 extern "C" {
10 #endif
11 #undef com_android_providers_media_leveldb_LevelDBInstance_MAX_BULK_INSERT_ENTRIES
12 #define com_android_providers_media_leveldb_LevelDBInstance_MAX_BULK_INSERT_ENTRIES 100L
13
getStatusCode(leveldb::Status status)14 static std::string getStatusCode(leveldb::Status status) {
15 if (status.ok()) {
16 return "0";
17 } else if (status.IsNotFound()) {
18 return "1";
19 } else if (status.IsInvalidArgument()) {
20 return "2";
21 } else {
22 return "3";
23 }
24 }
25
createLevelDBResult(JNIEnv * env,leveldb::Status status,std::string value)26 static jobject createLevelDBResult(JNIEnv* env, leveldb::Status status, std::string value) {
27 // Create the object of the class LevelDBResult
28 jclass levelDbResultClass = env->FindClass("com/android/providers/media/leveldb/LevelDBResult");
29 jobject levelDbResultData = env->AllocObject(levelDbResultClass);
30
31 // Get the UserData fields to be set
32 jfieldID codeField = env->GetFieldID(levelDbResultClass, "mCode", "Ljava/lang/String;");
33 jfieldID messageField =
34 env->GetFieldID(levelDbResultClass, "mErrorMessage", "Ljava/lang/String;");
35 jfieldID valueField = env->GetFieldID(levelDbResultClass, "mValue", "Ljava/lang/String;");
36
37 std::string statusCode = getStatusCode(status);
38 env->SetObjectField(levelDbResultData, codeField, env->NewStringUTF(statusCode.c_str()));
39 env->SetObjectField(levelDbResultData, messageField,
40 env->NewStringUTF(status.ToString().c_str()));
41 env->SetObjectField(levelDbResultData, valueField, env->NewStringUTF(value.c_str()));
42 return levelDbResultData;
43 }
44
insertInLevelDB(JNIEnv * env,jobject obj,jlong leveldbptr,jobject leveldbentry)45 static leveldb::Status insertInLevelDB(JNIEnv* env, jobject obj, jlong leveldbptr,
46 jobject leveldbentry) {
47 jclass levelDbEntryClass = env->GetObjectClass(leveldbentry);
48 jmethodID getKeyMethodId =
49 env->GetMethodID(levelDbEntryClass, "getKey", "()Ljava/lang/String;");
50 jmethodID getValueMethodId =
51 env->GetMethodID(levelDbEntryClass, "getValue", "()Ljava/lang/String;");
52
53 jstring key = (jstring)env->CallObjectMethod(leveldbentry, getKeyMethodId);
54 jstring value = (jstring)env->CallObjectMethod(leveldbentry, getValueMethodId);
55 ScopedUtfChars utf_chars_key(env, key);
56 ScopedUtfChars utf_chars_value(env, value);
57 leveldb::DB* leveldb = reinterpret_cast<leveldb::DB*>(leveldbptr);
58 leveldb::Status status;
59 status = leveldb->Put(leveldb::WriteOptions(), utf_chars_key.c_str(), utf_chars_value.c_str());
60 return status;
61 }
62
insert(JNIEnv * env,jobject obj,jlong leveldbptr,jobject leveldbentry)63 static jobject insert(JNIEnv* env, jobject obj, jlong leveldbptr, jobject leveldbentry) {
64 return createLevelDBResult(env, insertInLevelDB(env, obj, leveldbptr, leveldbentry), "");
65 }
66
67 /*
68 * Class: com_android_providers_media_leveldb_LevelDBInstance
69 * Method: nativeCreateInstance
70 * Signature: (Ljava/lang/String;)J
71 */
72 JNIEXPORT jlong JNICALL
Java_com_android_providers_media_leveldb_LevelDBInstance_nativeCreateInstance(JNIEnv * env,jclass leveldbInstanceClass,jstring path)73 Java_com_android_providers_media_leveldb_LevelDBInstance_nativeCreateInstance(
74 JNIEnv* env, jclass leveldbInstanceClass, jstring path) {
75 ScopedUtfChars utf_chars_path(env, path);
76 leveldb::Options options;
77 options.create_if_missing = true;
78 leveldb::DB* leveldb;
79 leveldb::Status status = leveldb::DB::Open(options, utf_chars_path.c_str(), &leveldb);
80 if (status.ok()) {
81 return reinterpret_cast<jlong>(leveldb);
82 } else {
83 long val = 0;
84 return (jlong)val;
85 }
86 }
87
88 /*
89 * Class: com_android_providers_media_leveldb_LevelDBInstance
90 * Method: nativeQuery
91 * Signature: (JLjava/lang/String;)Lcom/android/providers/media/leveldb/LevelDBResult;
92 */
Java_com_android_providers_media_leveldb_LevelDBInstance_nativeQuery(JNIEnv * env,jobject obj,jlong leveldbptr,jstring path)93 JNIEXPORT jobject JNICALL Java_com_android_providers_media_leveldb_LevelDBInstance_nativeQuery(
94 JNIEnv* env, jobject obj, jlong leveldbptr, jstring path) {
95 ScopedUtfChars utf_chars_path(env, path);
96 leveldb::DB* leveldb = reinterpret_cast<leveldb::DB*>(leveldbptr);
97 leveldb::Status status;
98 std::string value = "";
99 status = leveldb->Get(leveldb::ReadOptions(), utf_chars_path.c_str(), &value);
100 return createLevelDBResult(env, status, value);
101 }
102
103 /*
104 * Class: com_android_providers_media_leveldb_LevelDBInstance
105 * Method: nativeInsert
106 * Signature: (JLcom/android/providers/media/leveldb/LevelDBEntry;)
107 * Lcom/android/providers/media/leveldb/LevelDBResult;
108 */
Java_com_android_providers_media_leveldb_LevelDBInstance_nativeInsert(JNIEnv * env,jobject obj,jlong leveldbptr,jobject leveldbentry)109 JNIEXPORT jobject JNICALL Java_com_android_providers_media_leveldb_LevelDBInstance_nativeInsert(
110 JNIEnv* env, jobject obj, jlong leveldbptr, jobject leveldbentry) {
111 return insert(env, obj, leveldbptr, leveldbentry);
112 }
113
114 /*
115 * Class: com_android_providers_media_leveldb_LevelDBInstance
116 * Method: nativeBulkInsert
117 * Signature: (JLjava/util/List;)Lcom/android/providers/media/leveldb/LevelDBResult;
118 */
Java_com_android_providers_media_leveldb_LevelDBInstance_nativeBulkInsert(JNIEnv * env,jobject obj,jlong leveldbptr,jobject entries)119 JNIEXPORT jobject JNICALL Java_com_android_providers_media_leveldb_LevelDBInstance_nativeBulkInsert(
120 JNIEnv* env, jobject obj, jlong leveldbptr, jobject entries) {
121 // Get the class of the list
122 jclass listClass = env->GetObjectClass(entries);
123
124 // Get the iterator method ID
125 jmethodID iteratorMethod = env->GetMethodID(listClass, "iterator", "()Ljava/util/Iterator;");
126
127 // Get the iterator object
128 jobject iterator = env->CallObjectMethod(entries, iteratorMethod);
129
130 // Get the iterator class
131 jclass iteratorClass = env->GetObjectClass(iterator);
132
133 // Get the hasNext and next method IDs
134 jmethodID hasNextMethod = env->GetMethodID(iteratorClass, "hasNext", "()Z");
135 jmethodID nextMethod = env->GetMethodID(iteratorClass, "next", "()Ljava/lang/Object;");
136
137 leveldb::Status status;
138
139 // Iterate through the list
140 while (env->CallBooleanMethod(iterator, hasNextMethod)) {
141 jobject jLevelDBEntryObject = env->CallObjectMethod(iterator, nextMethod);
142 leveldb::Status status = insertInLevelDB(env, obj, leveldbptr, jLevelDBEntryObject);
143 if (!status.ok()) {
144 break;
145 }
146 }
147
148 return createLevelDBResult(env, status, "");
149 }
150
151 /*
152 * Class: com_android_providers_media_leveldb_LevelDBInstance
153 * Method: nativeDelete
154 * Signature: (JLjava/lang/String;)Lcom/android/providers/media/leveldb/LevelDBResult;
155 */
Java_com_android_providers_media_leveldb_LevelDBInstance_nativeDelete(JNIEnv * env,jobject obj,jlong leveldbptr,jstring key)156 JNIEXPORT jobject JNICALL Java_com_android_providers_media_leveldb_LevelDBInstance_nativeDelete(
157 JNIEnv* env, jobject obj, jlong leveldbptr, jstring key) {
158 ScopedUtfChars utf_chars_key(env, key);
159 leveldb::DB* leveldb = reinterpret_cast<leveldb::DB*>(leveldbptr);
160 leveldb::Status status;
161 status = leveldb->Delete(leveldb::WriteOptions(), utf_chars_key.c_str());
162 return createLevelDBResult(env, status, "");
163 }
164
165 #ifdef __cplusplus
166 }
167 #endif
168 #endif
169