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 KV_DB_MANAGER_H
17 #define KV_DB_MANAGER_H
18 
19 #include <string>
20 #include <map>
21 #include <mutex>
22 #include <set>
23 #include <condition_variable>
24 
25 #include "db_errno.h"
26 #include "ikvdb.h"
27 #include "ikvdb_factory.h"
28 #include "platform_specific.h"
29 
30 namespace DistributedDB {
31 class KvDBManager final {
32 public:
33     // used to generate process label
34     static const std::string PROCESS_LABEL_CONNECTOR;
35 
36     // used to open a kvdb with the given property
37     static IKvDB *OpenDatabase(const KvDBProperties &property, int &errCode);
38 
39     // used to open a kvdb with the given property
40     static IKvDBConnection *GetDatabaseConnection(const KvDBProperties &property, int &errCode,
41         bool isNeedIfOpened = true);
42 
43     // used to close the connection.
44     static int ReleaseDatabaseConnection(IKvDBConnection *connection);
45 
46     // used to delete a kvdb with the given property.
47     static int RemoveDatabase(const KvDBProperties &property);
48 
49     // Used to set the process userid and appid
50     static int SetProcessLabel(const std::string &appId, const std::string &userId);
51 
52     static int CalculateKvStoreSize(const KvDBProperties &property, uint64_t &size);
53 
54     // used to restore the sync module of the store.
55     static void RestoreSyncableKvStore();
56 
57     // used to set the corruption handler.
58     static void SetDatabaseCorruptionHandler(const KvStoreCorruptionHandler &handler);
59 
60     // Attention. After call FindKvDB and kvdb is not null, you need to call DecObjRef.
61     IKvDB* FindKvDB(const std::string &identifier) const;
62 
63     // Get a KvDBManager instance, Singleton mode
64     static KvDBManager *GetInstance();
65 
66     // Dump all db message in cache
67     void Dump(int fd);
68 private:
69     // Generate a KvDB unique Identifier
70     static std::string GenerateKvDBIdentifier(const KvDBProperties &property);
71 
72     // used to judge Db opened, can not remove Db file
73     static int CheckDatabaseFileStatus(const KvDBProperties &properties);
74 
75     IKvDB *OpenNewDatabase(const KvDBProperties &property, int &errCode);
76 
77     // Save to IKvDB to the global map
78     IKvDB *SaveKvDBToCache(IKvDB *kvDB);
79 
80     // Get IKvdb From global map
81     IKvDB *FindAndGetKvDBFromCache(const KvDBProperties &property, int &errCode) const;
82 
83     // Get IKvdb From global map
84     void RemoveKvDBFromCache(const IKvDB *kvDB);
85 
86     // Find a IKvdb From the given cache. the IKvDB will IncObjRef if found.
87     IKvDB *FindKvDBFromCache(const KvDBProperties &property,
88         const std::map<std::string, IKvDB *> &cache, bool isNeedCheckPasswd, int &errCode) const;
89 
90     bool IsOpenMemoryDb(const KvDBProperties &properties, const std::map<std::string, IKvDB *> &cache) const;
91 
92     void RestoreSyncerOfAllKvStore();
93 
94     void SetAllDatabaseCorruptionHander(const KvStoreCorruptionHandler &handler);
95 
96     IKvDB *CreateDataBase(const KvDBProperties &property, int &errCode);
97 
98     IKvDB *GetDataBase(const KvDBProperties &property, int &errCode, bool isNeedIfOpened);
99 
100     void DataBaseCorruptNotify(const std::string &appId, const std::string &userId, const std::string &storeId);
101 
102     void DataBaseCorruptNotifyAsync(const std::string &appId, const std::string &userId, const std::string &storeId);
103 
104     void EnterDBOpenCloseProcess(const std::string &identifier);
105 
106     void ExitDBOpenCloseProcess(const std::string &identifier);
107 
108     void SetCorruptHandlerForDatabases(const std::map<std::string, IKvDB *> &kvDBMap);
109 
110     // Compare two schema objects and return true if both are empty,
111     // or both are not empty and the schemas are equal, otherwise return false.
112     static bool CompareSchemaObject(const SchemaObject &newSchema, const SchemaObject &oldSchema);
113 
114     // check schema is valid
115     static int CheckSchema(const IKvDB *kvDB, const KvDBProperties &properties);
116 
117     static int ExecuteRemoveDatabase(const KvDBProperties &properties);
118 
119     static void RemoveDBDirectory(const KvDBProperties &properties);
120 
121     int CheckKvDBProperties(const IKvDB *kvDB, const KvDBProperties &properties,
122         bool isNeedCheckPasswd) const;
123 
124     IKvDB *GetKvDBFromCacheByIdentify(const std::string &identifier, const std::map<std::string, IKvDB *> &cache) const;
125 
126     static int CheckRemoveStateAndRetry(const KvDBProperties &property);
127 
128     static int TryLockDB(const KvDBProperties &kvDBProp, int retryTimes);
129     static int UnlockDB(const KvDBProperties &kvDBProp);
130 
131     static bool CheckOpenDBOptionWithCached(const KvDBProperties &properties, IKvDB *kvdb);
132 
133     static std::atomic<KvDBManager *> instance_;
134     static std::mutex kvDBLock_;
135     static std::mutex instanceLock_;
136 
137     static std::mutex fileHandleMutex_;
138     static std::map<std::string, OS::FileHandle *> locks_;
139 
140     std::map<std::string, IKvDB *> localKvDBs_;
141     std::map<std::string, IKvDB *> multiVerNaturalStores_;
142     std::map<std::string, IKvDB *> singleVerNaturalStores_;
143 
144     std::mutex corruptMutex_;
145     std::mutex kvDBOpenMutex_;
146     std::condition_variable kvDBOpenCondition_;
147     std::set<std::string> kvDBOpenSet_;
148     KvStoreCorruptionHandler corruptHandler_;
149 };
150 } // namespace DistributedDB
151 
152 #endif // KV_DB_MANAGER_H
153