entry_kernel.h revision 2a99a7e74a7f215066514fe81d2bfa6639d9eddd
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.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/node_ordinal.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 21namespace syncer { 22 23class Cryptographer; 24 25namespace 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 36static const int64 kInvalidMetaHandle = 0; 37 38enum { 39 BEGIN_FIELDS = 0, 40 INT64_FIELDS_BEGIN = BEGIN_FIELDS 41}; 42 43enum 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 49enum 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 55enum 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 63enum { 64 INT64_FIELDS_COUNT = INT64_FIELDS_END - INT64_FIELDS_BEGIN, 65 TIME_FIELDS_BEGIN = INT64_FIELDS_END, 66}; 67 68enum TimeField { 69 MTIME = TIME_FIELDS_BEGIN, 70 SERVER_MTIME, 71 CTIME, 72 SERVER_CTIME, 73 TIME_FIELDS_END, 74}; 75 76enum { 77 TIME_FIELDS_COUNT = TIME_FIELDS_END - TIME_FIELDS_BEGIN, 78 ID_FIELDS_BEGIN = TIME_FIELDS_END, 79}; 80 81enum 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 87 PREV_ID, 88 NEXT_ID, 89 ID_FIELDS_END 90}; 91 92enum { 93 ID_FIELDS_COUNT = ID_FIELDS_END - ID_FIELDS_BEGIN, 94 BIT_FIELDS_BEGIN = ID_FIELDS_END 95}; 96 97enum IndexedBitField { 98 IS_UNSYNCED = BIT_FIELDS_BEGIN, 99 IS_UNAPPLIED_UPDATE, 100 INDEXED_BIT_FIELDS_END, 101}; 102 103enum IsDelField { 104 IS_DEL = INDEXED_BIT_FIELDS_END, 105}; 106 107enum BitField { 108 IS_DIR = IS_DEL + 1, 109 SERVER_IS_DIR, 110 SERVER_IS_DEL, 111 BIT_FIELDS_END 112}; 113 114enum { 115 BIT_FIELDS_COUNT = BIT_FIELDS_END - BIT_FIELDS_BEGIN, 116 STRING_FIELDS_BEGIN = BIT_FIELDS_END 117}; 118 119enum StringField { 120 // Name, will be truncated by server. Can be duplicated in a folder. 121 NON_UNIQUE_NAME = STRING_FIELDS_BEGIN, 122 // The server version of |NON_UNIQUE_NAME|. 123 SERVER_NON_UNIQUE_NAME, 124 125 // A tag string which identifies this node as a particular top-level 126 // permanent object. The tag can be thought of as a unique key that 127 // identifies a singleton instance. 128 UNIQUE_SERVER_TAG, // Tagged by the server 129 UNIQUE_CLIENT_TAG, // Tagged by the client 130 STRING_FIELDS_END, 131}; 132 133enum { 134 STRING_FIELDS_COUNT = STRING_FIELDS_END - STRING_FIELDS_BEGIN, 135 PROTO_FIELDS_BEGIN = STRING_FIELDS_END 136}; 137 138// From looking at the sqlite3 docs, it's not directly stated, but it 139// seems the overhead for storing a NULL blob is very small. 140enum ProtoField { 141 SPECIFICS = PROTO_FIELDS_BEGIN, 142 SERVER_SPECIFICS, 143 BASE_SERVER_SPECIFICS, 144 PROTO_FIELDS_END, 145}; 146 147enum { 148 PROTO_FIELDS_COUNT = PROTO_FIELDS_END - PROTO_FIELDS_BEGIN, 149 ORDINAL_FIELDS_BEGIN = PROTO_FIELDS_END 150}; 151 152enum OrdinalField { 153 // An Ordinal that identifies the relative ordering of this object 154 // among its siblings. 155 SERVER_ORDINAL_IN_PARENT = ORDINAL_FIELDS_BEGIN, 156 ORDINAL_FIELDS_END 157}; 158 159enum { 160 ORDINAL_FIELDS_COUNT = ORDINAL_FIELDS_END - ORDINAL_FIELDS_BEGIN, 161 FIELD_COUNT = ORDINAL_FIELDS_END - BEGIN_FIELDS, 162 // Past this point we have temporaries, stored in memory only. 163 BEGIN_TEMPS = ORDINAL_FIELDS_END, 164 BIT_TEMPS_BEGIN = BEGIN_TEMPS, 165}; 166 167enum BitTemp { 168 // Not to be confused with IS_UNSYNCED, this bit is used to detect local 169 // changes to items that happen during the server Commit operation. 170 SYNCING = BIT_TEMPS_BEGIN, 171 BIT_TEMPS_END, 172}; 173 174enum { 175 BIT_TEMPS_COUNT = BIT_TEMPS_END - BIT_TEMPS_BEGIN 176}; 177 178 179 180struct SYNC_EXPORT_PRIVATE EntryKernel { 181 private: 182 std::string string_fields[STRING_FIELDS_COUNT]; 183 sync_pb::EntitySpecifics specifics_fields[PROTO_FIELDS_COUNT]; 184 int64 int64_fields[INT64_FIELDS_COUNT]; 185 base::Time time_fields[TIME_FIELDS_COUNT]; 186 Id id_fields[ID_FIELDS_COUNT]; 187 NodeOrdinal ordinal_fields[ORDINAL_FIELDS_COUNT]; 188 std::bitset<BIT_FIELDS_COUNT> bit_fields; 189 std::bitset<BIT_TEMPS_COUNT> bit_temps; 190 191 public: 192 EntryKernel(); 193 ~EntryKernel(); 194 195 // Set the dirty bit, and optionally add this entry's metahandle to 196 // a provided index on dirty bits in |dirty_index|. Parameter may be null, 197 // and will result only in setting the dirty bit of this entry. 198 inline void mark_dirty(syncable::MetahandleSet* dirty_index) { 199 if (!dirty_ && dirty_index) { 200 DCHECK_NE(0, ref(META_HANDLE)); 201 dirty_index->insert(ref(META_HANDLE)); 202 } 203 dirty_ = true; 204 } 205 206 // Clear the dirty bit, and optionally remove this entry's metahandle from 207 // a provided index on dirty bits in |dirty_index|. Parameter may be null, 208 // and will result only in clearing dirty bit of this entry. 209 inline void clear_dirty(syncable::MetahandleSet* dirty_index) { 210 if (dirty_ && dirty_index) { 211 DCHECK_NE(0, ref(META_HANDLE)); 212 dirty_index->erase(ref(META_HANDLE)); 213 } 214 dirty_ = false; 215 } 216 217 inline bool is_dirty() const { 218 return dirty_; 219 } 220 221 // Setters. 222 inline void put(MetahandleField field, int64 value) { 223 int64_fields[field - INT64_FIELDS_BEGIN] = value; 224 } 225 inline void put(Int64Field field, int64 value) { 226 int64_fields[field - INT64_FIELDS_BEGIN] = value; 227 } 228 inline void put(TimeField field, const base::Time& value) { 229 // Round-trip to proto time format and back so that we have 230 // consistent time resolutions (ms). 231 time_fields[field - TIME_FIELDS_BEGIN] = 232 ProtoTimeToTime(TimeToProtoTime(value)); 233 } 234 inline void put(IdField field, const Id& value) { 235 id_fields[field - ID_FIELDS_BEGIN] = value; 236 } 237 inline void put(BaseVersion field, int64 value) { 238 int64_fields[field - INT64_FIELDS_BEGIN] = value; 239 } 240 inline void put(IndexedBitField field, bool value) { 241 bit_fields[field - BIT_FIELDS_BEGIN] = value; 242 } 243 inline void put(IsDelField field, bool value) { 244 bit_fields[field - BIT_FIELDS_BEGIN] = value; 245 } 246 inline void put(BitField field, bool value) { 247 bit_fields[field - BIT_FIELDS_BEGIN] = value; 248 } 249 inline void put(StringField field, const std::string& value) { 250 string_fields[field - STRING_FIELDS_BEGIN] = value; 251 } 252 inline void put(ProtoField field, const sync_pb::EntitySpecifics& value) { 253 specifics_fields[field - PROTO_FIELDS_BEGIN].CopyFrom(value); 254 } 255 inline void put(OrdinalField field, const NodeOrdinal& value) { 256 ordinal_fields[field - ORDINAL_FIELDS_BEGIN] = value; 257 } 258 inline void put(BitTemp field, bool value) { 259 bit_temps[field - BIT_TEMPS_BEGIN] = value; 260 } 261 262 // Const ref getters. 263 inline int64 ref(MetahandleField field) const { 264 return int64_fields[field - INT64_FIELDS_BEGIN]; 265 } 266 inline int64 ref(Int64Field field) const { 267 return int64_fields[field - INT64_FIELDS_BEGIN]; 268 } 269 inline const base::Time& ref(TimeField field) const { 270 return time_fields[field - TIME_FIELDS_BEGIN]; 271 } 272 inline const Id& ref(IdField field) const { 273 return id_fields[field - ID_FIELDS_BEGIN]; 274 } 275 inline int64 ref(BaseVersion field) const { 276 return int64_fields[field - INT64_FIELDS_BEGIN]; 277 } 278 inline bool ref(IndexedBitField field) const { 279 return bit_fields[field - BIT_FIELDS_BEGIN]; 280 } 281 inline bool ref(IsDelField field) const { 282 return bit_fields[field - BIT_FIELDS_BEGIN]; 283 } 284 inline bool ref(BitField field) const { 285 return bit_fields[field - BIT_FIELDS_BEGIN]; 286 } 287 inline const std::string& ref(StringField field) const { 288 return string_fields[field - STRING_FIELDS_BEGIN]; 289 } 290 inline const sync_pb::EntitySpecifics& ref(ProtoField field) const { 291 return specifics_fields[field - PROTO_FIELDS_BEGIN]; 292 } 293 inline const NodeOrdinal& ref(OrdinalField field) const { 294 return ordinal_fields[field - ORDINAL_FIELDS_BEGIN]; 295 } 296 inline bool ref(BitTemp field) const { 297 return bit_temps[field - BIT_TEMPS_BEGIN]; 298 } 299 300 // Non-const, mutable ref getters for object types only. 301 inline std::string& mutable_ref(StringField field) { 302 return string_fields[field - STRING_FIELDS_BEGIN]; 303 } 304 inline sync_pb::EntitySpecifics& mutable_ref(ProtoField field) { 305 return specifics_fields[field - PROTO_FIELDS_BEGIN]; 306 } 307 inline Id& mutable_ref(IdField field) { 308 return id_fields[field - ID_FIELDS_BEGIN]; 309 } 310 inline NodeOrdinal& mutable_ref(OrdinalField field) { 311 return ordinal_fields[field - ORDINAL_FIELDS_BEGIN]; 312 } 313 314 ModelType GetServerModelType() 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 328class EntryKernelLessByMetaHandle { 329 public: 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 336typedef std::set<const EntryKernel*, EntryKernelLessByMetaHandle> 337 EntryKernelSet; 338 339struct EntryKernelMutation { 340 EntryKernel original, mutated; 341}; 342 343typedef std::map<int64, EntryKernelMutation> EntryKernelMutationMap; 344 345typedef Immutable<EntryKernelMutationMap> ImmutableEntryKernelMutationMap; 346 347// Caller owns the return value. 348base::DictionaryValue* EntryKernelMutationToValue( 349 const EntryKernelMutation& mutation); 350 351// Caller owns the return value. 352base::ListValue* EntryKernelMutationMapToValue( 353 const EntryKernelMutationMap& mutations); 354 355} // namespace syncable 356} // namespace syncer 357 358#endif // SYNC_SYNCABLE_ENTRY_KERNEL_H_ 359