• 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/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.
mark_dirtyEntryKernel196   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.
clear_dirtyEntryKernel207   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 
is_dirtyEntryKernel215   inline bool is_dirty() const {
216     return dirty_;
217   }
218 
219   // Setters.
putEntryKernel220   inline void put(MetahandleField field, int64 value) {
221     int64_fields[field - INT64_FIELDS_BEGIN] = value;
222   }
putEntryKernel223   inline void put(Int64Field field, int64 value) {
224     int64_fields[field - INT64_FIELDS_BEGIN] = value;
225   }
putEntryKernel226   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   }
putEntryKernel232   inline void put(IdField field, const Id& value) {
233     id_fields[field - ID_FIELDS_BEGIN] = value;
234   }
putEntryKernel235   inline void put(BaseVersion field, int64 value) {
236     int64_fields[field - INT64_FIELDS_BEGIN] = value;
237   }
putEntryKernel238   inline void put(IndexedBitField field, bool value) {
239     bit_fields[field - BIT_FIELDS_BEGIN] = value;
240   }
putEntryKernel241   inline void put(IsDelField field, bool value) {
242     bit_fields[field - BIT_FIELDS_BEGIN] = value;
243   }
putEntryKernel244   inline void put(BitField field, bool value) {
245     bit_fields[field - BIT_FIELDS_BEGIN] = value;
246   }
putEntryKernel247   inline void put(StringField field, const std::string& value) {
248     string_fields[field - STRING_FIELDS_BEGIN] = value;
249   }
putEntryKernel250   inline void put(ProtoField field, const sync_pb::EntitySpecifics& value) {
251     specifics_fields[field - PROTO_FIELDS_BEGIN].CopyFrom(value);
252   }
putEntryKernel253   inline void put(UniquePositionField field, const UniquePosition& value) {
254     unique_position_fields[field - UNIQUE_POSITION_FIELDS_BEGIN] = value;
255   }
putEntryKernel256   inline void put(BitTemp field, bool value) {
257     bit_temps[field - BIT_TEMPS_BEGIN] = value;
258   }
259 
260   // Const ref getters.
refEntryKernel261   inline int64 ref(MetahandleField field) const {
262     return int64_fields[field - INT64_FIELDS_BEGIN];
263   }
refEntryKernel264   inline int64 ref(Int64Field field) const {
265     return int64_fields[field - INT64_FIELDS_BEGIN];
266   }
refEntryKernel267   inline const base::Time& ref(TimeField field) const {
268     return time_fields[field - TIME_FIELDS_BEGIN];
269   }
refEntryKernel270   inline const Id& ref(IdField field) const {
271     return id_fields[field - ID_FIELDS_BEGIN];
272   }
refEntryKernel273   inline int64 ref(BaseVersion field) const {
274     return int64_fields[field - INT64_FIELDS_BEGIN];
275   }
refEntryKernel276   inline bool ref(IndexedBitField field) const {
277     return bit_fields[field - BIT_FIELDS_BEGIN];
278   }
refEntryKernel279   inline bool ref(IsDelField field) const {
280     return bit_fields[field - BIT_FIELDS_BEGIN];
281   }
refEntryKernel282   inline bool ref(BitField field) const {
283     return bit_fields[field - BIT_FIELDS_BEGIN];
284   }
refEntryKernel285   inline const std::string& ref(StringField field) const {
286     return string_fields[field - STRING_FIELDS_BEGIN];
287   }
refEntryKernel288   inline const sync_pb::EntitySpecifics& ref(ProtoField field) const {
289     return specifics_fields[field - PROTO_FIELDS_BEGIN];
290   }
refEntryKernel291   inline const UniquePosition& ref(UniquePositionField field) const {
292     return unique_position_fields[field - UNIQUE_POSITION_FIELDS_BEGIN];
293   }
refEntryKernel294   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.
mutable_refEntryKernel299   inline std::string& mutable_ref(StringField field) {
300     return string_fields[field - STRING_FIELDS_BEGIN];
301   }
mutable_refEntryKernel302   inline sync_pb::EntitySpecifics& mutable_ref(ProtoField field) {
303     return specifics_fields[field - PROTO_FIELDS_BEGIN];
304   }
mutable_refEntryKernel305   inline Id& mutable_ref(IdField field) {
306     return id_fields[field - ID_FIELDS_BEGIN];
307   }
mutable_refEntryKernel308   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:
operator()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