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