1 //
2 // Copyright RIME Developers
3 // Distributed under the BSD License
4 //
5 // 2013-04-16 GONG Chen <chen.sst@gmail.com>
6 //
7 #ifndef RIME_USER_DB_H_
8 #define RIME_USER_DB_H_
9 
10 #include <stdint.h>
11 #include <rime/component.h>
12 #include <rime/dict/db.h>
13 #include <rime/dict/db_utils.h>
14 
15 namespace rime {
16 
17 using TickCount = uint64_t;
18 
19 /// Properties of a user db entry value.
20 struct UserDbValue {
21   int commits = 0;
22   double dee = 0.0;
23   TickCount tick = 0;
24 
25   UserDbValue() = default;
26   UserDbValue(const string& value);
27 
28   string Pack() const;
29   bool Unpack(const string& value);
30 };
31 
32 /**
33  * A placeholder class for user db.
34  *
35  * Note: do not directly use this class to instantiate a user db.
36  * Instead, use the rime::UserDbWrapper<T> template, which creates
37  * wrapper classes for underlying implementations of rime::Db.
38  */
39 class UserDb {
40  public:
41   static string snapshot_extension();
42 
43   /// Abstract class for a user db component.
44   class Component : public Db::Component {
45    public:
46     virtual string extension() const = 0;
47   };
48 
49   /// Requires a registered component for a user db class.
Require(const string & name)50   static Component* Require(const string& name) {
51     return dynamic_cast<Component*>(Db::Require(name));
52   }
53 
54   UserDb() = delete;
55 
56 };
57 
58 /// A helper class to provide extra functionalities related to user db.
59 class UserDbHelper {
60  public:
UserDbHelper(Db * db)61   UserDbHelper(Db* db) : db_(db) {
62   }
UserDbHelper(const the<Db> & db)63   UserDbHelper(const the<Db>& db) : db_(db.get()) {
64   }
UserDbHelper(const an<Db> & db)65   UserDbHelper(const an<Db>& db) : db_(db.get()) {
66   }
67 
68   bool UpdateUserInfo();
69   static bool IsUniformFormat(const string& name);
70   bool UniformBackup(const string& snapshot_file);
71   bool UniformRestore(const string& snapshot_file);
72 
73   bool IsUserDb();
74   string GetDbName();
75   string GetUserId();
76   string GetRimeVersion();
77 
78  protected:
79   Db* db_;
80 };
81 
82 /// A template to define a user db class based on an implementation of rime::Db.
83 template <class BaseDb>
84 class UserDbWrapper : public BaseDb {
85  public:
86   RIME_API UserDbWrapper(const string& file_name, const string& db_name);
87 
CreateMetadata()88   virtual bool CreateMetadata() {
89     return BaseDb::CreateMetadata() &&
90         UserDbHelper(this).UpdateUserInfo();
91   }
Backup(const string & snapshot_file)92   virtual bool Backup(const string& snapshot_file) {
93     return UserDbHelper::IsUniformFormat(snapshot_file) ?
94         UserDbHelper(this).UniformBackup(snapshot_file) :
95         BaseDb::Backup(snapshot_file);
96   }
Restore(const string & snapshot_file)97   virtual bool Restore(const string& snapshot_file) {
98     return UserDbHelper::IsUniformFormat(snapshot_file) ?
99         UserDbHelper(this).UniformRestore(snapshot_file) :
100         BaseDb::Restore(snapshot_file);
101   }
102 };
103 
104 /// Implements a component that serves as a factory for a user db class.
105 template <class BaseDb>
106 class UserDbComponent : public UserDb::Component,
107                         protected DbComponentBase {
108  public:
109   using UserDbImpl = UserDbWrapper<BaseDb>;
Create(const string & name)110   Db* Create(const string& name) override {
111     return new UserDbImpl(DbFilePath(name, extension()), name);
112   }
113 
114   string extension() const override;
115 };
116 
117 class UserDbMerger : public Sink {
118  public:
119   explicit UserDbMerger(Db* db);
120   virtual ~UserDbMerger();
121 
122   virtual bool MetaPut(const string& key, const string& value);
123   virtual bool Put(const string& key, const string& value);
124 
125   void CloseMerge();
126 
127  protected:
128   Db* db_;
129   TickCount our_tick_;
130   TickCount their_tick_;
131   TickCount max_tick_;
132   int merged_entries_;
133 };
134 
135 class UserDbImporter : public Sink {
136  public:
137   explicit UserDbImporter(Db* db);
138 
139   virtual bool MetaPut(const string& key, const string& value);
140   virtual bool Put(const string& key, const string& value);
141 
142  protected:
143   Db* db_;
144 };
145 
146 }  // namespace rime
147 
148 #endif  // RIME_USER_DB_H_
149