1 /*
2  * Copyright (c) 2023 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 #include "rd_single_ver_natural_store.h"
16 
17 #include "rd_single_ver_natural_store_connection.h"
18 #include "rd_utils.h"
19 #include "sqlite_single_ver_storage_engine.h"
20 
21 namespace DistributedDB {
22 
RdSingleVerNaturalStore()23 RdSingleVerNaturalStore::RdSingleVerNaturalStore()
24     : storageEngine_(nullptr),
25       notificationEventsRegistered_(false)
26 {
27     LOGD("RdSingleVerNaturalStore Created");
28 }
29 
~RdSingleVerNaturalStore()30 RdSingleVerNaturalStore::~RdSingleVerNaturalStore()
31 {
32 }
33 
NewConnection(int & errCode)34 GenericKvDBConnection *RdSingleVerNaturalStore::NewConnection(int &errCode)
35 {
36     RdSingleVerNaturalStoreConnection *connection = new (std::nothrow) RdSingleVerNaturalStoreConnection(this);
37     if (connection == nullptr) {
38         errCode = -E_OUT_OF_MEMORY;
39         return nullptr;
40     }
41     errCode = E_OK;
42     return connection;
43 }
44 
GetAndInitStorageEngine(const KvDBProperties & kvDBProp)45 int RdSingleVerNaturalStore::GetAndInitStorageEngine(const KvDBProperties &kvDBProp)
46 {
47     int errCode = E_OK;
48     {
49         std::unique_lock<std::shared_mutex> lock(engineMutex_);
50         storageEngine_ =
51             static_cast<RdSingleVerStorageEngine *>(StorageEngineManager::GetStorageEngine(kvDBProp, errCode));
52         if (storageEngine_ == nullptr) {
53             return errCode;
54         }
55     }
56 
57     errCode = InitDatabaseContext(kvDBProp);
58     if (errCode != E_OK) {
59         LOGE("[RdSinStore][GetAndInitStorageEngine] Init database context fail! errCode = [%d]", errCode);
60     }
61     return errCode;
62 }
63 
RegisterNotification()64 int RdSingleVerNaturalStore::RegisterNotification()
65 {
66     static const std::vector<int> events {
67         static_cast<int>(SQLiteGeneralNSNotificationEventType::SQLITE_GENERAL_NS_PUT_EVENT),
68     };
69     for (auto event = events.begin(); event != events.end(); ++event) {
70         int errCode = RegisterNotificationEventType(*event);
71         if (errCode == E_OK) {
72             continue;
73         }
74         LOGE("Register rd single version event %d failed:%d!", *event, errCode);
75         for (auto iter = events.begin(); iter != event; ++iter) {
76             UnRegisterNotificationEventType(*iter);
77         }
78         return errCode;
79     }
80     notificationEventsRegistered_ = true;
81     return E_OK;
82 }
83 
ReleaseHandle(RdSingleVerStorageExecutor * & handle) const84 void RdSingleVerNaturalStore::ReleaseHandle(RdSingleVerStorageExecutor *&handle) const
85 {
86     if (handle == nullptr) {
87         return;
88     }
89     if (storageEngine_ != nullptr) {
90         StorageExecutor *databaseHandle = handle;
91         storageEngine_->Recycle(databaseHandle);
92         handle = nullptr;
93     }
94     engineMutex_.unlock_shared(); // unlock after handle used up
95 }
96 
TransObserverTypeToRegisterFunctionType(int observerType,RegisterFuncType & type) const97 int RdSingleVerNaturalStore::TransObserverTypeToRegisterFunctionType(int observerType, RegisterFuncType &type) const
98 {
99     static constexpr TransPair transMap[] = {
100         { static_cast<int>(SQLiteGeneralNSNotificationEventType::SQLITE_GENERAL_NS_PUT_EVENT),
101             RegisterFuncType::OBSERVER_SINGLE_VERSION_NS_PUT_EVENT },
102     };
103     auto funcType = GetFuncType(observerType, transMap, sizeof(transMap) / sizeof(TransPair));
104     if (funcType == RegisterFuncType::REGISTER_FUNC_TYPE_MAX) {
105         return -E_NOT_SUPPORT;
106     }
107     type = funcType;
108     return E_OK;
109 }
110 
Open(const KvDBProperties & kvDBProp)111 int RdSingleVerNaturalStore::Open(const KvDBProperties &kvDBProp)
112 {
113     // Currently, Design for the consistency of directory and file setting secOption
114     int errCode = ClearIncompleteDatabase(kvDBProp);
115     if (errCode != E_OK) {
116         LOGE("Clear incomplete database failed in single version:%d", errCode);
117         return errCode;
118     }
119     const std::string dataDir = kvDBProp.GetStringProp(KvDBProperties::DATA_DIR, "");
120     const std::string identifierDir = kvDBProp.GetStringProp(KvDBProperties::IDENTIFIER_DIR, "");
121     bool isCreate = kvDBProp.GetBoolProp(KvDBProperties::CREATE_IF_NECESSARY, true);
122     errCode = DBCommon::CreateStoreDirectory(dataDir, identifierDir, DBConstant::SINGLE_SUB_DIR, isCreate);
123     if (errCode != E_OK) {
124         LOGE("Create single version natural store directory failed:%d", errCode);
125         return errCode;
126     }
127     LOGD("[RdSingleVerNaturalStore] Open RdSingleVerNaturalStore");
128     errCode = GetAndInitStorageEngine(kvDBProp);
129     if (errCode != E_OK) {
130         ReleaseResources();
131         return errCode;
132     }
133     errCode = RegisterNotification();
134     if (errCode != E_OK) {
135         LOGE("register notification failed:%d", errCode);
136         ReleaseResources();
137         return errCode;
138     }
139     MyProp() = kvDBProp;
140     OnKill([this]() { ReleaseResources(); });
141     return errCode;
142 }
143 
ReleaseResources()144 void RdSingleVerNaturalStore::ReleaseResources()
145 {
146     if (notificationEventsRegistered_) {
147         UnRegisterNotificationEventType(
148             static_cast<EventType>(SQLiteGeneralNSNotificationEventType::SQLITE_GENERAL_NS_PUT_EVENT));
149         notificationEventsRegistered_ = false;
150     }
151     {
152         std::unique_lock<std::shared_mutex> lock(engineMutex_);
153         if (storageEngine_ != nullptr) {
154             (void)StorageEngineManager::ReleaseStorageEngine(storageEngine_);
155             storageEngine_ = nullptr;
156         }
157     }
158 }
159 
160 // Invoked automatically when connection count is zero
Close()161 void RdSingleVerNaturalStore::Close()
162 {
163     ReleaseResources();
164 }
165 
166 // Get interface type of this kvdb.
GetInterfaceType() const167 int RdSingleVerNaturalStore::GetInterfaceType() const
168 {
169     return -E_NOT_SUPPORT;
170 }
171 
172 // Get the interface ref-count, in order to access asynchronously.
IncRefCount()173 void RdSingleVerNaturalStore::IncRefCount()
174 {
175     return;
176 }
177 
178 // Drop the interface ref-count.
DecRefCount()179 void RdSingleVerNaturalStore::DecRefCount()
180 {
181     return;
182 }
183 
184 // Get the identifier of this kvdb.
GetIdentifier() const185 std::vector<uint8_t> RdSingleVerNaturalStore::GetIdentifier() const
186 {
187     return {};
188 }
189 
190 // Get interface for syncer.
GetSyncInterface()191 IKvDBSyncInterface *RdSingleVerNaturalStore::GetSyncInterface()
192 {
193     return nullptr;
194 }
195 
GetMetaData(const Key & key,Value & value) const196 int RdSingleVerNaturalStore::GetMetaData(const Key &key, Value &value) const
197 {
198     return -E_NOT_SUPPORT;
199 }
200 
PutMetaData(const Key & key,const Value & value,bool isInTransaction)201 int RdSingleVerNaturalStore::PutMetaData(const Key &key, const Value &value, bool isInTransaction)
202 {
203     return -E_NOT_SUPPORT;
204 }
205 
206 // Delete multiple meta data records in a transaction.
DeleteMetaData(const std::vector<Key> & keys)207 int RdSingleVerNaturalStore::DeleteMetaData(const std::vector<Key> &keys)
208 {
209     return -E_NOT_SUPPORT;
210 }
211 
212 // Delete multiple meta data records with key prefix in a transaction.
DeleteMetaDataByPrefixKey(const Key & keyPrefix) const213 int RdSingleVerNaturalStore::DeleteMetaDataByPrefixKey(const Key &keyPrefix) const
214 {
215     return -E_NOT_SUPPORT;
216 }
217 
GetAllMetaKeys(std::vector<Key> & keys) const218 int RdSingleVerNaturalStore::GetAllMetaKeys(std::vector<Key> &keys) const
219 {
220     return -E_NOT_SUPPORT;
221 }
222 
GetMaxTimestamp(Timestamp & stamp) const223 void RdSingleVerNaturalStore::GetMaxTimestamp(Timestamp &stamp) const
224 {
225     return;
226 }
227 
SetMaxTimestamp(Timestamp timestamp)228 void RdSingleVerNaturalStore::SetMaxTimestamp(Timestamp timestamp)
229 {
230     return;
231 }
232 
Rekey(const CipherPassword & passwd)233 int RdSingleVerNaturalStore::Rekey(const CipherPassword &passwd)
234 {
235     return -E_NOT_SUPPORT;
236 }
237 
Export(const std::string & filePath,const CipherPassword & passwd)238 int RdSingleVerNaturalStore::Export(const std::string &filePath, const CipherPassword &passwd)
239 {
240     if (storageEngine_ == nullptr) {
241         return -E_INVALID_DB;
242     }
243 
244     // MEMORY_MODE is false, not E_NOT_SUPPORT
245     if (MyProp().GetBoolProp(KvDBProperties::MEMORY_MODE, false)) {
246         return -E_NOT_SUPPORT;
247     }
248 
249     // MEMORY_MODE is READ_ONLY_MODE is true, not E_NOT_SUPPORT
250     if (MyProp().GetBoolProp(KvDBProperties::READ_ONLY_MODE, true)) {
251         return -E_READ_ONLY;
252     }
253 
254     int errCode = E_OK;
255     RdSingleVerStorageExecutor *handle = GetHandle(true, errCode);
256     if (handle == nullptr) {
257         return errCode;
258     }
259 
260     // forbid migrate by hold write handle not release
261     if (storageEngine_->GetEngineState() != EngineState::MAINDB) {
262         errCode = (storageEngine_->GetEngineState() == EngineState::CACHEDB) ? -E_NOT_SUPPORT : -E_BUSY;
263         ReleaseHandle(handle);
264         return errCode;
265     }
266 
267     errCode = TryToDisableConnection(OperatePerm::NORMAL_WRITE);
268     if (errCode != E_OK) {
269         ReleaseHandle(handle);
270         return errCode;
271     }
272 
273     uint8_t *encryptedKey = const_cast<uint8_t*>(passwd.GetData());
274     uint32_t encryptedKeyLen = (uint32_t)passwd.GetSize();
275     errCode = handle->Backup(filePath, encryptedKey, encryptedKeyLen);
276     if (errCode != E_OK) {
277         LOGE("[RdSingleVerNaturalStore][Backup] can not backup the data %d", errCode);
278     }
279 
280     ReEnableConnection(OperatePerm::NORMAL_WRITE);
281     ReleaseHandle(handle);
282     return errCode;
283 }
284 
PreCheckRdImport(std::string & storePath)285 int RdSingleVerNaturalStore::PreCheckRdImport(std::string &storePath)
286 {
287     if (storageEngine_ == nullptr) {
288         LOGE("storageEngine_ is nullptr!");
289         return -E_INVALID_DB;
290     }
291 
292     // MEMORY_MODE is false, not E_NOT_SUPPORT
293     if (MyProp().GetBoolProp(KvDBProperties::MEMORY_MODE, false)) {
294         LOGE("[RdSingleVerNaturalStore][Export] errCode is E_NOT_SUPPORT");
295         return -E_NOT_SUPPORT;
296     }
297 
298     // MEMORY_MODE is READ_ONLY_MODE is true, not E_NOT_SUPPORT
299     if (MyProp().GetBoolProp(KvDBProperties::READ_ONLY_MODE, true)) {
300         LOGE("Not support export when cacheDB existed! state = [%d]", storageEngine_->GetEngineState());
301         return -E_READ_ONLY;
302     }
303 
304     // get store path
305     OpenDbProperties optionTemp = storageEngine_->GetOption();
306     storePath = optionTemp.uri;
307     if (storePath.empty()) {
308         return -E_INVALID_ARGS;
309     }
310 
311     return E_OK;
312 }
313 
Import(const std::string & filePath,const CipherPassword & passwd)314 int RdSingleVerNaturalStore::Import(const std::string &filePath, const CipherPassword &passwd)
315 {
316     int errCode = E_OK;
317     std::string storePath;
318 
319     errCode = PreCheckRdImport(storePath);
320     if (errCode != E_OK) {
321         LOGE("[RdSingleVerNaturalStore][PreCheckRdImport] is failed: %d", errCode);
322         return errCode;
323     }
324 
325     uint8_t *decryptedKey = const_cast<uint8_t*>(passwd.GetData());
326     uint32_t decryptedKeyLen = (uint32_t)passwd.GetSize();
327 
328     // try to disable
329     errCode = storageEngine_->TryToDisable(false, OperatePerm::IMPORT_MONOPOLIZE_PERM);
330     if (errCode != E_OK) {
331         LOGE("TryToDisable is not %d", errCode);
332         return errCode;
333     }
334 
335     errCode = storageEngine_->TryToDisable(true, OperatePerm::IMPORT_MONOPOLIZE_PERM);
336     if (errCode != E_OK) {
337         LOGE("[Import] Failed to disable the database: %d", errCode);
338         AbortHandleAndWaitWriteHandle();
339         return errCode;
340     }
341 
342     if (storageEngine_->GetEngineState() != EngineState::MAINDB) {
343         LOGE("Not support import when cacheDB existed! state = [%d]", storageEngine_->GetEngineState());
344         errCode = (storageEngine_->GetEngineState() == EngineState::CACHEDB) ? -E_NOT_SUPPORT : -E_BUSY;
345         AbortHandleAndWaitWriteHandle();
346         return errCode;
347     }
348 
349     // close all grd handle
350     storageEngine_->CloseAllExecutor();
351 
352     errCode = RdRestore(storePath.c_str(), filePath.c_str(), decryptedKey, decryptedKeyLen);
353     if (errCode != E_OK) {
354         AbortHandleAndWaitWriteHandle();
355         return errCode;
356     }
357 
358     errCode = storageEngine_->InitAllReadWriteExecutor();
359     if (errCode != E_OK) {
360         LOGD("InitAllReadWriteExecutor is failed! errCode = [%d]", errCode);
361         return errCode;
362     }
363     storageEngine_->Enable(OperatePerm::IMPORT_MONOPOLIZE_PERM);
364     return errCode;
365 }
366 
AbortHandleAndWaitWriteHandle() const367 void RdSingleVerNaturalStore::AbortHandleAndWaitWriteHandle() const
368 {
369     storageEngine_->Enable(OperatePerm::IMPORT_MONOPOLIZE_PERM);
370     storageEngine_->WaitWriteHandleIdle();
371 }
372 
GetHandle(bool isWrite,int & errCode,OperatePerm perm) const373 RdSingleVerStorageExecutor *RdSingleVerNaturalStore::GetHandle(bool isWrite, int &errCode,
374     OperatePerm perm) const
375 {
376     engineMutex_.lock_shared();
377     if (storageEngine_ == nullptr) {
378         errCode = -E_INVALID_DB;
379         engineMutex_.unlock_shared(); // unlock when get handle failed.
380         return nullptr;
381     }
382     auto handle = storageEngine_->FindExecutor(isWrite, perm, errCode);
383     if (handle == nullptr) {
384         LOGD("Find null storage engine");
385         engineMutex_.unlock_shared(); // unlock when get handle failed.
386     }
387     return static_cast<RdSingleVerStorageExecutor *>(handle);
388 }
389 
GetSchemaInfo() const390 SchemaObject RdSingleVerNaturalStore::GetSchemaInfo() const
391 {
392     return MyProp().GetSchema();
393 }
394 
CheckCompatible(const std::string & schema,uint8_t type) const395 bool RdSingleVerNaturalStore::CheckCompatible(const std::string &schema, uint8_t type) const
396 {
397     return true;
398 }
399 
GetCurrentTimestamp()400 Timestamp RdSingleVerNaturalStore::GetCurrentTimestamp()
401 {
402     return 0;
403 }
404 
GetSchemaObject() const405 SchemaObject RdSingleVerNaturalStore::GetSchemaObject() const
406 {
407     return MyProp().GetSchema();
408 }
409 
GetSchemaObjectConstRef() const410 const SchemaObject &RdSingleVerNaturalStore::GetSchemaObjectConstRef() const
411 {
412     return MyProp().GetSchemaConstRef();
413 }
414 
GetDbProperties() const415 const KvDBProperties &RdSingleVerNaturalStore::GetDbProperties() const
416 {
417     return GetMyProperties();
418 }
419 
GetKvDBSize(const KvDBProperties & properties,uint64_t & size) const420 int RdSingleVerNaturalStore::GetKvDBSize(const KvDBProperties &properties, uint64_t &size) const
421 {
422     return -E_NOT_SUPPORT;
423 }
424 
GetDbPropertyForUpdate()425 KvDBProperties &RdSingleVerNaturalStore::GetDbPropertyForUpdate()
426 {
427     return MyProp();
428 }
429 
InitDatabaseContext(const KvDBProperties & kvDBProp)430 int RdSingleVerNaturalStore::InitDatabaseContext(const KvDBProperties &kvDBProp)
431 {
432     OpenDbProperties option;
433     InitDataBaseOption(kvDBProp, option);
434 
435     StorageEngineAttr poolSize = {1, 1, 1, 16}; // at most 1 write 16 read.
436 
437     storageEngine_->SetNotifiedCallback(
438         [&](int eventType, KvDBCommitNotifyFilterAbleData *committedData) {
439             auto commitData = static_cast<SingleVerNaturalStoreCommitNotifyData *>(committedData);
440             this->CommitAndReleaseNotifyData(commitData, true, eventType);
441         }
442     );
443 
444     std::string identifier = kvDBProp.GetStringProp(KvDBProperties::IDENTIFIER_DATA, "");
445     int errCode = storageEngine_->InitRdStorageEngine(poolSize, option, identifier);
446     if (errCode != E_OK) {
447         LOGE("Init the rd storage engine failed:%d", errCode);
448     }
449     return errCode;
450 }
451 
RegisterLifeCycleCallback(const DatabaseLifeCycleNotifier & notifier)452 int RdSingleVerNaturalStore::RegisterLifeCycleCallback(const DatabaseLifeCycleNotifier &notifier)
453 {
454     return -E_NOT_SUPPORT;
455 }
456 
SetAutoLifeCycleTime(uint32_t time)457 int RdSingleVerNaturalStore::SetAutoLifeCycleTime(uint32_t time)
458 {
459     return -E_NOT_SUPPORT;
460 }
461 
IsDataMigrating() const462 bool RdSingleVerNaturalStore::IsDataMigrating() const
463 {
464     return false;
465 }
466 
TriggerToMigrateData() const467 int RdSingleVerNaturalStore::TriggerToMigrateData() const
468 {
469     return -E_NOT_SUPPORT;
470 }
471 
CheckReadDataControlled() const472 int RdSingleVerNaturalStore::CheckReadDataControlled() const
473 {
474     return E_OK;
475 }
476 
IsCacheDBMode() const477 bool RdSingleVerNaturalStore::IsCacheDBMode() const
478 {
479     return false;
480 }
481 
IncreaseCacheRecordVersion() const482 void RdSingleVerNaturalStore::IncreaseCacheRecordVersion() const
483 {
484     return;
485 }
486 
GetCacheRecordVersion() const487 uint64_t RdSingleVerNaturalStore::GetCacheRecordVersion() const
488 {
489     return 0;
490 }
491 
GetAndIncreaseCacheRecordVersion() const492 uint64_t RdSingleVerNaturalStore::GetAndIncreaseCacheRecordVersion() const
493 {
494     return 0;
495 }
496 
CheckIntegrity() const497 int RdSingleVerNaturalStore::CheckIntegrity() const
498 {
499     return -E_NOT_SUPPORT;
500 }
501 
GetCompressionAlgo(std::set<CompressAlgorithm> & algorithmSet) const502 int RdSingleVerNaturalStore::GetCompressionAlgo(std::set<CompressAlgorithm> &algorithmSet) const
503 {
504     return -E_NOT_SUPPORT;
505 }
506 
SetSendDataInterceptor(const PushDataInterceptor & interceptor)507 void RdSingleVerNaturalStore::SetSendDataInterceptor(const PushDataInterceptor &interceptor)
508 {
509     return;
510 }
511 
SetMaxLogSize(uint64_t limit)512 int RdSingleVerNaturalStore::SetMaxLogSize(uint64_t limit)
513 {
514     return -E_NOT_SUPPORT;
515 }
516 
GetMaxLogSize() const517 uint64_t RdSingleVerNaturalStore::GetMaxLogSize() const
518 {
519     return 0;
520 }
521 
Dump(int fd)522 void RdSingleVerNaturalStore::Dump(int fd)
523 {
524     return;
525 }
526 
WakeUpSyncer()527 void RdSingleVerNaturalStore::WakeUpSyncer()
528 {
529     LOGD("Not support syncer yet");
530     return;
531 }
532 
CommitNotify(int notifyEvent,KvDBCommitNotifyFilterAbleData * data)533 void RdSingleVerNaturalStore::CommitNotify(int notifyEvent, KvDBCommitNotifyFilterAbleData *data)
534 {
535     GenericKvDB::CommitNotify(notifyEvent, data);
536 }
537 
InitDataBaseOption(const KvDBProperties & kvDBProp,OpenDbProperties & option)538 void RdSingleVerNaturalStore::InitDataBaseOption(const KvDBProperties &kvDBProp, OpenDbProperties &option)
539 {
540     option.uri = GetDatabasePath(kvDBProp);
541     option.subdir = GetSubDirPath(kvDBProp);
542     SecurityOption securityOpt;
543     if (RuntimeContext::GetInstance()->IsProcessSystemApiAdapterValid()) {
544         securityOpt.securityLabel = kvDBProp.GetSecLabel();
545         securityOpt.securityFlag = kvDBProp.GetSecFlag();
546     }
547     option.createIfNecessary = kvDBProp.GetBoolProp(KvDBProperties::CREATE_IF_NECESSARY, true);
548     option.createDirByStoreIdOnly = kvDBProp.GetBoolProp(KvDBProperties::CREATE_DIR_BY_STORE_ID_ONLY, false);
549     option.readOnly = kvDBProp.GetBoolProp(KvDBProperties::READ_ONLY_MODE, false);
550     option.isNeedIntegrityCheck = kvDBProp.GetBoolProp(KvDBProperties::CHECK_INTEGRITY, false);
551     option.isNeedRmCorruptedDb = kvDBProp.GetBoolProp(KvDBProperties::RM_CORRUPTED_DB, false);
552     bool isSharedMode = kvDBProp.GetBoolProp(KvDBProperties::SHARED_MODE, false);
553     option.isHashTable = (IndexType)kvDBProp.GetIntProp(KvDBProperties::INDEX_TYPE, BTREE) == HASH;
554     int pageSize = kvDBProp.GetIntProp(KvDBProperties::PAGE_SIZE, 32);
555     int cacheSize = kvDBProp.GetIntProp(KvDBProperties::CACHE_SIZE, 2048);
556 
557     std::string config = "{";
558     config += InitRdConfig() + R"(, )";
559     config += option.isHashTable ?
560         R"("bufferPoolPolicy": "BUF_PRIORITY_NORMAL")" : R"("bufferPoolPolicy": "BUF_PRIORITY_INDEX")";
561     config += R"(, "pageSize":)" + std::to_string(pageSize) + R"(, )";
562     config += R"("bufferPoolSize":)" + std::to_string(cacheSize) + R"(, )";
563     config += R"("redoPubBufSize":)" + std::to_string(cacheSize) + R"(, )";
564     config += isSharedMode ? R"("sharedModeEnable": 1)" : R"("sharedModeEnable": 0)";
565     config += "}";
566     option.rdConfig = config;
567 }
568 
SetReceiveDataInterceptor(const DataInterceptor & interceptor)569 void RdSingleVerNaturalStore::SetReceiveDataInterceptor(const DataInterceptor &interceptor)
570 {
571 }
572 } // namespace DistributedDB
573