• 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 "single_ver_natural_store_commit_notify_data.h"
17 #include "db_errno.h"
18 #include "log_print.h"
19 #include "db_common.h"
20 
21 namespace DistributedDB {
SingleVerNaturalStoreCommitNotifyData()22 SingleVerNaturalStoreCommitNotifyData::SingleVerNaturalStoreCommitNotifyData() : conflictedFlag_(0) {}
23 
GetInsertedEntries(int & errCode) const24 const std::list<Entry> SingleVerNaturalStoreCommitNotifyData::GetInsertedEntries(int &errCode) const
25 {
26     return FilterEntriesByKey(insertedEntries_, keyFilter_, errCode);
27 }
28 
GetUpdatedEntries(int & errCode) const29 const std::list<Entry> SingleVerNaturalStoreCommitNotifyData::GetUpdatedEntries(int &errCode) const
30 {
31     return FilterEntriesByKey(updatedEntries_, keyFilter_, errCode);
32 }
33 
GetDeletedEntries(int & errCode) const34 const std::list<Entry> SingleVerNaturalStoreCommitNotifyData::GetDeletedEntries(int &errCode) const
35 {
36     return FilterEntriesByKey(deletedEntries_, keyFilter_, errCode);
37 }
38 
GetCommitConflicts(int & errCode) const39 const std::list<KvDBConflictEntry> SingleVerNaturalStoreCommitNotifyData::GetCommitConflicts(int &errCode) const
40 {
41     errCode = E_OK;
42     return conflictedEntries_;
43 }
44 
SetFilterKey(const Key & key)45 void SingleVerNaturalStoreCommitNotifyData::SetFilterKey(const Key &key)
46 {
47     keyFilter_ = key;
48     return;
49 }
50 
IsChangedDataEmpty() const51 bool SingleVerNaturalStoreCommitNotifyData::IsChangedDataEmpty() const
52 {
53     int errCode;
54     return (!IsCleared() && GetInsertedEntries(errCode).empty() && GetUpdatedEntries(errCode).empty() &&
55         GetDeletedEntries(errCode).empty());
56 }
57 
IsConflictedDataEmpty() const58 bool SingleVerNaturalStoreCommitNotifyData::IsConflictedDataEmpty() const
59 {
60     return conflictedEntries_.empty();
61 }
62 
InsertCommittedData(const Entry & entry,DataType dataType,bool needMerge)63 int SingleVerNaturalStoreCommitNotifyData::InsertCommittedData(const Entry &entry, DataType dataType, bool needMerge)
64 {
65     if (!needMerge) {
66         return InsertEntry(dataType, entry);
67     }
68 
69     Key hashKey;
70     DBCommon::CalcValueHash(entry.key, hashKey);
71     // conclude the operation type
72     if (!IsKeyPropSet(hashKey)) {
73         return E_OK;
74     }
75     DataType type = DataType::NONE;
76     if (keyPropRecord_[hashKey].existStatus == ExistStatus::EXIST) {
77         if (dataType == DataType::INSERT || dataType == DataType::UPDATE) {
78             type = DataType::UPDATE;
79         } else if (dataType == DataType::DELETE) {
80             type = DataType::DELETE;
81         }
82     } else {
83         if (dataType == DataType::INSERT || dataType == DataType::UPDATE) {
84             type = DataType::INSERT;
85         } else if (dataType == DataType::DELETE) {
86             type = DataType::NONE;
87         }
88     }
89 
90     // clear the old data
91     DeleteEntryByKey(entry.key, keyPropRecord_[hashKey].latestType);
92 
93     // update the latest operation type value
94     keyPropRecord_[hashKey].latestType = type;
95 
96     return InsertEntry(type, entry);
97 }
98 
InsertEntry(DataType dataType,const Entry & entry)99 int SingleVerNaturalStoreCommitNotifyData::InsertEntry(DataType dataType, const Entry &entry)
100 {
101     if (dataType == DataType::INSERT) {
102         insertedEntries_.push_back(entry);
103     } else if (dataType == DataType::UPDATE) {
104         updatedEntries_.push_back(entry);
105     } else if (dataType == DataType::DELETE) {
106         deletedEntries_.push_back(entry);
107     }
108     return E_OK;
109 }
110 
InsertConflictedItem(const DataItemInfo & itemInfo,bool isOriginal)111 int SingleVerNaturalStoreCommitNotifyData::InsertConflictedItem(const DataItemInfo &itemInfo, bool isOriginal)
112 {
113     Key hashKey;
114     DBCommon::CalcValueHash(itemInfo.dataItem.key, hashKey);
115     if (!IsKeyPropSet(hashKey)) {
116         LOGE("key property not set.");
117         return E_OK;
118     }
119     // key not exist in db
120     if (keyPropRecord_[hashKey].existStatus == ExistStatus::NONE) {
121         return E_OK;
122     }
123 
124     auto iter = orgDataItem_.find(itemInfo.dataItem.key);
125     if (iter == orgDataItem_.end()) {
126         if (isOriginal) {
127             orgDataItem_[itemInfo.dataItem.key] = itemInfo;
128         }
129         return E_OK;
130     }
131     if (!isOriginal) {
132         PutIntoConflictData(iter->second, itemInfo);
133     }
134 
135     return E_OK;
136 }
137 
FilterEntriesByKey(const std::list<Entry> & entries,const Key & filterKey,int & errCode)138 const std::list<Entry> SingleVerNaturalStoreCommitNotifyData::FilterEntriesByKey(
139     const std::list<Entry> &entries, const Key &filterKey, int &errCode)
140 {
141     errCode = E_OK;
142     if (filterKey.empty()) {
143         return entries;
144     }
145     std::list<Entry> filterEntries;
146     for (const auto &entry : entries) {
147         if (entry.key == filterKey) {
148             filterEntries.push_back(entry);
149         }
150     }
151     return filterEntries;
152 }
153 
DeleteEntry(const Key & key,std::list<Entry> & entries) const154 void SingleVerNaturalStoreCommitNotifyData::DeleteEntry(const Key &key, std::list<Entry> &entries) const
155 {
156     if (entries.empty()) {
157         return;
158     }
159     entries.remove_if([&key](const Entry &entry) {
160         return entry.key == key;
161     });
162 }
163 
DeleteEntryByKey(const Key & key,DataType type)164 void SingleVerNaturalStoreCommitNotifyData::DeleteEntryByKey(const Key &key, DataType type)
165 {
166     if (type == DataType::INSERT) {
167         DeleteEntry(key, insertedEntries_);
168     }
169 
170     if (type == DataType::UPDATE) {
171         DeleteEntry(key, updatedEntries_);
172     }
173 
174     if (type == DataType::DELETE) {
175         DeleteEntry(key, deletedEntries_);
176     }
177 }
178 
InitKeyPropRecord(const Key & key,ExistStatus status)179 void SingleVerNaturalStoreCommitNotifyData::InitKeyPropRecord(const Key &key, ExistStatus status)
180 {
181     // check if key status set before, we can only set key status at the first time
182     if (IsKeyPropSet(key)) {
183         return;
184     }
185 
186     keyPropRecord_[key].existStatus = status;
187 }
188 
SetConflictedNotifiedFlag(int conflictedFlag)189 void SingleVerNaturalStoreCommitNotifyData::SetConflictedNotifiedFlag(int conflictedFlag)
190 {
191     conflictedFlag_ = conflictedFlag;
192 }
193 
GetConflictedNotifiedFlag() const194 int SingleVerNaturalStoreCommitNotifyData::GetConflictedNotifiedFlag() const
195 {
196     return conflictedFlag_;
197 }
198 
IsConflictedNotifyMatched(const DataItem & itemPut,const DataItem & itemGet) const199 bool SingleVerNaturalStoreCommitNotifyData::IsConflictedNotifyMatched(const DataItem &itemPut,
200     const DataItem &itemGet) const
201 {
202     int dataConflictedType = 0;
203     // Local put
204     if ((itemPut.flag & DataItem::LOCAL_FLAG) != 0) {
205         dataConflictedType = SINGLE_VER_CONFLICT_NATIVE_ALL;
206     } else {
207         // Compare the origin device of the get and put item.
208         if (itemPut.origDev != itemGet.origDev) {
209             dataConflictedType = SINGLE_VER_CONFLICT_FOREIGN_KEY_ORIG;
210         } else {
211             dataConflictedType = SINGLE_VER_CONFLICT_FOREIGN_KEY_ONLY;
212         }
213     }
214 
215     int conflictedFlag = GetConflictedNotifiedFlag();
216     LOGD("flag bind kvdb is %d, current data conflicted flag is %d", conflictedFlag, dataConflictedType);
217     return (static_cast<uint32_t>(conflictedFlag) & static_cast<uint32_t>(dataConflictedType)) != 0;
218 }
219 
PutIntoConflictData(const DataItemInfo & orgItemInfo,const DataItemInfo & newItemInfo)220 void SingleVerNaturalStoreCommitNotifyData::PutIntoConflictData(const DataItemInfo &orgItemInfo,
221     const DataItemInfo &newItemInfo)
222 {
223     if (orgItemInfo.dataItem.value == newItemInfo.dataItem.value &&
224         orgItemInfo.dataItem.origDev == newItemInfo.dataItem.origDev &&
225         orgItemInfo.dataItem.flag == newItemInfo.dataItem.flag &&
226         orgItemInfo.deviceName == newItemInfo.deviceName) {
227         LOGW("same data no need to put.");
228         return;
229     }
230 
231     KvDBConflictEntry conflictData;
232     // Local put
233     if (newItemInfo.isLocal) {
234         conflictData.type = SingleVerNaturalStoreCommitNotifyData::SINGLE_VER_CONFLICT_NATIVE_ALL;
235     } else {
236         // Compare the origin device of the get and put item.
237         conflictData.type = ((newItemInfo.dataItem.origDev != orgItemInfo.dataItem.origDev) ?
238             SingleVerNaturalStoreCommitNotifyData::SINGLE_VER_CONFLICT_FOREIGN_KEY_ORIG :
239             SingleVerNaturalStoreCommitNotifyData::SINGLE_VER_CONFLICT_FOREIGN_KEY_ONLY);
240     }
241 
242     bool isDeleted = ((orgItemInfo.dataItem.flag & DataItem::DELETE_FLAG) == DataItem::DELETE_FLAG);
243     conflictData.oldData = {orgItemInfo.dataItem.value, isDeleted, true};
244 
245     isDeleted = ((newItemInfo.dataItem.flag & DataItem::DELETE_FLAG) == DataItem::DELETE_FLAG);
246     conflictData.newData = {newItemInfo.dataItem.value, isDeleted, newItemInfo.isLocal};
247 
248     // If the new item is deleted, just using the key of the old data item.
249     // If the items are all deleted, this function should not be executed.
250     conflictData.key = isDeleted ? orgItemInfo.dataItem.key : newItemInfo.dataItem.key;
251     if (newItemInfo.dataItem.writeTimestamp <= orgItemInfo.dataItem.writeTimestamp) {
252         std::swap(conflictData.newData, conflictData.oldData);
253     }
254 
255     DeleteConflictEntry(conflictData.key);
256     conflictedEntries_.push_back(std::move(conflictData));
257 }
258 
DeleteConflictEntry(const Key & key)259 void SingleVerNaturalStoreCommitNotifyData::DeleteConflictEntry(const Key &key)
260 {
261     if (conflictedEntries_.empty()) {
262         return;
263     }
264     auto iter = conflictedEntries_.begin();
265     for (; iter != conflictedEntries_.end(); ++iter) {
266         if (iter->key == key) {
267             conflictedEntries_.erase(iter);
268             return;
269         }
270     }
271 }
272 
IsKeyPropSet(const Key & key) const273 bool SingleVerNaturalStoreCommitNotifyData::IsKeyPropSet(const Key &key) const
274 {
275     // check if key status set before
276     return (keyPropRecord_.find(key) != keyPropRecord_.end());
277 }
278 
279 DEFINE_OBJECT_TAG_FACILITIES(SingleVerNaturalStoreCommitNotifyData)
280 } // namespace DistributedDB
281