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