• 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 "generic_kvdb.h"
17 
18 #include "db_common.h"
19 #include "db_constant.h"
20 #include "db_errno.h"
21 #include "kvdb_commit_notify_filterable_data.h"
22 #include "kvdb_utils.h"
23 #include "log_print.h"
24 #include "package_file.h"
25 #include "runtime_context.h"
26 
27 namespace DistributedDB {
28 DEFINE_OBJECT_TAG_FACILITIES(GenericKvDB);
29 
GenericKvDB()30 GenericKvDB::GenericKvDB()
31     : performance_(nullptr),
32       eventNotifyCounter_(0),
33       connectionCount_(0),
34       notificationChain_(nullptr),
35       operatePerm_(OperatePerm::NORMAL_PERM)
36 {}
37 
~GenericKvDB()38 GenericKvDB::~GenericKvDB()
39 {
40     if (connectionCount_ > 0) {
41         LOGF("KvDB destructed with connection count > 0.");
42     }
43 
44     if (notificationChain_ != nullptr) {
45         RefObject::KillAndDecObjRef(notificationChain_);
46         notificationChain_ = nullptr;
47     }
48 }
49 
GetMyProperties() const50 const KvDBProperties &GenericKvDB::GetMyProperties() const
51 {
52     return MyProp();
53 }
54 
GetDBConnection(int & errCode)55 IKvDBConnection *GenericKvDB::GetDBConnection(int &errCode)
56 {
57     std::lock_guard<std::mutex> lock(connectMutex_);
58     if (operatePerm_ == OperatePerm::DISABLE_PERM) {
59         errCode = -E_STALE;
60         return nullptr;
61     } else if (operatePerm_ == OperatePerm::REKEY_MONOPOLIZE_PERM ||
62         operatePerm_ == OperatePerm::IMPORT_MONOPOLIZE_PERM) {
63         errCode = -E_BUSY;
64         return nullptr;
65     }
66 
67     GenericKvDBConnection *connection = NewConnection(errCode);
68     if (connection != nullptr) {
69         IncObjRef(this);
70         IncreaseConnectionCounter();
71     }
72     return connection;
73 }
74 
OnClose(const std::function<void (void)> & notifier)75 void GenericKvDB::OnClose(const std::function<void(void)> &notifier)
76 {
77     AutoLock lockGuard(this);
78     if (notifier) {
79         closeNotifiers_.push_back(notifier);
80     } else {
81         LOGW("Register kvdb 'Close()' notifier failed, notifier is null.");
82     }
83 }
84 
GetStoreId() const85 std::string GenericKvDB::GetStoreId() const
86 {
87     return MyProp().GetStringProp(KvDBProperties::STORE_ID, "");
88 }
89 
DelConnection(GenericKvDBConnection * connection)90 void GenericKvDB::DelConnection(GenericKvDBConnection *connection)
91 {
92     delete connection;
93     connection = nullptr;
94 }
95 
ReleaseDBConnection(GenericKvDBConnection * connection)96 void GenericKvDB::ReleaseDBConnection(GenericKvDBConnection *connection)
97 {
98     if (connectionCount_.load() == 1) {
99         SetConnectionFlag(false);
100     }
101 
102     if (connection != nullptr) {
103         {
104             std::lock_guard<std::mutex> lock(connectMutex_);
105             connection->SetSafeDeleted();
106             DelConnection(connection);
107             DecreaseConnectionCounter();
108         }
109         DecObjRef(this);
110     }
111 }
112 
CommitNotify(int notifyEvent,KvDBCommitNotifyFilterAbleData * data)113 void GenericKvDB::CommitNotify(int notifyEvent, KvDBCommitNotifyFilterAbleData *data)
114 {
115     if (notificationChain_ == nullptr) {
116         LOGE("Failed to do commit notify, notificationChain_ is nullptr.");
117         return;
118     }
119     ++eventNotifyCounter_;
120     if (data == nullptr) {
121         notificationChain_->NotifyEvent(static_cast<EventType>(notifyEvent), nullptr);
122     } else {
123         data->SetMyDb(this, eventNotifyCounter_);
124         data->IncObjRef(data);
125         int errCode = RuntimeContext::GetInstance()->ScheduleQueuedTask(GetStoreId(),
126             std::bind(&GenericKvDB::CommitNotifyAsync, this, notifyEvent, data));
127         if (errCode != E_OK) {
128             LOGE("Failed to do commit notify, schedule task err:%d.", errCode);
129             data->DecObjRef(data);
130             data = nullptr;
131         }
132     }
133 }
134 
CorruptNotifyAsync() const135 void GenericKvDB::CorruptNotifyAsync() const
136 {
137     {
138         std::lock_guard<std::mutex> lock(corruptMutex_);
139         if (corruptHandler_) {
140             corruptHandler_();
141         }
142     }
143 
144     DecObjRef(this);
145 }
146 
CorruptNotify() const147 void GenericKvDB::CorruptNotify() const
148 {
149     IncObjRef(this);
150     int errCode = RuntimeContext::GetInstance()->ScheduleQueuedTask(GetStoreId(),
151         std::bind(&GenericKvDB::CorruptNotifyAsync, this));
152     if (errCode != E_OK) {
153         LOGE("Failed to do the corrupt notify, schedule task err:%d.", errCode);
154         DecObjRef(this);
155     }
156 }
157 
TryToDisableConnection(OperatePerm perm)158 int GenericKvDB::TryToDisableConnection(OperatePerm perm)
159 {
160     std::lock_guard<std::mutex> lock(connectMutex_);
161     if (operatePerm_ != OperatePerm::NORMAL_PERM) {
162         return -E_BUSY;
163     }
164     // more than one connection, should prevent the rekey/import operation.
165     if ((perm == OperatePerm::REKEY_MONOPOLIZE_PERM || perm == OperatePerm::IMPORT_MONOPOLIZE_PERM) &&
166         connectionCount_ > 1) {
167         return -E_BUSY;
168     }
169     operatePerm_ = perm;
170     return E_OK;
171 }
172 
ReEnableConnection(OperatePerm perm)173 void GenericKvDB::ReEnableConnection(OperatePerm perm)
174 {
175     std::lock_guard<std::mutex> lock(connectMutex_);
176     if (perm == operatePerm_) {
177         operatePerm_ = OperatePerm::NORMAL_PERM;
178     }
179 }
180 
RegisterEventListener(EventType type,const NotificationChain::Listener::OnEvent & onEvent,const NotificationChain::Listener::OnFinalize & onFinalize,int & errCode)181 NotificationChain::Listener *GenericKvDB::RegisterEventListener(EventType type,
182     const NotificationChain::Listener::OnEvent &onEvent,
183     const NotificationChain::Listener::OnFinalize &onFinalize, int &errCode)
184 {
185     NotificationChain::Listener *listener = nullptr;
186     if (notificationChain_ != nullptr) {
187         listener = notificationChain_->RegisterListener(type, onEvent, onFinalize, errCode);
188     } else {
189         errCode = -E_NOT_PERMIT;
190     }
191     return listener;
192 }
193 
GetEventNotifyCounter() const194 uint64_t GenericKvDB::GetEventNotifyCounter() const
195 {
196     return eventNotifyCounter_;
197 }
198 
199 // Called when a new connection created.
IncreaseConnectionCounter()200 void GenericKvDB::IncreaseConnectionCounter()
201 {
202     connectionCount_.fetch_add(1, std::memory_order_seq_cst);
203     if (connectionCount_.load() > 0) {
204         SetConnectionFlag(true);
205     }
206 }
207 
208 // Called when a connection released.
DecreaseConnectionCounter()209 void GenericKvDB::DecreaseConnectionCounter()
210 {
211     int count = connectionCount_.fetch_sub(1, std::memory_order_seq_cst);
212     if (count <= 0) {
213         LOGF("Decrease kvdb connection counter failed, count <= 0.");
214         return;
215     }
216     if (count != 1) {
217         return;
218     }
219 
220     operatePerm_ = OperatePerm::DISABLE_PERM;
221     LockObj();
222     auto notifiers = std::move(closeNotifiers_);
223     UnlockObj();
224 
225     for (const auto &notifier : notifiers) {
226         if (notifier) {
227             notifier();
228         }
229     }
230 
231     Close();
232 }
233 
234 // Register a new notification event type.
RegisterNotificationEventType(int eventType)235 int GenericKvDB::RegisterNotificationEventType(int eventType)
236 {
237     if (notificationChain_ == nullptr) {
238         // Lazy init.
239         notificationChain_ = new (std::nothrow) NotificationChain;
240         if (notificationChain_ == nullptr) {
241             return -E_OUT_OF_MEMORY;
242         }
243     }
244     // We DON'T release 'notificationChain_' here event if RegisterEventType()
245     // is failed, it belongs to the class object and is released in the destructor.
246     return notificationChain_->RegisterEventType(static_cast<EventType>(eventType));
247 }
248 
249 // Unregister a notification event type.
UnRegisterNotificationEventType(int eventType)250 void GenericKvDB::UnRegisterNotificationEventType(int eventType)
251 {
252     if (notificationChain_ != nullptr) {
253         notificationChain_->UnRegisterEventType(static_cast<EventType>(eventType));
254     }
255 }
256 
MyProp() const257 const KvDBProperties &GenericKvDB::MyProp() const
258 {
259     return properties_;
260 }
261 
MyProp()262 KvDBProperties &GenericKvDB::MyProp()
263 {
264     return properties_;
265 }
266 
267 #ifndef OMIT_MULTI_VER
GetWorkDir(const KvDBProperties & kvDBProp,std::string & workDir)268 int GenericKvDB::GetWorkDir(const KvDBProperties &kvDBProp, std::string &workDir)
269 {
270     std::string origDataDir = kvDBProp.GetStringProp(KvDBProperties::DATA_DIR, "");
271     std::string identifierDir = kvDBProp.GetStringProp(KvDBProperties::IDENTIFIER_DIR, "");
272     if (origDataDir.empty()) {
273         return -E_INVALID_ARGS;
274     }
275 
276     workDir = origDataDir + "/" + identifierDir;
277     return E_OK;
278 }
279 #endif
280 
SetCorruptHandler(const DatabaseCorruptHandler & handler)281 void GenericKvDB::SetCorruptHandler(const DatabaseCorruptHandler &handler)
282 {
283     std::lock_guard<std::mutex> lock(corruptMutex_);
284     corruptHandler_ = handler;
285 }
286 
CommitNotifyAsync(int notifyEvent,KvDBCommitNotifyFilterAbleData * data)287 void GenericKvDB::CommitNotifyAsync(int notifyEvent, KvDBCommitNotifyFilterAbleData *data)
288 {
289     notificationChain_->NotifyEvent(static_cast<EventType>(notifyEvent), data);
290     data->DecObjRef(data);
291     data = nullptr;
292 }
293 
RegisterFunction(RegisterFuncType type)294 int GenericKvDB::RegisterFunction(RegisterFuncType type)
295 {
296     if (type >= RegisterFuncType::REGISTER_FUNC_TYPE_MAX) {
297         return -E_NOT_SUPPORT;
298     }
299     std::lock_guard<std::mutex> lock(regFuncCountMutex_);
300     if (registerFunctionCount_.empty()) {
301         registerFunctionCount_.resize(static_cast<uint32_t>(RegisterFuncType::REGISTER_FUNC_TYPE_MAX), 0);
302         if (registerFunctionCount_.size() != static_cast<size_t>(RegisterFuncType::REGISTER_FUNC_TYPE_MAX)) {
303             return -E_OUT_OF_MEMORY;
304         }
305     }
306     registerFunctionCount_[static_cast<int>(type)]++;
307     return E_OK;
308 }
309 
UnregisterFunction(RegisterFuncType type)310 int GenericKvDB::UnregisterFunction(RegisterFuncType type)
311 {
312     if (type >= RegisterFuncType::REGISTER_FUNC_TYPE_MAX) {
313         return -E_NOT_SUPPORT;
314     }
315     std::lock_guard<std::mutex> lock(regFuncCountMutex_);
316     if (registerFunctionCount_.size() != static_cast<size_t>(RegisterFuncType::REGISTER_FUNC_TYPE_MAX) ||
317         registerFunctionCount_[static_cast<int>(type)] == 0) {
318         return -E_UNEXPECTED_DATA;
319     }
320     registerFunctionCount_[static_cast<int>(type)]--;
321     return E_OK;
322 }
323 
GetRegisterFunctionCount(RegisterFuncType type) const324 uint32_t GenericKvDB::GetRegisterFunctionCount(RegisterFuncType type) const
325 {
326     std::lock_guard<std::mutex> lock(regFuncCountMutex_);
327     if (type >= RegisterFuncType::REGISTER_FUNC_TYPE_MAX ||
328         registerFunctionCount_.size() != static_cast<size_t>(RegisterFuncType::REGISTER_FUNC_TYPE_MAX)) {
329         return 0;
330     }
331     return registerFunctionCount_[static_cast<int>(type)];
332 }
333 
TransObserverTypeToRegisterFunctionType(int observerType,RegisterFuncType & type) const334 int GenericKvDB::TransObserverTypeToRegisterFunctionType(int observerType, RegisterFuncType &type) const
335 {
336     (void)observerType;
337     (void)type;
338     return -E_NOT_SUPPORT;
339 }
340 
TransConflictTypeToRegisterFunctionType(int conflictType,RegisterFuncType & type) const341 int GenericKvDB::TransConflictTypeToRegisterFunctionType(int conflictType, RegisterFuncType &type) const
342 {
343     (void)conflictType;
344     (void)type;
345     return -E_NOT_SUPPORT;
346 }
347 
CheckDataStatus(const Key & key,const Value & value,bool isDeleted) const348 int GenericKvDB::CheckDataStatus(const Key &key, const Value &value, bool isDeleted) const
349 {
350     if (key.empty() || key.size() > DBConstant::MAX_KEY_SIZE ||
351         value.size() > DBConstant::MAX_VALUE_SIZE) {
352         return -E_INVALID_ARGS;
353     }
354     return E_OK;
355 }
356 
CheckWritePermission() const357 bool GenericKvDB::CheckWritePermission() const
358 {
359     return true;
360 }
361 
IsDataMigrating() const362 bool GenericKvDB::IsDataMigrating() const
363 {
364     return false;
365 }
366 
SetConnectionFlag(bool isExisted) const367 void GenericKvDB::SetConnectionFlag(bool isExisted) const
368 {
369     (void)isExisted;
370 }
371 
CheckIntegrity() const372 int GenericKvDB::CheckIntegrity() const
373 {
374     return E_OK;
375 }
376 
GetStoreDirectory(const KvDBProperties & properties,int dbType,std::string & storeDir,std::string & storeOnlyDir) const377 void GenericKvDB::GetStoreDirectory(const KvDBProperties &properties, int dbType,
378     std::string &storeDir, std::string &storeOnlyDir) const
379 {
380     std::string identifierDir = properties.GetStringProp(KvDBProperties::IDENTIFIER_DIR, "");
381     std::string dataDir = properties.GetStringProp(KvDBProperties::DATA_DIR, "");
382     std::string subDir = KvDBProperties::GetStoreSubDirectory(dbType);
383 
384     std::string storeOnlyIdentifier = GetStoreIdOnlyIdentifier(properties);
385     storeOnlyDir = dataDir + "/" + storeOnlyIdentifier + "/" + subDir + "/";
386     storeDir = dataDir + "/" + identifierDir + "/" + subDir + "/";
387 }
388 
GetStoreIdOnlyIdentifier(const KvDBProperties & properties) const389 std::string GenericKvDB::GetStoreIdOnlyIdentifier(const KvDBProperties &properties) const
390 {
391     std::string storeId = properties.GetStringProp(KvDBProperties::STORE_ID, "");
392     std::string hashStoreId = DBCommon::TransferHashString(storeId);
393     std::string hashStoreDir = DBCommon::TransferStringToHex(hashStoreId);
394     return hashStoreDir;
395 }
396 
GetStorePath() const397 std::string GenericKvDB::GetStorePath() const
398 {
399     return properties_.GetStringProp(KvDBProperties::DATA_DIR, "");
400 }
401 
Dump(int fd)402 void GenericKvDB::Dump(int fd)
403 {
404 }
405 } // namespace DistributedDB
406