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   SERVER_ATTACHMENT_METADATA,
    168   ATTACHMENT_METADATA_FIELDS_END
    169 };
    170 
    171 enum {
    172   ATTACHMENT_METADATA_FIELDS_COUNT =
    173       ATTACHMENT_METADATA_FIELDS_END - ATTACHMENT_METADATA_FIELDS_BEGIN,
    174   FIELD_COUNT = ATTACHMENT_METADATA_FIELDS_END - BEGIN_FIELDS,
    175   // Past this point we have temporaries, stored in memory only.
    176   BEGIN_TEMPS = ATTACHMENT_METADATA_FIELDS_END,
    177   BIT_TEMPS_BEGIN = BEGIN_TEMPS,
    178 };
    179 
    180 enum BitTemp {
    181   // Not to be confused with IS_UNSYNCED, this bit is used to detect local
    182   // changes to items that happen during the server Commit operation.
    183   SYNCING = BIT_TEMPS_BEGIN,
    184   BIT_TEMPS_END,
    185 };
    186 
    187 enum {
    188   BIT_TEMPS_COUNT = BIT_TEMPS_END - BIT_TEMPS_BEGIN
    189 };
    190 
    191 
    192 
    193 struct SYNC_EXPORT_PRIVATE EntryKernel {
    194  private:
    195   std::string string_fields[STRING_FIELDS_COUNT];
    196   sync_pb::EntitySpecifics specifics_fields[PROTO_FIELDS_COUNT];
    197   int64 int64_fields[INT64_FIELDS_COUNT];
    198   base::Time time_fields[TIME_FIELDS_COUNT];
    199   Id id_fields[ID_FIELDS_COUNT];
    200   UniquePosition unique_position_fields[UNIQUE_POSITION_FIELDS_COUNT];
    201   sync_pb::AttachmentMetadata
    202       attachment_metadata_fields[ATTACHMENT_METADATA_FIELDS_COUNT];
    203   std::bitset<BIT_FIELDS_COUNT> bit_fields;
    204   std::bitset<BIT_TEMPS_COUNT> bit_temps;
    205 
    206  public:
    207   EntryKernel();
    208   ~EntryKernel();
    209 
    210   // Set the dirty bit, and optionally add this entry's metahandle to
    211   // a provided index on dirty bits in |dirty_index|. Parameter may be null,
    212   // and will result only in setting the dirty bit of this entry.
    213   inline void mark_dirty(syncable::MetahandleSet* dirty_index) {
    214     if (!dirty_ && dirty_index) {
    215       DCHECK_NE(0, ref(META_HANDLE));
    216       dirty_index->insert(ref(META_HANDLE));
    217     }
    218     dirty_ = true;
    219   }
    220 
    221   // Clear the dirty bit, and optionally remove this entry's metahandle from
    222   // a provided index on dirty bits in |dirty_index|. Parameter may be null,
    223   // and will result only in clearing dirty bit of this entry.
    224   inline void clear_dirty(syncable::MetahandleSet* dirty_index) {
    225     if (dirty_ && dirty_index) {
    226       DCHECK_NE(0, ref(META_HANDLE));
    227       dirty_index->erase(ref(META_HANDLE));
    228     }
    229     dirty_ = false;
    230   }
    231 
    232   inline bool is_dirty() const {
    233     return dirty_;
    234   }
    235 
    236   // Setters.
    237   inline void put(MetahandleField field, int64 value) {
    238     int64_fields[field - INT64_FIELDS_BEGIN] = value;
    239   }
    240   inline void put(Int64Field field, int64 value) {
    241     int64_fields[field - INT64_FIELDS_BEGIN] = value;
    242   }
    243   inline void put(TimeField field, const base::Time& value) {
    244     // Round-trip to proto time format and back so that we have
    245     // consistent time resolutions (ms).
    246     time_fields[field - TIME_FIELDS_BEGIN] =
    247         ProtoTimeToTime(TimeToProtoTime(value));
    248   }
    249   inline void put(IdField field, const Id& value) {
    250     id_fields[field - ID_FIELDS_BEGIN] = value;
    251   }
    252   inline void put(BaseVersion field, int64 value) {
    253     int64_fields[field - INT64_FIELDS_BEGIN] = value;
    254   }
    255   inline void put(IndexedBitField field, bool value) {
    256     bit_fields[field - BIT_FIELDS_BEGIN] = value;
    257   }
    258   inline void put(IsDelField field, bool value) {
    259     bit_fields[field - BIT_FIELDS_BEGIN] = value;
    260   }
    261   inline void put(BitField field, bool value) {
    262     bit_fields[field - BIT_FIELDS_BEGIN] = value;
    263   }
    264   inline void put(StringField field, const std::string& value) {
    265     string_fields[field - STRING_FIELDS_BEGIN] = value;
    266   }
    267   inline void put(ProtoField field, const sync_pb::EntitySpecifics& value) {
    268     specifics_fields[field - PROTO_FIELDS_BEGIN].CopyFrom(value);
    269   }
    270   inline void put(UniquePositionField field, const UniquePosition& value) {
    271     unique_position_fields[field - UNIQUE_POSITION_FIELDS_BEGIN] = value;
    272   }
    273   inline void put(AttachmentMetadataField field,
    274                   const sync_pb::AttachmentMetadata& value) {
    275     attachment_metadata_fields[field - ATTACHMENT_METADATA_FIELDS_BEGIN] =
    276         value;
    277   }
    278   inline void put(BitTemp field, bool value) {
    279     bit_temps[field - BIT_TEMPS_BEGIN] = value;
    280   }
    281 
    282   // Const ref getters.
    283   inline int64 ref(MetahandleField field) const {
    284     return int64_fields[field - INT64_FIELDS_BEGIN];
    285   }
    286   inline int64 ref(Int64Field field) const {
    287     return int64_fields[field - INT64_FIELDS_BEGIN];
    288   }
    289   inline const base::Time& ref(TimeField field) const {
    290     return time_fields[field - TIME_FIELDS_BEGIN];
    291   }
    292   inline const Id& ref(IdField field) const {
    293     return id_fields[field - ID_FIELDS_BEGIN];
    294   }
    295   inline int64 ref(BaseVersion field) const {
    296     return int64_fields[field - INT64_FIELDS_BEGIN];
    297   }
    298   inline bool ref(IndexedBitField field) const {
    299     return bit_fields[field - BIT_FIELDS_BEGIN];
    300   }
    301   inline bool ref(IsDelField field) const {
    302     return bit_fields[field - BIT_FIELDS_BEGIN];
    303   }
    304   inline bool ref(BitField field) const {
    305     return bit_fields[field - BIT_FIELDS_BEGIN];
    306   }
    307   inline const std::string& ref(StringField field) const {
    308     return string_fields[field - STRING_FIELDS_BEGIN];
    309   }
    310   inline const sync_pb::EntitySpecifics& ref(ProtoField field) const {
    311     return specifics_fields[field - PROTO_FIELDS_BEGIN];
    312   }
    313   inline const UniquePosition& ref(UniquePositionField field) const {
    314     return unique_position_fields[field - UNIQUE_POSITION_FIELDS_BEGIN];
    315   }
    316   inline const sync_pb::AttachmentMetadata& ref(
    317       AttachmentMetadataField field) const {
    318     return attachment_metadata_fields[field - ATTACHMENT_METADATA_FIELDS_BEGIN];
    319   }
    320   inline bool ref(BitTemp field) const {
    321     return bit_temps[field - BIT_TEMPS_BEGIN];
    322   }
    323 
    324   // Non-const, mutable ref getters for object types only.
    325   inline std::string& mutable_ref(StringField field) {
    326     return string_fields[field - STRING_FIELDS_BEGIN];
    327   }
    328   inline sync_pb::EntitySpecifics& mutable_ref(ProtoField field) {
    329     return specifics_fields[field - PROTO_FIELDS_BEGIN];
    330   }
    331   inline Id& mutable_ref(IdField field) {
    332     return id_fields[field - ID_FIELDS_BEGIN];
    333   }
    334   inline UniquePosition& mutable_ref(UniquePositionField field) {
    335     return unique_position_fields[field - UNIQUE_POSITION_FIELDS_BEGIN];
    336   }
    337   inline sync_pb::AttachmentMetadata& mutable_ref(
    338       AttachmentMetadataField field) {
    339     return attachment_metadata_fields[field - ATTACHMENT_METADATA_FIELDS_BEGIN];
    340   }
    341 
    342   ModelType GetModelType() const;
    343   ModelType GetServerModelType() const;
    344   bool ShouldMaintainPosition() const;
    345   bool ShouldMaintainHierarchy() const;
    346 
    347   // Dumps all kernel info into a DictionaryValue and returns it.
    348   // Transfers ownership of the DictionaryValue to the caller.
    349   // Note: |cryptographer| is an optional parameter for use in decrypting
    350   // encrypted specifics. If it is NULL or the specifics are not decryptsble,
    351   // they will be serialized as empty proto's.
    352   base::DictionaryValue* ToValue(Cryptographer* cryptographer) const;
    353 
    354  private:
    355   // Tracks whether this entry needs to be saved to the database.
    356   bool dirty_;
    357 };
    358 
    359 class EntryKernelLessByMetaHandle {
    360  public:
    361   inline bool operator()(const EntryKernel* a,
    362                          const EntryKernel* b) const {
    363     return a->ref(META_HANDLE) < b->ref(META_HANDLE);
    364   }
    365 };
    366 
    367 typedef std::set<const EntryKernel*, EntryKernelLessByMetaHandle>
    368     EntryKernelSet;
    369 
    370 struct EntryKernelMutation {
    371   EntryKernel original, mutated;
    372 };
    373 
    374 typedef std::map<int64, EntryKernelMutation> EntryKernelMutationMap;
    375 
    376 typedef Immutable<EntryKernelMutationMap> ImmutableEntryKernelMutationMap;
    377 
    378 // Caller owns the return value.
    379 base::DictionaryValue* EntryKernelMutationToValue(
    380     const EntryKernelMutation& mutation);
    381 
    382 // Caller owns the return value.
    383 base::ListValue* EntryKernelMutationMapToValue(
    384     const EntryKernelMutationMap& mutations);
    385 
    386 }  // namespace syncable
    387 }  // namespace syncer
    388 
    389 #endif // SYNC_SYNCABLE_ENTRY_KERNEL_H_
    390