• 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