Home | History | Annotate | Download | only in syncable
      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/attachments.pb.h"
     17 #include "sync/protocol/sync.pb.h"
     18 #include "sync/syncable/metahandle_set.h"
     19 #include "sync/syncable/syncable_id.h"
     20 #include "sync/util/time.h"
     21 
     22 namespace syncer {
     23 
     24 class Cryptographer;
     25 
     26 namespace syncable {
     27 
     28 // Things you need to update if you change any of the fields below:
     29 //  - EntryKernel struct in this file
     30 //  - syncable_columns.h
     31 //  - syncable_enum_conversions{.h,.cc,_unittest.cc}
     32 //  - EntryKernel::EntryKernel(), EntryKernel::ToValue() in entry_kernel.cc
     33 //  - operator<< in Entry.cc
     34 //  - BindFields() and UnpackEntry() in directory_backing_store.cc
     35 //  - kCurrentDBVersion, DirectoryBackingStore::InitializeTables in
     36 //    directory_backing_store.cc
     37 //  - TestSimpleFieldsPreservedDuringSaveChanges in syncable_unittest.cc
     38 
     39 static const int64 kInvalidMetaHandle = 0;
     40 
     41 enum {
     42   BEGIN_FIELDS = 0,
     43   INT64_FIELDS_BEGIN = BEGIN_FIELDS
     44 };
     45 
     46 enum MetahandleField {
     47   // Primary key into the table.  Keep this as a handle to the meta entry
     48   // across transactions.
     49   META_HANDLE = INT64_FIELDS_BEGIN
     50 };
     51 
     52 enum BaseVersion {
     53   // After initial upload, the version is controlled by the server, and is
     54   // increased whenever the data or metadata changes on the server.
     55   BASE_VERSION = META_HANDLE + 1,
     56 };
     57 
     58 enum Int64Field {
     59   SERVER_VERSION = BASE_VERSION + 1,
     60   LOCAL_EXTERNAL_ID,  // ID of an item in the external local storage that this
     61                       // entry is associated with. (such as bookmarks.js)
     62   TRANSACTION_VERSION,
     63   INT64_FIELDS_END
     64 };
     65 
     66 enum {
     67   INT64_FIELDS_COUNT = INT64_FIELDS_END - INT64_FIELDS_BEGIN,
     68   TIME_FIELDS_BEGIN = INT64_FIELDS_END,
     69 };
     70 
     71 enum TimeField {
     72   MTIME = TIME_FIELDS_BEGIN,
     73   SERVER_MTIME,
     74   CTIME,
     75   SERVER_CTIME,
     76   TIME_FIELDS_END,
     77 };
     78 
     79 enum {
     80   TIME_FIELDS_COUNT = TIME_FIELDS_END - TIME_FIELDS_BEGIN,
     81   ID_FIELDS_BEGIN = TIME_FIELDS_END,
     82 };
     83 
     84 enum IdField {
     85   // Code in InitializeTables relies on ID being the first IdField value.
     86   ID = ID_FIELDS_BEGIN,
     87   PARENT_ID,
     88   SERVER_PARENT_ID,
     89   ID_FIELDS_END
     90 };
     91 
     92 enum {
     93   ID_FIELDS_COUNT = ID_FIELDS_END - ID_FIELDS_BEGIN,
     94   BIT_FIELDS_BEGIN = ID_FIELDS_END
     95 };
     96 
     97 enum IndexedBitField {
     98   IS_UNSYNCED = BIT_FIELDS_BEGIN,
     99   IS_UNAPPLIED_UPDATE,
    100   INDEXED_BIT_FIELDS_END,
    101 };
    102 
    103 enum IsDelField {
    104   IS_DEL = INDEXED_BIT_FIELDS_END,
    105 };
    106 
    107 enum BitField {
    108   IS_DIR = IS_DEL + 1,
    109   SERVER_IS_DIR,
    110   SERVER_IS_DEL,
    111   BIT_FIELDS_END
    112 };
    113 
    114 enum {
    115   BIT_FIELDS_COUNT = BIT_FIELDS_END - BIT_FIELDS_BEGIN,
    116   STRING_FIELDS_BEGIN = BIT_FIELDS_END
    117 };
    118 
    119 enum 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   UNIQUE_BOOKMARK_TAG,  // Client tags for bookmark items
    131   STRING_FIELDS_END,
    132 };
    133 
    134 enum {
    135   STRING_FIELDS_COUNT = STRING_FIELDS_END - STRING_FIELDS_BEGIN,
    136   PROTO_FIELDS_BEGIN = STRING_FIELDS_END
    137 };
    138 
    139 // From looking at the sqlite3 docs, it's not directly stated, but it
    140 // seems the overhead for storing a NULL blob is very small.
    141 enum ProtoField {
    142   SPECIFICS = PROTO_FIELDS_BEGIN,
    143   SERVER_SPECIFICS,
    144   BASE_SERVER_SPECIFICS,
    145   PROTO_FIELDS_END,
    146 };
    147 
    148 enum {
    149   PROTO_FIELDS_COUNT = PROTO_FIELDS_END - PROTO_FIELDS_BEGIN,
    150   UNIQUE_POSITION_FIELDS_BEGIN = PROTO_FIELDS_END
    151 };
    152 
    153 enum UniquePositionField {
    154   SERVER_UNIQUE_POSITION = UNIQUE_POSITION_FIELDS_BEGIN,
    155   UNIQUE_POSITION,
    156   UNIQUE_POSITION_FIELDS_END
    157 };
    158 
    159 enum {
    160   UNIQUE_POSITION_FIELDS_COUNT =
    161       UNIQUE_POSITION_FIELDS_END - UNIQUE_POSITION_FIELDS_BEGIN,
    162   ATTACHMENT_METADATA_FIELDS_BEGIN = UNIQUE_POSITION_FIELDS_END
    163 };
    164 
    165 enum AttachmentMetadataField {
    166   ATTACHMENT_METADATA = ATTACHMENT_METADATA_FIELDS_BEGIN,
    167   ATTACHMENT_METADATA_FIELDS_END
    168 };
    169 
    170 enum {
    171   ATTACHMENT_METADATA_FIELDS_COUNT =
    172       ATTACHMENT_METADATA_FIELDS_END - ATTACHMENT_METADATA_FIELDS_BEGIN,
    173   FIELD_COUNT = ATTACHMENT_METADATA_FIELDS_END - BEGIN_FIELDS,
    174   // Past this point we have temporaries, stored in memory only.
    175   BEGIN_TEMPS = ATTACHMENT_METADATA_FIELDS_END,
    176   BIT_TEMPS_BEGIN = BEGIN_TEMPS,
    177 };
    178 
    179 enum BitTemp {
    180   // Not to be confused with IS_UNSYNCED, this bit is used to detect local
    181   // changes to items that happen during the server Commit operation.
    182   SYNCING = BIT_TEMPS_BEGIN,
    183   BIT_TEMPS_END,
    184 };
    185 
    186 enum {
    187   BIT_TEMPS_COUNT = BIT_TEMPS_END - BIT_TEMPS_BEGIN
    188 };
    189 
    190 
    191 
    192 struct SYNC_EXPORT_PRIVATE EntryKernel {
    193  private:
    194   std::string string_fields[STRING_FIELDS_COUNT];
    195   sync_pb::EntitySpecifics specifics_fields[PROTO_FIELDS_COUNT];
    196   int64 int64_fields[INT64_FIELDS_COUNT];
    197   base::Time time_fields[TIME_FIELDS_COUNT];
    198   Id id_fields[ID_FIELDS_COUNT];
    199   UniquePosition unique_position_fields[UNIQUE_POSITION_FIELDS_COUNT];
    200   sync_pb::AttachmentMetadata
    201       attachment_metadata_fields[ATTACHMENT_METADATA_FIELDS_COUNT];
    202   std::bitset<BIT_FIELDS_COUNT> bit_fields;
    203   std::bitset<BIT_TEMPS_COUNT> bit_temps;
    204 
    205  public:
    206   EntryKernel();
    207   ~EntryKernel();
    208 
    209   // Set the dirty bit, and optionally add this entry's metahandle to
    210   // a provided index on dirty bits in |dirty_index|. Parameter may be null,
    211   // and will result only in setting the dirty bit of this entry.
    212   inline void mark_dirty(syncable::MetahandleSet* dirty_index) {
    213     if (!dirty_ && dirty_index) {
    214       DCHECK_NE(0, ref(META_HANDLE));
    215       dirty_index->insert(ref(META_HANDLE));
    216     }
    217     dirty_ = true;
    218   }
    219 
    220   // Clear the dirty bit, and optionally remove this entry's metahandle from
    221   // a provided index on dirty bits in |dirty_index|. Parameter may be null,
    222   // and will result only in clearing dirty bit of this entry.
    223   inline void clear_dirty(syncable::MetahandleSet* dirty_index) {
    224     if (dirty_ && dirty_index) {
    225       DCHECK_NE(0, ref(META_HANDLE));
    226       dirty_index->erase(ref(META_HANDLE));
    227     }
    228     dirty_ = false;
    229   }
    230 
    231   inline bool is_dirty() const {
    232     return dirty_;
    233   }
    234 
    235   // Setters.
    236   inline void put(MetahandleField field, int64 value) {
    237     int64_fields[field - INT64_FIELDS_BEGIN] = value;
    238   }
    239   inline void put(Int64Field field, int64 value) {
    240     int64_fields[field - INT64_FIELDS_BEGIN] = value;
    241   }
    242   inline void put(TimeField field, const base::Time& value) {
    243     // Round-trip to proto time format and back so that we have
    244     // consistent time resolutions (ms).
    245     time_fields[field - TIME_FIELDS_BEGIN] =
    246         ProtoTimeToTime(TimeToProtoTime(value));
    247   }
    248   inline void put(IdField field, const Id& value) {
    249     id_fields[field - ID_FIELDS_BEGIN] = value;
    250   }
    251   inline void put(BaseVersion field, int64 value) {
    252     int64_fields[field - INT64_FIELDS_BEGIN] = value;
    253   }
    254   inline void put(IndexedBitField field, bool value) {
    255     bit_fields[field - BIT_FIELDS_BEGIN] = value;
    256   }
    257   inline void put(IsDelField field, bool value) {
    258     bit_fields[field - BIT_FIELDS_BEGIN] = value;
    259   }
    260   inline void put(BitField field, bool value) {
    261     bit_fields[field - BIT_FIELDS_BEGIN] = value;
    262   }
    263   inline void put(StringField field, const std::string& value) {
    264     string_fields[field - STRING_FIELDS_BEGIN] = value;
    265   }
    266   inline void put(ProtoField field, const sync_pb::EntitySpecifics& value) {
    267     specifics_fields[field - PROTO_FIELDS_BEGIN].CopyFrom(value);
    268   }
    269   inline void put(UniquePositionField field, const UniquePosition& value) {
    270     unique_position_fields[field - UNIQUE_POSITION_FIELDS_BEGIN] = value;
    271   }
    272   inline void put(AttachmentMetadataField field,
    273                   const sync_pb::AttachmentMetadata& value) {
    274     attachment_metadata_fields[field - ATTACHMENT_METADATA_FIELDS_BEGIN] =
    275         value;
    276   }
    277   inline void put(BitTemp field, bool value) {
    278     bit_temps[field - BIT_TEMPS_BEGIN] = value;
    279   }
    280 
    281   // Const ref getters.
    282   inline int64 ref(MetahandleField field) const {
    283     return int64_fields[field - INT64_FIELDS_BEGIN];
    284   }
    285   inline int64 ref(Int64Field field) const {
    286     return int64_fields[field - INT64_FIELDS_BEGIN];
    287   }
    288   inline const base::Time& ref(TimeField field) const {
    289     return time_fields[field - TIME_FIELDS_BEGIN];
    290   }
    291   inline const Id& ref(IdField field) const {
    292     return id_fields[field - ID_FIELDS_BEGIN];
    293   }
    294   inline int64 ref(BaseVersion field) const {
    295     return int64_fields[field - INT64_FIELDS_BEGIN];
    296   }
    297   inline bool ref(IndexedBitField field) const {
    298     return bit_fields[field - BIT_FIELDS_BEGIN];
    299   }
    300   inline bool ref(IsDelField field) const {
    301     return bit_fields[field - BIT_FIELDS_BEGIN];
    302   }
    303   inline bool ref(BitField field) const {
    304     return bit_fields[field - BIT_FIELDS_BEGIN];
    305   }
    306   inline const std::string& ref(StringField field) const {
    307     return string_fields[field - STRING_FIELDS_BEGIN];
    308   }
    309   inline const sync_pb::EntitySpecifics& ref(ProtoField field) const {
    310     return specifics_fields[field - PROTO_FIELDS_BEGIN];
    311   }
    312   inline const UniquePosition& ref(UniquePositionField field) const {
    313     return unique_position_fields[field - UNIQUE_POSITION_FIELDS_BEGIN];
    314   }
    315   inline const sync_pb::AttachmentMetadata& ref(
    316       AttachmentMetadataField field) const {
    317     return attachment_metadata_fields[field - ATTACHMENT_METADATA_FIELDS_BEGIN];
    318   }
    319   inline bool ref(BitTemp field) const {
    320     return bit_temps[field - BIT_TEMPS_BEGIN];
    321   }
    322 
    323   // Non-const, mutable ref getters for object types only.
    324   inline std::string& mutable_ref(StringField field) {
    325     return string_fields[field - STRING_FIELDS_BEGIN];
    326   }
    327   inline sync_pb::EntitySpecifics& mutable_ref(ProtoField field) {
    328     return specifics_fields[field - PROTO_FIELDS_BEGIN];
    329   }
    330   inline Id& mutable_ref(IdField field) {
    331     return id_fields[field - ID_FIELDS_BEGIN];
    332   }
    333   inline UniquePosition& mutable_ref(UniquePositionField field) {
    334     return unique_position_fields[field - UNIQUE_POSITION_FIELDS_BEGIN];
    335   }
    336   inline sync_pb::AttachmentMetadata& mutable_ref(
    337       AttachmentMetadataField field) {
    338     return attachment_metadata_fields[field - ATTACHMENT_METADATA_FIELDS_BEGIN];
    339   }
    340 
    341   ModelType GetModelType() const;
    342   ModelType GetServerModelType() const;
    343   bool ShouldMaintainPosition() const;
    344 
    345   // Dumps all kernel info into a DictionaryValue and returns it.
    346   // Transfers ownership of the DictionaryValue to the caller.
    347   // Note: |cryptographer| is an optional parameter for use in decrypting
    348   // encrypted specifics. If it is NULL or the specifics are not decryptsble,
    349   // they will be serialized as empty proto's.
    350   base::DictionaryValue* ToValue(Cryptographer* cryptographer) const;
    351 
    352  private:
    353   // Tracks whether this entry needs to be saved to the database.
    354   bool dirty_;
    355 };
    356 
    357 class EntryKernelLessByMetaHandle {
    358  public:
    359   inline bool operator()(const EntryKernel* a,
    360                          const EntryKernel* b) const {
    361     return a->ref(META_HANDLE) < b->ref(META_HANDLE);
    362   }
    363 };
    364 
    365 typedef std::set<const EntryKernel*, EntryKernelLessByMetaHandle>
    366     EntryKernelSet;
    367 
    368 struct EntryKernelMutation {
    369   EntryKernel original, mutated;
    370 };
    371 
    372 typedef std::map<int64, EntryKernelMutation> EntryKernelMutationMap;
    373 
    374 typedef Immutable<EntryKernelMutationMap> ImmutableEntryKernelMutationMap;
    375 
    376 // Caller owns the return value.
    377 base::DictionaryValue* EntryKernelMutationToValue(
    378     const EntryKernelMutation& mutation);
    379 
    380 // Caller owns the return value.
    381 base::ListValue* EntryKernelMutationMapToValue(
    382     const EntryKernelMutationMap& mutations);
    383 
    384 }  // namespace syncable
    385 }  // namespace syncer
    386 
    387 #endif // SYNC_SYNCABLE_ENTRY_KERNEL_H_
    388