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_result_set.h"
16 #include "db_errno.h"
17 #include "grd_db_api.h"
18 #include "grd_resultset_api.h"
19 #include "log_print.h"
20 #include "rd_utils.h"
21 #include "sqlite_single_ver_storage_executor_sql.h"
22 
23 namespace DistributedDB {
RdSingleVerResultSet(RdSingleVerNaturalStore * kvDB,const Key & key)24 RdSingleVerResultSet::RdSingleVerResultSet(RdSingleVerNaturalStore *kvDB, const Key &key)
25     : key_(key), kvDB_(kvDB)
26 {
27     kvScanMode_ = KV_SCAN_PREFIX;
28 }
29 
RdSingleVerResultSet(RdSingleVerNaturalStore * kvDB,const Key & beginKey,const Key & endKey,GRD_KvScanModeE kvScanMode)30 RdSingleVerResultSet::RdSingleVerResultSet(RdSingleVerNaturalStore *kvDB, const Key &beginKey,
31     const Key &endKey, GRD_KvScanModeE kvScanMode)
32     : beginKey_(beginKey), endKey_(endKey), kvScanMode_(kvScanMode), kvDB_(kvDB) {}
33 
~RdSingleVerResultSet()34 RdSingleVerResultSet::~RdSingleVerResultSet()
35 {
36     isOpen_ = false;
37     position_ = INIT_POSITION;
38     kvDB_ = nullptr;
39     handle_ = nullptr;
40 }
41 
Open(bool isMemDb)42 int RdSingleVerResultSet::Open(bool isMemDb)
43 {
44     (void)isMemDb;
45     std::lock_guard<std::mutex> lockGuard(mutex_);
46     if (isOpen_) {
47         LOGW("[RdSinResSet] Not need to open result set again!");
48         return E_OK;
49     }
50     if (kvDB_ == nullptr) { // Unlikely
51         return -E_INVALID_ARGS;
52     }
53     if (kvScanMode_ >= KV_SCAN_BUTT) {
54         LOGE("[RdSinResSet] Open result scan mode is invalid.");
55         return -E_INVALID_ARGS;
56     }
57     int errCode = E_OK;
58     handle_ = kvDB_->GetHandle(false, errCode);
59     if (handle_ == nullptr) {
60         LOGE("[RdSinResSet] Get handle failed, errCode=%d.", errCode);
61         return errCode;
62     }
63     switch (kvScanMode_) {
64         case KV_SCAN_PREFIX: {
65             errCode = handle_->OpenResultSet(key_, kvScanMode_, &resultSet_);
66             break;
67         }
68         case KV_SCAN_RANGE: {
69             errCode = handle_->OpenResultSet(beginKey_, endKey_, &resultSet_);
70             break;
71         }
72         default:
73             return -E_INVALID_ARGS;
74     }
75     if (errCode != E_OK) {
76         LOGE("[RdSinResSet] open result set failed, %d.", errCode);
77         kvDB_->ReleaseHandle(handle_);
78         return errCode;
79     }
80     isOpen_ = true;
81     return E_OK;
82 }
83 
Close()84 int RdSingleVerResultSet::Close()
85 {
86     std::lock_guard<std::mutex> lockGuard(mutex_);
87     int errCode = PreCheckResultSet();
88     if (errCode != E_OK) {
89         return errCode;
90     }
91 
92     errCode = handle_->CloseResultSet(resultSet_);
93     if (errCode != E_OK) {
94         LOGE("[RdSinResSet] close rd result set failed, errCode=%d.", errCode);
95         kvDB_->ReleaseHandle(handle_);
96         return errCode;
97     }
98     kvDB_->ReleaseHandle(handle_);
99     isOpen_ = false;
100     position_ = INIT_POSITION;
101     return E_OK;
102 }
103 
PreCheckResultSet() const104 int RdSingleVerResultSet::PreCheckResultSet() const
105 {
106     if (!isOpen_) {
107         LOGE("[RdSinResSet] Result set not open yet.");
108         return -E_RESULT_SET_STATUS_INVALID;
109     }
110     if (kvDB_ == nullptr) { // Unlikely
111         LOGE("[RdSinResSet] KvDB not set yet.");
112         return -E_INVALID_ARGS;
113     }
114 
115     if (handle_ == nullptr) {
116         LOGE("[RdSinResSet] Handle not set yet.");
117         return -E_INVALID_ARGS;
118     }
119     return E_OK;
120 }
121 
GetCount() const122 int RdSingleVerResultSet::GetCount() const
123 {
124     int errCode = PreCheckResultSet();
125     if (errCode != E_OK) {
126         return errCode;
127     }
128     int count = 0;
129     switch (kvScanMode_) {
130         case KV_SCAN_PREFIX: {
131             errCode = handle_->GetCount(key_, count, kvScanMode_);
132             break;
133         }
134         case KV_SCAN_RANGE: {
135             errCode = handle_->GetCount(beginKey_, endKey_, count, kvScanMode_);
136             break;
137         }
138         default:
139             return -E_INVALID_ARGS;
140     }
141     if (errCode != E_OK && errCode != -E_RESULT_SET_EMPTY) {
142         return errCode;
143     }
144     return count;
145 }
146 
GetPosition() const147 int RdSingleVerResultSet::GetPosition() const
148 {
149     std::lock_guard<std::mutex> lockGuard(mutex_);
150     return position_;
151 }
152 
Move(int offset) const153 int RdSingleVerResultSet::Move(int offset) const
154 {
155     std::lock_guard<std::mutex> lockGuard(mutex_);
156     int errCode = E_OK;
157     if (offset == 0) {
158         return errCode;
159     }
160     offset = offset > INT_MAX ? INT_MAX : offset;
161     offset = offset < INT_MIN ? INT_MIN : offset;
162 
163     while (offset > 0) {
164         errCode = MoveToNext();
165         if (errCode != E_OK && errCode != -E_NOT_FOUND) {
166             LOGE("[RdSinResSet] move by offset failed, errCode=%d, offset=%d", errCode, offset);
167             return errCode;
168         }
169         --offset;
170         if (errCode == -E_NOT_FOUND && offset >= 0) {
171             LOGE("[RdSingleVerStorageExecutor] move offset: %d, out of bounds or result set empty, position: %d",
172                 offset, position_);
173             return -E_INVALID_ARGS;
174         }
175     }
176     while (offset < 0) {
177         errCode = MoveToPrev();
178         if (errCode != E_OK && errCode != -E_NOT_FOUND) {
179             LOGE("[RdSinResSet] move by offset failed, errCode=%d, offset=%d", errCode, offset);
180             return errCode;
181         }
182         ++offset;
183         if (errCode == -E_NOT_FOUND && offset <= 0) {
184             LOGE("[RdSingleVerStorageExecutor] move offset: %d, out of bounds or result set empty, position: %d",
185                 offset, position_);
186             return -E_INVALID_ARGS;
187         }
188     }
189     return errCode;
190 }
191 
MoveToNext() const192 int RdSingleVerResultSet::MoveToNext() const
193 {
194     int errCode = PreCheckResultSet();
195     if (errCode != E_OK) {
196         LOGE("[RdSinResSet] PreCheckResultSet failed");
197         return errCode;
198     }
199 
200     if (position_ == INIT_POSITION && isMovedBefore_) {
201         ++position_;
202         return E_OK;
203     }
204     errCode = handle_->MoveToNext(resultSet_);
205     if (errCode != E_OK && errCode != -E_NOT_FOUND) {
206         LOGE("[RdSinResSet] move next failed, errCode=%d.", errCode);
207         return errCode;
208     } else if (errCode == -E_NOT_FOUND) {
209         if (!isMovedBefore_) {
210             LOGE("[RdSinResSet] move next failed, result set is empty");
211             return -E_RESULT_SET_EMPTY;
212         }
213         // nothing to do when position_ equal with endposition_ which isn't equal with INIT_POSITION
214         if (endPosition_ == INIT_POSITION || position_ != endPosition_) {
215             ++position_;
216             endPosition_ = position_;
217         }
218         return errCode;
219     } else {
220         // E_OK
221         ++position_;
222         isMovedBefore_ = true;
223         if (position_ == endPosition_ && endPosition_ != INIT_POSITION) {
224             // incase we have chosen an end, but new data put in after that
225             endPosition_ = position_ + 1;
226         }
227     }
228     return errCode;
229 }
230 
MoveToPrev() const231 int RdSingleVerResultSet::MoveToPrev() const
232 {
233     int errCode = PreCheckResultSet();
234     if (errCode != E_OK) {
235         LOGE("[RdSinResSet] PreCheckResultSet failed");
236         return errCode;
237     }
238 
239     if (position_ == endPosition_ && endPosition_ != INIT_POSITION) {
240         --position_;
241         return E_OK;
242     }
243 
244     errCode = handle_->MoveToPrev(resultSet_);
245     if (errCode != E_OK && errCode != -E_NOT_FOUND) {
246         LOGE("[RdSinResSet] move prev failed, errCode=%d.", errCode);
247         return errCode;
248     }
249 
250     if (errCode == -E_NOT_FOUND) {
251         position_ = INIT_POSITION;
252     } else {
253         if (position_ <= 0) {
254             position_ = 0;
255         } else {
256             --position_;
257         }
258     }
259     return errCode;
260 }
261 
MoveTo(int position) const262 int RdSingleVerResultSet::MoveTo(int position) const
263 {
264     int errCode = PreCheckResultSet();
265     if (errCode != E_OK) {
266         return errCode;
267     }
268 
269     if (position < 0) {
270         LOGW("[RdSinResSet][MoveTo] Target Position=%d invalid.", position);
271     }
272 
273     return Move(position - position_);
274 }
275 
MoveToFirst()276 int RdSingleVerResultSet::MoveToFirst()
277 {
278     if (!isMovedBefore_) {
279         return MoveToNext();
280     }
281     if (position_ == INIT_POSITION) {
282         ++position_;
283         return E_OK;
284     }
285 
286     int errCode = E_OK;
287     do {
288         errCode = MoveToPrev();
289         if (errCode != E_OK && errCode != -E_NOT_FOUND) {
290             LOGE("[RdSinResSet] move to first failed, errCode=%d, position=%d", errCode, position_);
291             return errCode;
292         }
293         if (errCode == -E_NOT_FOUND) {
294             ++position_;
295             break;
296         }
297     } while (errCode == E_OK);
298 
299     return E_OK;
300 }
301 
MoveToLast()302 int RdSingleVerResultSet::MoveToLast()
303 {
304     int errCode = E_OK;
305     do {
306         errCode = MoveToNext();
307         if (errCode != E_OK && errCode != -E_NOT_FOUND) {
308             LOGE("[RdSinResSet] move to last failed, errCode=%d, position=%d", errCode, position_);
309             return errCode;
310         }
311         if (errCode == -E_NOT_FOUND) {
312             --position_;
313             break;
314         }
315     } while (errCode == E_OK);
316 
317     return E_OK;
318 }
319 
IsFirst() const320 bool RdSingleVerResultSet::IsFirst() const
321 {
322     int position = GetPosition();
323     if (GetCount() == 0) {
324         return false;
325     }
326     if (position == 0) {
327         return true;
328     }
329     return false;
330 }
331 
IsLast() const332 bool RdSingleVerResultSet::IsLast() const
333 {
334     int position = GetPosition();
335     int count = GetCount();
336     if (count == 0) {
337         return false;
338     }
339     if (position == (count - 1)) {
340         return true;
341     }
342     return false;
343 }
344 
IsBeforeFirst() const345 bool RdSingleVerResultSet::IsBeforeFirst() const
346 {
347     int position = GetPosition();
348 
349     if (GetCount() == 0) {
350         return true;
351     }
352     if (position <= INIT_POSITION) {
353         return true;
354     }
355     return false;
356 }
357 
IsAfterLast() const358 bool RdSingleVerResultSet::IsAfterLast() const
359 {
360     int position = GetPosition();
361     int count = GetCount();
362     if (count == 0) {
363         return true;
364     }
365     if (position >= count) {
366         return true;
367     }
368     return false;
369 }
370 
GetEntry(Entry & entry) const371 int RdSingleVerResultSet::GetEntry(Entry &entry) const
372 {
373     std::lock_guard<std::mutex> lockGuard(mutex_);
374     int errCode = PreCheckResultSet();
375     if (errCode != E_OK) {
376         return errCode;
377     }
378 
379     if (position_ == INIT_POSITION || (position_ == endPosition_ && endPosition_ != INIT_POSITION)) {
380         return -E_NO_SUCH_ENTRY;
381     }
382     errCode = handle_->GetEntry(resultSet_, entry);
383     if (errCode != E_OK && errCode != -E_NOT_FOUND) {
384         LOGE("[RdSinResSet][GetEntry] failed to get entry form result set.");
385     }
386     return errCode == -E_NOT_FOUND ? -E_NO_SUCH_ENTRY : errCode;
387 }
388 } // namespace DistributedDB