• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.
mark_dirtyEntryKernel213    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.
clear_dirtyEntryKernel224    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  
is_dirtyEntryKernel232    inline bool is_dirty() const {
233      return dirty_;
234    }
235  
236    // Setters.
putEntryKernel237    inline void put(MetahandleField field, int64 value) {
238      int64_fields[field - INT64_FIELDS_BEGIN] = value;
239    }
putEntryKernel240    inline void put(Int64Field field, int64 value) {
241      int64_fields[field - INT64_FIELDS_BEGIN] = value;
242    }
putEntryKernel243    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    }
putEntryKernel249    inline void put(IdField field, const Id& value) {
250      id_fields[field - ID_FIELDS_BEGIN] = value;
251    }
putEntryKernel252    inline void put(BaseVersion field, int64 value) {
253      int64_fields[field - INT64_FIELDS_BEGIN] = value;
254    }
putEntryKernel255    inline void put(IndexedBitField field, bool value) {
256      bit_fields[field - BIT_FIELDS_BEGIN] = value;
257    }
putEntryKernel258    inline void put(IsDelField field, bool value) {
259      bit_fields[field - BIT_FIELDS_BEGIN] = value;
260    }
putEntryKernel261    inline void put(BitField field, bool value) {
262      bit_fields[field - BIT_FIELDS_BEGIN] = value;
263    }
putEntryKernel264    inline void put(StringField field, const std::string& value) {
265      string_fields[field - STRING_FIELDS_BEGIN] = value;
266    }
putEntryKernel267    inline void put(ProtoField field, const sync_pb::EntitySpecifics& value) {
268      specifics_fields[field - PROTO_FIELDS_BEGIN].CopyFrom(value);
269    }
putEntryKernel270    inline void put(UniquePositionField field, const UniquePosition& value) {
271      unique_position_fields[field - UNIQUE_POSITION_FIELDS_BEGIN] = value;
272    }
putEntryKernel273    inline void put(AttachmentMetadataField field,
274                    const sync_pb::AttachmentMetadata& value) {
275      attachment_metadata_fields[field - ATTACHMENT_METADATA_FIELDS_BEGIN] =
276          value;
277    }
putEntryKernel278    inline void put(BitTemp field, bool value) {
279      bit_temps[field - BIT_TEMPS_BEGIN] = value;
280    }
281  
282    // Const ref getters.
refEntryKernel283    inline int64 ref(MetahandleField field) const {
284      return int64_fields[field - INT64_FIELDS_BEGIN];
285    }
refEntryKernel286    inline int64 ref(Int64Field field) const {
287      return int64_fields[field - INT64_FIELDS_BEGIN];
288    }
refEntryKernel289    inline const base::Time& ref(TimeField field) const {
290      return time_fields[field - TIME_FIELDS_BEGIN];
291    }
refEntryKernel292    inline const Id& ref(IdField field) const {
293      return id_fields[field - ID_FIELDS_BEGIN];
294    }
refEntryKernel295    inline int64 ref(BaseVersion field) const {
296      return int64_fields[field - INT64_FIELDS_BEGIN];
297    }
refEntryKernel298    inline bool ref(IndexedBitField field) const {
299      return bit_fields[field - BIT_FIELDS_BEGIN];
300    }
refEntryKernel301    inline bool ref(IsDelField field) const {
302      return bit_fields[field - BIT_FIELDS_BEGIN];
303    }
refEntryKernel304    inline bool ref(BitField field) const {
305      return bit_fields[field - BIT_FIELDS_BEGIN];
306    }
refEntryKernel307    inline const std::string& ref(StringField field) const {
308      return string_fields[field - STRING_FIELDS_BEGIN];
309    }
refEntryKernel310    inline const sync_pb::EntitySpecifics& ref(ProtoField field) const {
311      return specifics_fields[field - PROTO_FIELDS_BEGIN];
312    }
refEntryKernel313    inline const UniquePosition& ref(UniquePositionField field) const {
314      return unique_position_fields[field - UNIQUE_POSITION_FIELDS_BEGIN];
315    }
refEntryKernel316    inline const sync_pb::AttachmentMetadata& ref(
317        AttachmentMetadataField field) const {
318      return attachment_metadata_fields[field - ATTACHMENT_METADATA_FIELDS_BEGIN];
319    }
refEntryKernel320    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.
mutable_refEntryKernel325    inline std::string& mutable_ref(StringField field) {
326      return string_fields[field - STRING_FIELDS_BEGIN];
327    }
mutable_refEntryKernel328    inline sync_pb::EntitySpecifics& mutable_ref(ProtoField field) {
329      return specifics_fields[field - PROTO_FIELDS_BEGIN];
330    }
mutable_refEntryKernel331    inline Id& mutable_ref(IdField field) {
332      return id_fields[field - ID_FIELDS_BEGIN];
333    }
mutable_refEntryKernel334    inline UniquePosition& mutable_ref(UniquePositionField field) {
335      return unique_position_fields[field - UNIQUE_POSITION_FIELDS_BEGIN];
336    }
mutable_refEntryKernel337    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:
operator()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