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 #ifndef DISTRIBUTED_KVSTORE_TYPES_H
17 #define DISTRIBUTED_KVSTORE_TYPES_H
18 
19 #include <algorithm>
20 #include <cstdint>
21 #include <string>
22 #include <variant>
23 #include <vector>
24 #include "blob.h"
25 #include "store_errno.h"
26 #include "visibility.h"
27 
28 namespace OHOS {
29 namespace DistributedKv {
30 /**
31  * @brief Key set by client, can be any non-empty bytes array, and less than 1024 size.
32 */
33 using Key = OHOS::DistributedKv::Blob;
34 
35 /**
36  * @brief Value set by client, can be any bytes array.
37 */
38 using Value = OHOS::DistributedKv::Blob;
39 
40 /**
41  * @brief User identifier from user-account.
42 */
43 struct UserId {
44     std::string userId;
45 };
46 
47 /**
48  * @brief App identifier from bms.
49 */
50 struct API_EXPORT AppId {
51     std::string appId;
52 
53     /**
54      * @brief Support appId convert to std::string.
55     */
56     operator std::string &() noexcept
57     {
58         return appId;
59     }
60 
61     /**
62      * @brief Support appId convert to const std::string.
63     */
64     operator const std::string &() const noexcept
65     {
66         return appId;
67     }
68 
69     /**
70      * @brief Check appId.
71      */
IsValidAppId72     inline bool IsValid() const
73     {
74         if (appId.empty() || appId.size() > MAX_APP_ID_LEN) {
75             return false;
76         }
77         int count = 0;
78         auto iter = std::find_if_not(appId.begin(), appId.end(),
79             [&count](char c) {
80             count = (c == SEPARATOR_CHAR) ? (count + 1) : (count >= SEPARATOR_COUNT ? count : 0);
81             return (std::isprint(c) && c != '/');
82         });
83 
84         return (iter == appId.end()) && (count < SEPARATOR_COUNT);
85     }
86 private:
87     static constexpr int MAX_APP_ID_LEN = 256;
88     static constexpr int SEPARATOR_COUNT = 3;
89     static constexpr char SEPARATOR_CHAR = '#';
90 };
91 
92 /**
93  * @brief Kvstore name set by client by calling GetKvStore.
94  *
95  * storeId length must be less or equal than 256,
96  * and can not be empty and all space.
97 */
98 struct API_EXPORT StoreId {
99     std::string storeId;
100 
101     /**
102      * @brief Support storeId convert to std::string.
103     */
104     operator std::string &() noexcept
105     {
106         return storeId;
107     }
108 
109     /**
110      * @brief Support storeId convert to const std::string.
111     */
112     operator const std::string &() const noexcept
113     {
114         return storeId;
115     }
116 
117     /**
118      * @brief Operator <.
119      */
120     bool operator<(const StoreId &id) const noexcept
121     {
122         return this->storeId < id.storeId;
123     }
124 
125     /**
126      * @brief Check storeId.
127      */
IsValidStoreId128     inline bool IsValid() const
129     {
130         if (storeId.empty() || storeId.size() > MAX_STORE_ID_LEN) {
131             return false;
132         }
133         auto iter = std::find_if_not(storeId.begin(), storeId.end(),
134             [](char c) { return (std::isdigit(c) || std::isalpha(c) || c == '_'); });
135         return (iter == storeId.end());
136     }
137 private:
138     static constexpr int MAX_STORE_ID_LEN = 128;
139 };
140 
141 /**
142  * @brief Identifier unique database.
143 */
144 struct KvStoreTuple {
145     std::string userId;
146     std::string appId;
147     std::string storeId;
148 };
149 
150 /**
151  * @brief App thread information.
152 */
153 struct AppThreadInfo {
154     std::int32_t pid;
155     std::int32_t uid;
156 };
157 
158 /**
159  * @brief The type for observer database change.
160 */
161 enum SubscribeType : uint32_t {
162     /**
163      * Local changes of syncable kv store.
164     */
165     SUBSCRIBE_TYPE_LOCAL = 1,
166     /**
167      * Synced data changes from remote devices
168     */
169     SUBSCRIBE_TYPE_REMOTE = 2,
170     /**
171      * Synced data changes from remote devices
172     */
173     SUBSCRIBE_TYPE_CLOUD = 4,
174     /**
175      * Both local changes and synced data changes.
176     */
177     SUBSCRIBE_TYPE_ALL = 7,
178 };
179 
180 struct DataOrigin {
181     enum OriginType : int32_t {
182         ORIGIN_NEARBY,
183         ORIGIN_CLOUD,
184         ORIGIN_ALL,
185         ORIGIN_BUTT,
186     };
187     int32_t origin = ORIGIN_ALL;
188     // origin is ORIGIN_NEARBY, the id is networkId;
189     // origin is ORIGIN_CLOUD, the id is the cloud account id
190     std::vector<std::string> id;
191     std::string store;
192 };
193 
194 /**
195  * @brief Data is organized by entry definition.
196 */
197 struct Entry {
198     Key key;
199     Value value;
200 
201     static constexpr size_t MAX_KEY_LENGTH = 1024;
202     static constexpr size_t MAX_VALUE_LENGTH = 4 * 1024 * 1024;
203 
204     /**
205      * Write blob size and data to memory buffer.
206      * Return error when bufferLeftSize not enough.
207     */
WriteToBufferEntry208     bool WriteToBuffer(uint8_t *&cursorPtr, int &bufferLeftSize) const
209     {
210         return key.WriteToBuffer(cursorPtr, bufferLeftSize) && value.WriteToBuffer(cursorPtr, bufferLeftSize);
211     }
212 
213     /**
214      * Read a blob from memory buffer.
215     */
ReadFromBufferEntry216     bool ReadFromBuffer(const uint8_t *&cursorPtr, int &bufferLeftSize)
217     {
218         return key.ReadFromBuffer(cursorPtr, bufferLeftSize) && value.ReadFromBuffer(cursorPtr, bufferLeftSize);
219     }
220 
RawSizeEntry221     int RawSize() const
222     {
223         return key.RawSize() + value.RawSize();
224     }
225 };
226 
227 /**
228  * @brief Indicate how to sync data on sync operation.
229 */
230 enum SyncMode : int32_t {
231     /**
232      * Sync remote data to local.
233     */
234     PULL,
235     /**
236      * Sync local data to remote.
237     */
238     PUSH,
239     /**
240      * Both push and pull.
241     */
242     PUSH_PULL,
243 };
244 
245 /**
246  * @brief The kvstore type.
247 */
248 enum KvStoreType : int32_t {
249     /**
250      * Multi-device collaboration.
251      * The data is managed by the dimension of the device,
252      * and there is no conflict.
253      * Support to query data according to the dimension of equipment.
254     */
255     DEVICE_COLLABORATION,
256     /**
257      * Data is not divided into devices.
258      * Modifying the same key between devices will overwrite.
259     */
260     SINGLE_VERSION,
261     /**
262      * Not support type.
263     */
264     MULTI_VERSION,
265     LOCAL_ONLY,
266     INVALID_TYPE,
267 };
268 
269 /**
270  * @brief Enumeration of database security level.
271 */
272 enum SecurityLevel : int32_t {
273     INVALID_LABEL = -1,
274     NO_LABEL,
275     S0,
276     S1,
277     S2,
278     S3_EX,
279     S3,
280     S4,
281 };
282 
283 /**
284  * @brief Enumeration of database base directory.
285 */
286 enum Area : int32_t {
287     EL0,
288     EL1,
289     EL2,
290     EL3,
291     EL4
292 };
293 
294 enum KvControlCmd : int32_t {
295     SET_SYNC_PARAM = 1,
296     GET_SYNC_PARAM,
297 };
298 
299 using KvParam = OHOS::DistributedKv::Blob;
300 
301 struct KvSyncParam {
302     uint32_t allowedDelayMs { 0 };
303 };
304 
305 /**
306  * @brief Device basic information.
307  *
308  * Including device id, name and type.
309 */
310 struct DeviceInfo {
311     std::string deviceId;
312     std::string deviceName;
313     std::string deviceType;
314 };
315 
316 /**
317  * @brief Device filter strategy.
318 */
319 enum class DeviceFilterStrategy {
320     FILTER = 0,
321     NO_FILTER = 1,
322 };
323 
324 /**
325  * @brief Indicate how and when to sync data with other device.
326 */
327 enum PolicyType : uint32_t {
328     /**
329      * Data synchronization within valid time.
330     */
331     TERM_OF_SYNC_VALIDITY,
332     /**
333      * Data synchronization when device manager module call online operation.
334     */
335     IMMEDIATE_SYNC_ON_ONLINE,
336     /**
337      * Data synchronization when put, delete or update database.
338     */
339     IMMEDIATE_SYNC_ON_CHANGE,
340     /**
341      * Data synchronization when device manager module call onready operation.
342     */
343     IMMEDIATE_SYNC_ON_READY,
344     POLICY_BUTT
345 };
346 
347 /**
348  * @brief Policy Type value.
349 */
350 struct SyncPolicy {
351     uint32_t type;
352     std::variant<std::monostate, uint32_t> value;
353 };
354 
355 /**
356  * @brief Role Type value.
357 */
358 enum RoleType : uint32_t {
359     /**
360       * The user has administrative rights.
361     */
362     OWNER = 0,
363     /**
364       * The user has read-only permission.
365     */
366     VISITOR,
367 };
368 
369 struct Group {
370     std::string groupDir = "";
371     std::string groupId = "";
372 };
373 
374 /**
375  * @brief Cloud config
376 */
377 struct CloudConfig {
378     /**
379      * @brief enable cloud
380     */
381     bool enableCloud = false;
382     /**
383      * @brief Set cloud sync is auto sync
384     */
385     bool autoSync = false;
386 };
387 
388 enum IndexType : uint32_t {
389     /**
390       * use btree index type in database
391     */
392     BTREE = 0,
393     /**
394       * use hash index type in database
395     */
396     HASH,
397 };
398 
399 /**
400  * @brief Data type, that determined the way and timing of data synchronization.
401 */
402 enum DataType : uint32_t {
403     /**
404       * TYPE_STATICS: means synchronize on link establishment or device online.
405     */
406     TYPE_STATICS = 0,
407 
408     /**
409       * TYPE_DYNAMICAL: means synchronize on link establishment.
410       * synchronize can also triggered by the sync and async get interface.
411     */
412     TYPE_DYNAMICAL,
413 };
414 
415 /**
416  * @brief Verify data synchronization based on the account type.
417 */
418 enum AuthType : uint32_t {
419     /**
420       * DEFAULT: means all types of checks.
421     */
422     DEFAULT = 0,
423 
424     /**
425       * IDENTICAL_ACCOUNT_CHECK: means verify the same account type.
426     */
427     IDENTICAL_ACCOUNT
428 };
429 
430 /**
431  * @brief Provide configuration information for database creation.
432 */
433 struct Options {
434     /**
435      * Whether to create a database when the database file does not exist.
436      * It is created by default.
437     */
438     bool createIfMissing = true;
439     /**
440      * Set whether the database file is encrypted.
441      * It is not encrypted by default.
442     */
443     bool encrypt = false;
444     /**
445      * Set whether the rekey takes effect.
446      * It does not take effect by default.
447     */
448     bool autoRekey = false;
449     /**
450      * Data storage disk by default.
451     */
452     bool persistent = true;
453     /**
454      * Set whether the database file is backed up.
455      * It is back up by default.
456     */
457     bool backup = true;
458     /**
459      * Set whether the database file is automatically synchronized.
460      * It is not automatically synchronized by default.
461      * 'ohos.permission.DISTRIBUTED_DATASYNC' permission is necessary.
462      * AutoSync do not guarantee real-time consistency, sync interface is suggested if necessary.
463     */
464     bool autoSync = false;
465     /**
466      * True if is distributed store, false if is local store
467     */
468     bool syncable = true;
469     /**
470      * Set Whether rebuild the database.
471     */
472     bool rebuild = false;
473     /**
474      * Set Whether the database is public.
475     */
476     bool isPublic = false;
477     /**
478      * Set database security level.
479     */
480     int32_t securityLevel = INVALID_LABEL;
481     /**
482      * Set database directory area.
483     */
484     int32_t area = EL1;
485     /**
486      * Set the type of database to be created.
487      * The default is multi-device collaboration database.
488     */
489     KvStoreType kvStoreType = DEVICE_COLLABORATION;
490     /**
491      * The sync policy vector.
492     */
493     std::vector<SyncPolicy> policies{ { IMMEDIATE_SYNC_ON_CHANGE } };
494     /**
495      * Set the value stored in the database.
496      * Schema is not used by default.
497     */
498     std::string schema = "";
499     /**
500      * Set database directory hapName.
501     */
502     std::string hapName = "";
503     /**
504      * Set database directory baseDir.
505     */
506     std::string baseDir = "";
507     /**
508      * Whether the kvstore type is valid.
509     */
IsValidTypeOptions510     inline bool IsValidType() const
511     {
512         bool isValid = kvStoreType == KvStoreType::DEVICE_COLLABORATION ||
513             kvStoreType == KvStoreType::SINGLE_VERSION || kvStoreType == KvStoreType::LOCAL_ONLY;
514         return isValid && (dataType == DataType::TYPE_STATICS || dataType == DataType::TYPE_DYNAMICAL);
515     }
516     /**
517      * Get the databaseDir.
518     */
GetDatabaseDirOptions519     inline std::string GetDatabaseDir() const
520     {
521         if (baseDir.empty()) {
522             return group.groupDir;
523         }
524         return !group.groupDir.empty() ? "" : baseDir;
525     }
526     /**
527      * Whether the databaseDir is valid.
528     */
IsPathValidOptions529     inline bool IsPathValid() const
530     {
531         if ((baseDir.empty() && group.groupDir.empty()) || (!baseDir.empty() && !group.groupDir.empty())) {
532             return false;
533         }
534         return true;
535     }
536     Group group;
537     /**
538      * Set database role.
539     */
540     RoleType role;
541     /**
542      * Whether the sync happend in client.
543     */
544     bool isClientSync = false;
545     /**
546      * Whether the sync need compress.
547     */
548     bool isNeedCompress = true;
549     /**
550      * Indicates data type.
551      * Only dynamic data support auto sync.
552     */
553     DataType dataType = DataType::TYPE_DYNAMICAL;
554     /**
555      * config database details.
556     */
557     struct Config {
558         IndexType type = BTREE;
559         uint32_t pageSize = 32u;
560         uint32_t cacheSize = 2048u;
561     } config;
562     /**
563      * Set cloud config of kv store.
564     */
565     CloudConfig cloudConfig;
566     /**
567      * Set authType of kv store.
568     */
569     AuthType authType = AuthType::DEFAULT;
570     /**
571     * Sub user config for system ability.
572     */
573     int32_t subUser = 0;
574 };
575 
576 /**
577  * @brief Provide the user information.
578 */
579 struct UserInfo {
580     /**
581      * The userId Info.
582     */
583     std::string userId;
584 
585     /**
586      * The userType Info.
587     */
588     int32_t userType;
589 };
590 
591 /**
592  * @brief Cloud sync progress status.
593 */
594 enum Progress {
595     SYNC_BEGIN = 0,
596     SYNC_IN_PROGRESS,
597     SYNC_FINISH,
598 };
599 
600 /**
601  * @brief Cloud sync statistic.
602 */
603 struct Statistic {
604     uint32_t total;
605     uint32_t success;
606     uint32_t failed;
607     uint32_t untreated;
608 };
609 
610 /**
611  * @brief Cloud sync table detail.
612 */
613 struct TableDetail {
614     Statistic upload;
615     Statistic download;
616 };
617 
618 /**
619  * @brief Cloud sync process detail.
620 */
621 struct ProgressDetail {
622     /**
623      * Cloud sync progress status
624     */
625     int32_t progress;
626     int32_t code;
627     TableDetail details;
628 };
629 
630 using AsyncDetail = std::function<void(ProgressDetail &&)>;
631 
632 /**
633  * @brief Provide the switch data.
634 */
635 struct SwitchData {
636     /**
637      * The value of switch data, one bit represents a switch state.
638     */
639     uint32_t value;
640 
641     /**
642      * The effective bit count from low bit to high bit, must be 8, 16 or 24, max is 24.
643     */
644     uint16_t length;
645 };
646 
647 /**
648  * @brief Switch data opertaion.
649 */
650 enum SwitchState: uint32_t {
651     /**
652      * INSERT: means insert data.
653     */
654     INSERT = 0,
655 
656     /**
657      * UPDATE: means update data.
658     */
659     UPDATE,
660 
661     /**
662      * DELETE: means delete data.
663     */
664     DELETE,
665 };
666 
667 /**
668  * @brief Switch data notification for change.
669 */
670 struct SwitchNotification {
671     /**
672      * Switch data.
673     */
674     SwitchData data;
675 
676     /**
677      * The device networkId.
678     */
679     std::string deviceId;
680 
681     /**
682      * Switch state.
683     */
684     SwitchState state = SwitchState::INSERT;
685 };
686 
687 /**
688  * @brief Set config of kv store.
689  */
690 struct StoreConfig {
691     /**
692      * Set cloud config of kv store.
693      */
694     CloudConfig cloudConfig;
695 };
696 }  // namespace DistributedKv
697 }  // namespace OHOS
698 #endif  // DISTRIBUTED_KVSTORE_TYPES_H
699