1 // Copyright (c) 2011-present, Facebook, Inc.  All rights reserved.
2 //  This source code is licensed under both the GPLv2 (found in the
3 //  COPYING file in the root directory) and Apache 2.0 License
4 //  (found in the LICENSE.Apache file in the root directory).
5 
6 #include <jni.h>
7 #include <map>
8 #include <string>
9 #include <unordered_set>
10 #include <vector>
11 
12 #include "include/org_rocksdb_MemoryUtil.h"
13 
14 #include "rocksjni/portal.h"
15 
16 #include "rocksdb/utilities/memory_util.h"
17 
18 
19 /*
20  * Class:     org_rocksdb_MemoryUtil
21  * Method:    getApproximateMemoryUsageByType
22  * Signature: ([J[J)Ljava/util/Map;
23  */
Java_org_rocksdb_MemoryUtil_getApproximateMemoryUsageByType(JNIEnv * env,jclass,jlongArray jdb_handles,jlongArray jcache_handles)24 jobject Java_org_rocksdb_MemoryUtil_getApproximateMemoryUsageByType(
25     JNIEnv *env, jclass /*jclazz*/, jlongArray jdb_handles, jlongArray jcache_handles) {
26   std::vector<ROCKSDB_NAMESPACE::DB *> dbs;
27   jsize db_handle_count = env->GetArrayLength(jdb_handles);
28   if(db_handle_count > 0) {
29     jlong *ptr_jdb_handles = env->GetLongArrayElements(jdb_handles, nullptr);
30     if (ptr_jdb_handles == nullptr) {
31       // exception thrown: OutOfMemoryError
32       return nullptr;
33     }
34     for (jsize i = 0; i < db_handle_count; i++) {
35       dbs.push_back(
36           reinterpret_cast<ROCKSDB_NAMESPACE::DB *>(ptr_jdb_handles[i]));
37     }
38     env->ReleaseLongArrayElements(jdb_handles, ptr_jdb_handles, JNI_ABORT);
39   }
40 
41   std::unordered_set<const ROCKSDB_NAMESPACE::Cache *> cache_set;
42   jsize cache_handle_count = env->GetArrayLength(jcache_handles);
43   if(cache_handle_count > 0) {
44     jlong *ptr_jcache_handles = env->GetLongArrayElements(jcache_handles, nullptr);
45     if (ptr_jcache_handles == nullptr) {
46       // exception thrown: OutOfMemoryError
47       return nullptr;
48     }
49     for (jsize i = 0; i < cache_handle_count; i++) {
50       auto *cache_ptr =
51           reinterpret_cast<std::shared_ptr<ROCKSDB_NAMESPACE::Cache> *>(
52               ptr_jcache_handles[i]);
53       cache_set.insert(cache_ptr->get());
54     }
55     env->ReleaseLongArrayElements(jcache_handles, ptr_jcache_handles, JNI_ABORT);
56   }
57 
58   std::map<ROCKSDB_NAMESPACE::MemoryUtil::UsageType, uint64_t> usage_by_type;
59   if (ROCKSDB_NAMESPACE::MemoryUtil::GetApproximateMemoryUsageByType(
60           dbs, cache_set, &usage_by_type) != ROCKSDB_NAMESPACE::Status::OK()) {
61     // Non-OK status
62     return nullptr;
63   }
64 
65   jobject jusage_by_type = ROCKSDB_NAMESPACE::HashMapJni::construct(
66       env, static_cast<uint32_t>(usage_by_type.size()));
67   if (jusage_by_type == nullptr) {
68     // exception occurred
69     return nullptr;
70   }
71   const ROCKSDB_NAMESPACE::HashMapJni::FnMapKV<
72       const ROCKSDB_NAMESPACE::MemoryUtil::UsageType, const uint64_t, jobject,
73       jobject>
74       fn_map_kv = [env](
75                       const std::pair<ROCKSDB_NAMESPACE::MemoryUtil::UsageType,
76                                       uint64_t> &pair) {
77         // Construct key
78         const jobject jusage_type = ROCKSDB_NAMESPACE::ByteJni::valueOf(
79             env, ROCKSDB_NAMESPACE::MemoryUsageTypeJni::toJavaMemoryUsageType(
80                      pair.first));
81         if (jusage_type == nullptr) {
82           // an error occurred
83           return std::unique_ptr<std::pair<jobject, jobject>>(nullptr);
84         }
85         // Construct value
86         const jobject jusage_value =
87             ROCKSDB_NAMESPACE::LongJni::valueOf(env, pair.second);
88         if (jusage_value == nullptr) {
89           // an error occurred
90           return std::unique_ptr<std::pair<jobject, jobject>>(nullptr);
91         }
92         // Construct and return pointer to pair of jobjects
93         return std::unique_ptr<std::pair<jobject, jobject>>(
94             new std::pair<jobject, jobject>(jusage_type,
95                                             jusage_value));
96       };
97 
98   if (!ROCKSDB_NAMESPACE::HashMapJni::putAll(env, jusage_by_type,
99                                              usage_by_type.begin(),
100                                              usage_by_type.end(), fn_map_kv)) {
101     // exception occcurred
102     jusage_by_type = nullptr;
103   }
104 
105   return jusage_by_type;
106 
107 }
108