• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "doc_store.h"
17 
18 #include <cinttypes>
19 #include <memory>
20 
21 #include "doc_db.h"
22 #include "doc_util.h"
23 #include "ejdb2.h"
24 #include "hilog/log.h"
25 
26 namespace OHOS {
27 namespace HiviewDFX {
28 constexpr HiLogLabel LABEL = {LOG_CORE, 0xD002D10, "HiView-DOCDB"};
29 class CallBackInfo {
30 public:
CallBackInfo(IWXSTR * xstr,std::function<int (int,const Entry &)> callback)31     CallBackInfo(IWXSTR *xstr, std::function<int (int, const Entry&)> callback)
32         : finish_(false), xstr_(xstr), callback_(callback)
33     {
34     }
35 
~CallBackInfo()36     ~CallBackInfo()
37     {
38     }
39 
Clear()40     void Clear()
41     {
42         if (xstr_ != nullptr) {
43             iwxstr_clear(xstr_);
44         }
45     }
46 
DoCallBack(int id,const Entry & entry)47     void DoCallBack(int id, const Entry& entry)
48     {
49         if (callback_(id, entry) != 0) {
50             finish_ = true;
51         }
52     }
53 
GetIWXSTR()54     IWXSTR* GetIWXSTR()
55     {
56         return xstr_;
57     }
58 
IsFinish() const59     bool IsFinish() const
60     {
61         return finish_;
62     }
63 private:
64     bool finish_;
65     IWXSTR *xstr_;
66     std::function<int (int, const Entry&)> callback_;
67 };
68 
Put(const Entry & entry,const char * coll)69 int DocStore::Put(const Entry &entry, const char* coll)
70 {
71     std::lock_guard<std::mutex> lock(dbStoreMutex);
72     if (dbPtr == nullptr) {
73         return -1;
74     }
75 
76     JBL jbl = 0;
77     iwrc rc = 0;
78     rc = jbl_from_json(&jbl, entry.value.c_str());
79     RCGO(rc, FINISH);
80 
81     rc = ejdb_put_new(dbPtr->db_, coll, jbl, const_cast<int64_t*>(&entry.id));
82     RCGO(rc, FINISH);
83     HiLog::Debug(LABEL, "put data to doc store success, coll=%{public}s", coll);
84 FINISH:
85     if (jbl != 0) {
86         jbl_destroy(&jbl);
87     }
88     if (rc != 0) {
89         iwlog_ecode_error3(rc);
90         HiLog::Error(LABEL, "put data to doc store failed, reason:%{public}s", iwlog_ecode_explained(rc));
91         return MapErrorCode(rc);
92     }
93     return 0;
94 }
95 
PutBatch(const std::vector<Entry> & entries)96 int DocStore::PutBatch(const std::vector<Entry> &entries)
97 {
98     if (dbPtr == nullptr) {
99         return -1;
100     }
101     for (auto entry = entries.begin(); entry != entries.end(); entry++) {
102         Put(*entry);
103     }
104     return 0;
105 }
106 
Merge(const Entry & entry,const char * coll)107 int DocStore::Merge(const Entry &entry, const char* coll)
108 {
109     std::lock_guard<std::mutex> lock(dbStoreMutex);
110     if (entry.id <= 0) {
111         HiLog::Error(LABEL, "id less than 0");
112         return -1;
113     }
114 
115     if (entry.value.empty()) {
116         HiLog::Error(LABEL, "value is empty");
117         return -1;
118     }
119 
120     iwrc rc = ejdb_patch(dbPtr->db_, coll, entry.value.c_str(), entry.id);
121     if (rc != 0) {
122         HiLog::Error(LABEL, "merge data to doc store failed, reason:%{public}s", iwlog_ecode_explained(rc));
123         return MapErrorCode(rc);
124     }
125     return 0;
126 }
127 
Delete(const DataQuery & query,const char * coll)128 int DocStore::Delete(const DataQuery &query, const char* coll)
129 {
130     std::lock_guard<std::mutex> lock(dbStoreMutex);
131     if (dbPtr == nullptr) {
132         return -1;
133     }
134     std::string delSql = query.ToDelString(query.limit_);
135     HiLog::Debug(LABEL, "delete=%{public}s", delSql.c_str());
136     JQL q = 0;
137     iwrc rc = jql_create(&q, coll, delSql.c_str());
138     RCGO(rc, FINISH);
139 
140     EJDB_EXEC ux;
141     ux.cnt = 0;
142     ux.db = dbPtr->db_;
143     ux.limit = 0;
144     ux.log = 0;
145     ux.opaque = 0;
146     ux.pool = 0;
147     ux.q = q;
148     ux.skip = 0;
149     ux.visitor = 0;
150     rc = ejdb_exec(&ux);
151     RCGO(rc, FINISH);
152 FINISH:
153     if (q) {
154         jql_destroy(&q);
155     }
156     if (rc != 0) {
157         iwlog_ecode_error3(rc);
158         HiLog::Error(LABEL, "delete data from doc store failed, reason:%{public}s", iwlog_ecode_explained(rc));
159         return MapErrorCode(rc);
160     }
161     HiLog::Debug(LABEL, "delete num=%{public}" PRId64, ux.cnt);
162     return ux.cnt;
163 }
164 
GetNum()165 int DocStore::GetNum()
166 {
167     std::lock_guard<std::mutex> lock(dbStoreMutex);
168     if (dbPtr == nullptr) {
169         return -1;
170     }
171     int num = 0;
172     JBL meta = nullptr;
173     JBL jbl = nullptr;
174     iwrc rc = ejdb_get_meta(dbPtr->db_, &meta);
175     RCGO(rc, FINISH);
176     rc = jbl_at(meta, "/collections/0/rnum", &jbl);
177     RCGO(rc, FINISH);
178     num = jbl_get_i64(jbl);
179 FINISH:
180     if (meta != nullptr) {
181         jbl_destroy(&meta);
182     }
183     if (jbl != nullptr) {
184         jbl_destroy(&jbl);
185     }
186     if (rc != 0) {
187         iwlog_ecode_error3(rc);
188         HiLog::Error(LABEL, "failed to get meta from doc store, reason:%{public}s", iwlog_ecode_explained(rc));
189         return MapErrorCode(rc);
190     }
191     HiLog::Debug(LABEL, "get num=%{public}d", num);
192     return num;
193 }
194 
GetEntriesWithQuery(const DataQuery & query,std::vector<Entry> & entries,const char * coll) const195 int DocStore::GetEntriesWithQuery(const DataQuery &query, std::vector<Entry> &entries, const char* coll) const
196 {
197     if (dbPtr == nullptr) {
198         return -1;
199     }
200 
201     unsigned int count = 0;
202     IWXSTR *xstr = iwxstr_new();
203     EJDB_DOC doc = nullptr;
204     EJDB_LIST listp;
205     HiLog::Debug(LABEL, "query=%{public}s, limit=%{public}d", query.ToString().c_str(), query.limit_);
206     iwrc rc = ejdb_list2(dbPtr->db_, coll, query.ToString().c_str(), query.limit_, &listp);
207     RCGO(rc, FINISH);
208     doc = listp->first;
209     while (doc != nullptr) {
210         count++;
211         iwxstr_clear(xstr);
212         iwrc resRc = jbl_as_json(doc->raw, jbl_xstr_json_printer, xstr, 0);
213         if (resRc != 0) {
214             HiLog::Error(LABEL, "query result=%{public}" PRId64 " value is invalid, reason:%{public}s",
215                 doc->id, iwlog_ecode_explained(resRc));
216             doc = doc->next;
217             continue;
218         }
219 
220         Entry entry;
221         entry.id = doc->id;
222         entry.value = iwxstr_ptr(xstr);
223         if (entry.value.empty()) {
224             HiLog::Debug(LABEL, "query result=%{public}" PRId64 " value is empty", doc->id);
225             doc = doc->next;
226             continue;
227         }
228         entries.emplace_back(entry);
229         doc = doc->next;
230     }
231     HiLog::Debug(LABEL, "query count=%{public}u", count);
232 FINISH:
233     if (xstr) {
234         iwxstr_destroy(xstr);
235     }
236 
237     if (rc == 0) {
238         ejdb_list_destroy(&listp);
239     } else {
240         iwlog_ecode_error3(rc);
241         HiLog::Error(LABEL, "query data from doc store failed, reason:%{public}s", iwlog_ecode_explained(rc));
242         return MapErrorCode(rc);
243     }
244     return 0;
245 }
246 
DocumentsVisitor(EJDB_EXEC * ctx,const EJDB_DOC doc,int64_t * step)247 static iwrc DocumentsVisitor(EJDB_EXEC *ctx, const EJDB_DOC doc, int64_t *step)
248 {
249     CallBackInfo* callBackInfoPtr = reinterpret_cast<CallBackInfo*>(ctx->opaque);
250     if (callBackInfoPtr == nullptr) {
251         return 0;
252     }
253     if (callBackInfoPtr->IsFinish()) {
254         return 0;
255     }
256     callBackInfoPtr->Clear();
257     Entry entry;
258     entry.id = doc->id;
259     iwrc rc = jbl_as_json(doc->raw, jbl_xstr_json_printer, callBackInfoPtr->GetIWXSTR(), 0);
260     entry.value = iwxstr_ptr(callBackInfoPtr->GetIWXSTR());
261     callBackInfoPtr->DoCallBack(ctx->cnt, entry);
262     return rc;
263 }
264 
GetEntryDuringQuery(const DataQuery & query,std::function<int (int,const Entry &)> callback,const char * coll) const265 int DocStore::GetEntryDuringQuery(const DataQuery &query, std::function<int (int, const Entry&)> callback,
266     const char* coll) const
267 {
268     if (dbPtr == nullptr) {
269         return -1;
270     }
271     HiLog::Debug(LABEL, "query=%{public}s, limit=%{public}d", query.ToString().c_str(), query.limit_);
272     IWXSTR *xstr = iwxstr_new();
273     CallBackInfo *callBackInfoPtr = new CallBackInfo(xstr, callback);
274     JQL q = 0;
275     iwrc rc = jql_create(&q, coll, query.ToString().c_str());
276     RCGO(rc, FINISH);
277 
278     EJDB_EXEC ux;
279     ux.cnt = 1;
280     ux.db = dbPtr->db_;
281     ux.limit = 0;
282     ux.log = 0;
283     ux.opaque = reinterpret_cast<CallBackInfo*>(callBackInfoPtr);
284     ux.pool = 0;
285     ux.q = q;
286     ux.skip = 0;
287     ux.visitor = DocumentsVisitor;
288     rc = ejdb_exec(&ux);
289     RCGO(rc, FINISH);
290 FINISH:
291     if (q) {
292         jql_destroy(&q);
293     }
294 
295     if (xstr) {
296         iwxstr_clear(xstr);
297     }
298 
299     if (callBackInfoPtr) {
300         delete callBackInfoPtr;
301     }
302 
303     if (rc != 0) {
304         iwlog_ecode_error3(rc);
305         HiLog::Error(LABEL, "query data from doc store failed, reason:%{public}s", iwlog_ecode_explained(rc));
306         return MapErrorCode(rc);
307     }
308     return 0;
309 }
310 } // HiviewDFX
311 } // OHOS