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/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.
    196   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.
    207   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 
    215   inline bool is_dirty() const {
    216     return dirty_;
    217   }
    218 
    219   // Setters.
    220   inline void put(MetahandleField field, int64 value) {
    221     int64_fields[field - INT64_FIELDS_BEGIN] = value;
    222   }
    223   inline void put(Int64Field field, int64 value) {
    224     int64_fields[field - INT64_FIELDS_BEGIN] = value;
    225   }
    226   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   }
    232   inline void put(IdField field, const Id& value) {
    233     id_fields[field - ID_FIELDS_BEGIN] = value;
    234   }
    235   inline void put(BaseVersion field, int64 value) {
    236     int64_fields[field - INT64_FIELDS_BEGIN] = value;
    237   }
    238   inline void put(IndexedBitField field, bool value) {
    239     bit_fields[field - BIT_FIELDS_BEGIN] = value;
    240   }
    241   inline void put(IsDelField field, bool value) {
    242     bit_fields[field - BIT_FIELDS_BEGIN] = value;
    243   }
    244   inline void put(BitField field, bool value) {
    245     bit_fields[field - BIT_FIELDS_BEGIN] = value;
    246   }
    247   inline void put(StringField field, const std::string& value) {
    248     string_fields[field - STRING_FIELDS_BEGIN] = value;
    249   }
    250   inline void put(ProtoField field, const sync_pb::EntitySpecifics& value) {
    251     specifics_fields[field - PROTO_FIELDS_BEGIN].CopyFrom(value);
    252   }
    253   inline void put(UniquePositionField field, const UniquePosition& value) {
    254     unique_position_fields[field - UNIQUE_POSITION_FIELDS_BEGIN] = value;
    255   }
    256   inline void put(BitTemp field, bool value) {
    257     bit_temps[field - BIT_TEMPS_BEGIN] = value;
    258   }
    259 
    260   // Const ref getters.
    261   inline int64 ref(MetahandleField field) const {
    262     return int64_fields[field - INT64_FIELDS_BEGIN];
    263   }
    264   inline int64 ref(Int64Field field) const {
    265     return int64_fields[field - INT64_FIELDS_BEGIN];
    266   }
    267   inline const base::Time& ref(TimeField field) const {
    268     return time_fields[field - TIME_FIELDS_BEGIN];
    269   }
    270   inline const Id& ref(IdField field) const {
    271     return id_fields[field - ID_FIELDS_BEGIN];
    272   }
    273   inline int64 ref(BaseVersion field) const {
    274     return int64_fields[field - INT64_FIELDS_BEGIN];
    275   }
    276   inline bool ref(IndexedBitField field) const {
    277     return bit_fields[field - BIT_FIELDS_BEGIN];
    278   }
    279   inline bool ref(IsDelField field) const {
    280     return bit_fields[field - BIT_FIELDS_BEGIN];
    281   }
    282   inline bool ref(BitField field) const {
    283     return bit_fields[field - BIT_FIELDS_BEGIN];
    284   }
    285   inline const std::string& ref(StringField field) const {
    286     return string_fields[field - STRING_FIELDS_BEGIN];
    287   }
    288   inline const sync_pb::EntitySpecifics& ref(ProtoField field) const {
    289     return specifics_fields[field - PROTO_FIELDS_BEGIN];
    290   }
    291   inline const UniquePosition& ref(UniquePositionField field) const {
    292     return unique_position_fields[field - UNIQUE_POSITION_FIELDS_BEGIN];
    293   }
    294   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.
    299   inline std::string& mutable_ref(StringField field) {
    300     return string_fields[field - STRING_FIELDS_BEGIN];
    301   }
    302   inline sync_pb::EntitySpecifics& mutable_ref(ProtoField field) {
    303     return specifics_fields[field - PROTO_FIELDS_BEGIN];
    304   }
    305   inline Id& mutable_ref(IdField field) {
    306     return id_fields[field - ID_FIELDS_BEGIN];
    307   }
    308   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:
    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