1 // Copyright 2012 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #ifndef SYNC_SYNCABLE_ENTRY_KERNEL_H_ 6 #define SYNC_SYNCABLE_ENTRY_KERNEL_H_ 7 8 #include <set> 9 10 #include "base/time/time.h" 11 #include "base/values.h" 12 #include "sync/base/sync_export.h" 13 #include "sync/internal_api/public/base/model_type.h" 14 #include "sync/internal_api/public/base/unique_position.h" 15 #include "sync/internal_api/public/util/immutable.h" 16 #include "sync/protocol/sync.pb.h" 17 #include "sync/syncable/metahandle_set.h" 18 #include "sync/syncable/syncable_id.h" 19 #include "sync/util/time.h" 20 21 namespace syncer { 22 23 class Cryptographer; 24 25 namespace syncable { 26 27 // Things you need to update if you change any of the fields below: 28 // - EntryKernel struct in this file 29 // - syncable_columns.h 30 // - syncable_enum_conversions{.h,.cc,_unittest.cc} 31 // - EntryKernel::EntryKernel(), EntryKernel::ToValue() in entry_kernel.cc 32 // - operator<< in Entry.cc 33 // - BindFields() and UnpackEntry() in directory_backing_store.cc 34 // - TestSimpleFieldsPreservedDuringSaveChanges in syncable_unittest.cc 35 36 static const int64 kInvalidMetaHandle = 0; 37 38 enum { 39 BEGIN_FIELDS = 0, 40 INT64_FIELDS_BEGIN = BEGIN_FIELDS 41 }; 42 43 enum MetahandleField { 44 // Primary key into the table. Keep this as a handle to the meta entry 45 // across transactions. 46 META_HANDLE = INT64_FIELDS_BEGIN 47 }; 48 49 enum BaseVersion { 50 // After initial upload, the version is controlled by the server, and is 51 // increased whenever the data or metadata changes on the server. 52 BASE_VERSION = META_HANDLE + 1, 53 }; 54 55 enum Int64Field { 56 SERVER_VERSION = BASE_VERSION + 1, 57 LOCAL_EXTERNAL_ID, // ID of an item in the external local storage that this 58 // entry is associated with. (such as bookmarks.js) 59 TRANSACTION_VERSION, 60 INT64_FIELDS_END 61 }; 62 63 enum { 64 INT64_FIELDS_COUNT = INT64_FIELDS_END - INT64_FIELDS_BEGIN, 65 TIME_FIELDS_BEGIN = INT64_FIELDS_END, 66 }; 67 68 enum TimeField { 69 MTIME = TIME_FIELDS_BEGIN, 70 SERVER_MTIME, 71 CTIME, 72 SERVER_CTIME, 73 TIME_FIELDS_END, 74 }; 75 76 enum { 77 TIME_FIELDS_COUNT = TIME_FIELDS_END - TIME_FIELDS_BEGIN, 78 ID_FIELDS_BEGIN = TIME_FIELDS_END, 79 }; 80 81 enum IdField { 82 // Code in InitializeTables relies on ID being the first IdField value. 83 ID = ID_FIELDS_BEGIN, 84 PARENT_ID, 85 SERVER_PARENT_ID, 86 ID_FIELDS_END 87 }; 88 89 enum { 90 ID_FIELDS_COUNT = ID_FIELDS_END - ID_FIELDS_BEGIN, 91 BIT_FIELDS_BEGIN = ID_FIELDS_END 92 }; 93 94 enum IndexedBitField { 95 IS_UNSYNCED = BIT_FIELDS_BEGIN, 96 IS_UNAPPLIED_UPDATE, 97 INDEXED_BIT_FIELDS_END, 98 }; 99 100 enum IsDelField { 101 IS_DEL = INDEXED_BIT_FIELDS_END, 102 }; 103 104 enum BitField { 105 IS_DIR = IS_DEL + 1, 106 SERVER_IS_DIR, 107 SERVER_IS_DEL, 108 BIT_FIELDS_END 109 }; 110 111 enum { 112 BIT_FIELDS_COUNT = BIT_FIELDS_END - BIT_FIELDS_BEGIN, 113 STRING_FIELDS_BEGIN = BIT_FIELDS_END 114 }; 115 116 enum StringField { 117 // Name, will be truncated by server. Can be duplicated in a folder. 118 NON_UNIQUE_NAME = STRING_FIELDS_BEGIN, 119 // The server version of |NON_UNIQUE_NAME|. 120 SERVER_NON_UNIQUE_NAME, 121 122 // A tag string which identifies this node as a particular top-level 123 // permanent object. The tag can be thought of as a unique key that 124 // identifies a singleton instance. 125 UNIQUE_SERVER_TAG, // Tagged by the server 126 UNIQUE_CLIENT_TAG, // Tagged by the client 127 UNIQUE_BOOKMARK_TAG, // Client tags for bookmark items 128 STRING_FIELDS_END, 129 }; 130 131 enum { 132 STRING_FIELDS_COUNT = STRING_FIELDS_END - STRING_FIELDS_BEGIN, 133 PROTO_FIELDS_BEGIN = STRING_FIELDS_END 134 }; 135 136 // From looking at the sqlite3 docs, it's not directly stated, but it 137 // seems the overhead for storing a NULL blob is very small. 138 enum ProtoField { 139 SPECIFICS = PROTO_FIELDS_BEGIN, 140 SERVER_SPECIFICS, 141 BASE_SERVER_SPECIFICS, 142 PROTO_FIELDS_END, 143 }; 144 145 enum { 146 PROTO_FIELDS_COUNT = PROTO_FIELDS_END - PROTO_FIELDS_BEGIN, 147 UNIQUE_POSITION_FIELDS_BEGIN = PROTO_FIELDS_END 148 }; 149 150 enum UniquePositionField { 151 SERVER_UNIQUE_POSITION = UNIQUE_POSITION_FIELDS_BEGIN, 152 UNIQUE_POSITION, 153 UNIQUE_POSITION_FIELDS_END 154 }; 155 156 enum { 157 UNIQUE_POSITION_FIELDS_COUNT = 158 UNIQUE_POSITION_FIELDS_END - UNIQUE_POSITION_FIELDS_BEGIN, 159 FIELD_COUNT = UNIQUE_POSITION_FIELDS_END - BEGIN_FIELDS, 160 // Past this point we have temporaries, stored in memory only. 161 BEGIN_TEMPS = UNIQUE_POSITION_FIELDS_END, 162 BIT_TEMPS_BEGIN = BEGIN_TEMPS, 163 }; 164 165 enum BitTemp { 166 // Not to be confused with IS_UNSYNCED, this bit is used to detect local 167 // changes to items that happen during the server Commit operation. 168 SYNCING = BIT_TEMPS_BEGIN, 169 BIT_TEMPS_END, 170 }; 171 172 enum { 173 BIT_TEMPS_COUNT = BIT_TEMPS_END - BIT_TEMPS_BEGIN 174 }; 175 176 177 178 struct SYNC_EXPORT_PRIVATE EntryKernel { 179 private: 180 std::string string_fields[STRING_FIELDS_COUNT]; 181 sync_pb::EntitySpecifics specifics_fields[PROTO_FIELDS_COUNT]; 182 int64 int64_fields[INT64_FIELDS_COUNT]; 183 base::Time time_fields[TIME_FIELDS_COUNT]; 184 Id id_fields[ID_FIELDS_COUNT]; 185 UniquePosition unique_position_fields[UNIQUE_POSITION_FIELDS_COUNT]; 186 std::bitset<BIT_FIELDS_COUNT> bit_fields; 187 std::bitset<BIT_TEMPS_COUNT> bit_temps; 188 189 public: 190 EntryKernel(); 191 ~EntryKernel(); 192 193 // Set the dirty bit, and optionally add this entry's metahandle to 194 // a provided index on dirty bits in |dirty_index|. Parameter may be null, 195 // and will result only in setting the dirty bit of this entry. mark_dirtyEntryKernel196 inline void mark_dirty(syncable::MetahandleSet* dirty_index) { 197 if (!dirty_ && dirty_index) { 198 DCHECK_NE(0, ref(META_HANDLE)); 199 dirty_index->insert(ref(META_HANDLE)); 200 } 201 dirty_ = true; 202 } 203 204 // Clear the dirty bit, and optionally remove this entry's metahandle from 205 // a provided index on dirty bits in |dirty_index|. Parameter may be null, 206 // and will result only in clearing dirty bit of this entry. clear_dirtyEntryKernel207 inline void clear_dirty(syncable::MetahandleSet* dirty_index) { 208 if (dirty_ && dirty_index) { 209 DCHECK_NE(0, ref(META_HANDLE)); 210 dirty_index->erase(ref(META_HANDLE)); 211 } 212 dirty_ = false; 213 } 214 is_dirtyEntryKernel215 inline bool is_dirty() const { 216 return dirty_; 217 } 218 219 // Setters. putEntryKernel220 inline void put(MetahandleField field, int64 value) { 221 int64_fields[field - INT64_FIELDS_BEGIN] = value; 222 } putEntryKernel223 inline void put(Int64Field field, int64 value) { 224 int64_fields[field - INT64_FIELDS_BEGIN] = value; 225 } putEntryKernel226 inline void put(TimeField field, const base::Time& value) { 227 // Round-trip to proto time format and back so that we have 228 // consistent time resolutions (ms). 229 time_fields[field - TIME_FIELDS_BEGIN] = 230 ProtoTimeToTime(TimeToProtoTime(value)); 231 } putEntryKernel232 inline void put(IdField field, const Id& value) { 233 id_fields[field - ID_FIELDS_BEGIN] = value; 234 } putEntryKernel235 inline void put(BaseVersion field, int64 value) { 236 int64_fields[field - INT64_FIELDS_BEGIN] = value; 237 } putEntryKernel238 inline void put(IndexedBitField field, bool value) { 239 bit_fields[field - BIT_FIELDS_BEGIN] = value; 240 } putEntryKernel241 inline void put(IsDelField field, bool value) { 242 bit_fields[field - BIT_FIELDS_BEGIN] = value; 243 } putEntryKernel244 inline void put(BitField field, bool value) { 245 bit_fields[field - BIT_FIELDS_BEGIN] = value; 246 } putEntryKernel247 inline void put(StringField field, const std::string& value) { 248 string_fields[field - STRING_FIELDS_BEGIN] = value; 249 } putEntryKernel250 inline void put(ProtoField field, const sync_pb::EntitySpecifics& value) { 251 specifics_fields[field - PROTO_FIELDS_BEGIN].CopyFrom(value); 252 } putEntryKernel253 inline void put(UniquePositionField field, const UniquePosition& value) { 254 unique_position_fields[field - UNIQUE_POSITION_FIELDS_BEGIN] = value; 255 } putEntryKernel256 inline void put(BitTemp field, bool value) { 257 bit_temps[field - BIT_TEMPS_BEGIN] = value; 258 } 259 260 // Const ref getters. refEntryKernel261 inline int64 ref(MetahandleField field) const { 262 return int64_fields[field - INT64_FIELDS_BEGIN]; 263 } refEntryKernel264 inline int64 ref(Int64Field field) const { 265 return int64_fields[field - INT64_FIELDS_BEGIN]; 266 } refEntryKernel267 inline const base::Time& ref(TimeField field) const { 268 return time_fields[field - TIME_FIELDS_BEGIN]; 269 } refEntryKernel270 inline const Id& ref(IdField field) const { 271 return id_fields[field - ID_FIELDS_BEGIN]; 272 } refEntryKernel273 inline int64 ref(BaseVersion field) const { 274 return int64_fields[field - INT64_FIELDS_BEGIN]; 275 } refEntryKernel276 inline bool ref(IndexedBitField field) const { 277 return bit_fields[field - BIT_FIELDS_BEGIN]; 278 } refEntryKernel279 inline bool ref(IsDelField field) const { 280 return bit_fields[field - BIT_FIELDS_BEGIN]; 281 } refEntryKernel282 inline bool ref(BitField field) const { 283 return bit_fields[field - BIT_FIELDS_BEGIN]; 284 } refEntryKernel285 inline const std::string& ref(StringField field) const { 286 return string_fields[field - STRING_FIELDS_BEGIN]; 287 } refEntryKernel288 inline const sync_pb::EntitySpecifics& ref(ProtoField field) const { 289 return specifics_fields[field - PROTO_FIELDS_BEGIN]; 290 } refEntryKernel291 inline const UniquePosition& ref(UniquePositionField field) const { 292 return unique_position_fields[field - UNIQUE_POSITION_FIELDS_BEGIN]; 293 } refEntryKernel294 inline bool ref(BitTemp field) const { 295 return bit_temps[field - BIT_TEMPS_BEGIN]; 296 } 297 298 // Non-const, mutable ref getters for object types only. mutable_refEntryKernel299 inline std::string& mutable_ref(StringField field) { 300 return string_fields[field - STRING_FIELDS_BEGIN]; 301 } mutable_refEntryKernel302 inline sync_pb::EntitySpecifics& mutable_ref(ProtoField field) { 303 return specifics_fields[field - PROTO_FIELDS_BEGIN]; 304 } mutable_refEntryKernel305 inline Id& mutable_ref(IdField field) { 306 return id_fields[field - ID_FIELDS_BEGIN]; 307 } mutable_refEntryKernel308 inline UniquePosition& mutable_ref(UniquePositionField field) { 309 return unique_position_fields[field - UNIQUE_POSITION_FIELDS_BEGIN]; 310 } 311 312 ModelType GetModelType() const; 313 ModelType GetServerModelType() const; 314 bool ShouldMaintainPosition() const; 315 316 // Dumps all kernel info into a DictionaryValue and returns it. 317 // Transfers ownership of the DictionaryValue to the caller. 318 // Note: |cryptographer| is an optional parameter for use in decrypting 319 // encrypted specifics. If it is NULL or the specifics are not decryptsble, 320 // they will be serialized as empty proto's. 321 base::DictionaryValue* ToValue(Cryptographer* cryptographer) const; 322 323 private: 324 // Tracks whether this entry needs to be saved to the database. 325 bool dirty_; 326 }; 327 328 class EntryKernelLessByMetaHandle { 329 public: operator()330 inline bool operator()(const EntryKernel* a, 331 const EntryKernel* b) const { 332 return a->ref(META_HANDLE) < b->ref(META_HANDLE); 333 } 334 }; 335 336 typedef std::set<const EntryKernel*, EntryKernelLessByMetaHandle> 337 EntryKernelSet; 338 339 struct EntryKernelMutation { 340 EntryKernel original, mutated; 341 }; 342 343 typedef std::map<int64, EntryKernelMutation> EntryKernelMutationMap; 344 345 typedef Immutable<EntryKernelMutationMap> ImmutableEntryKernelMutationMap; 346 347 // Caller owns the return value. 348 base::DictionaryValue* EntryKernelMutationToValue( 349 const EntryKernelMutation& mutation); 350 351 // Caller owns the return value. 352 base::ListValue* EntryKernelMutationMapToValue( 353 const EntryKernelMutationMap& mutations); 354 355 } // namespace syncable 356 } // namespace syncer 357 358 #endif // SYNC_SYNCABLE_ENTRY_KERNEL_H_ 359