entry_kernel.h revision 2a99a7e74a7f215066514fe81d2bfa6639d9eddd
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.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/node_ordinal.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
21namespace syncer {
22
23class Cryptographer;
24
25namespace 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
36static const int64 kInvalidMetaHandle = 0;
37
38enum {
39  BEGIN_FIELDS = 0,
40  INT64_FIELDS_BEGIN = BEGIN_FIELDS
41};
42
43enum 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
49enum 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
55enum 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
63enum {
64  INT64_FIELDS_COUNT = INT64_FIELDS_END - INT64_FIELDS_BEGIN,
65  TIME_FIELDS_BEGIN = INT64_FIELDS_END,
66};
67
68enum TimeField {
69  MTIME = TIME_FIELDS_BEGIN,
70  SERVER_MTIME,
71  CTIME,
72  SERVER_CTIME,
73  TIME_FIELDS_END,
74};
75
76enum {
77  TIME_FIELDS_COUNT = TIME_FIELDS_END - TIME_FIELDS_BEGIN,
78  ID_FIELDS_BEGIN = TIME_FIELDS_END,
79};
80
81enum 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
87  PREV_ID,
88  NEXT_ID,
89  ID_FIELDS_END
90};
91
92enum {
93  ID_FIELDS_COUNT = ID_FIELDS_END - ID_FIELDS_BEGIN,
94  BIT_FIELDS_BEGIN = ID_FIELDS_END
95};
96
97enum IndexedBitField {
98  IS_UNSYNCED = BIT_FIELDS_BEGIN,
99  IS_UNAPPLIED_UPDATE,
100  INDEXED_BIT_FIELDS_END,
101};
102
103enum IsDelField {
104  IS_DEL = INDEXED_BIT_FIELDS_END,
105};
106
107enum BitField {
108  IS_DIR = IS_DEL + 1,
109  SERVER_IS_DIR,
110  SERVER_IS_DEL,
111  BIT_FIELDS_END
112};
113
114enum {
115  BIT_FIELDS_COUNT = BIT_FIELDS_END - BIT_FIELDS_BEGIN,
116  STRING_FIELDS_BEGIN = BIT_FIELDS_END
117};
118
119enum 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  STRING_FIELDS_END,
131};
132
133enum {
134  STRING_FIELDS_COUNT = STRING_FIELDS_END - STRING_FIELDS_BEGIN,
135  PROTO_FIELDS_BEGIN = STRING_FIELDS_END
136};
137
138// From looking at the sqlite3 docs, it's not directly stated, but it
139// seems the overhead for storing a NULL blob is very small.
140enum ProtoField {
141  SPECIFICS = PROTO_FIELDS_BEGIN,
142  SERVER_SPECIFICS,
143  BASE_SERVER_SPECIFICS,
144  PROTO_FIELDS_END,
145};
146
147enum {
148  PROTO_FIELDS_COUNT = PROTO_FIELDS_END - PROTO_FIELDS_BEGIN,
149  ORDINAL_FIELDS_BEGIN = PROTO_FIELDS_END
150};
151
152enum OrdinalField {
153  // An Ordinal that identifies the relative ordering of this object
154  // among its siblings.
155  SERVER_ORDINAL_IN_PARENT = ORDINAL_FIELDS_BEGIN,
156  ORDINAL_FIELDS_END
157};
158
159enum {
160  ORDINAL_FIELDS_COUNT = ORDINAL_FIELDS_END - ORDINAL_FIELDS_BEGIN,
161  FIELD_COUNT = ORDINAL_FIELDS_END - BEGIN_FIELDS,
162  // Past this point we have temporaries, stored in memory only.
163  BEGIN_TEMPS = ORDINAL_FIELDS_END,
164  BIT_TEMPS_BEGIN = BEGIN_TEMPS,
165};
166
167enum BitTemp {
168  // Not to be confused with IS_UNSYNCED, this bit is used to detect local
169  // changes to items that happen during the server Commit operation.
170  SYNCING = BIT_TEMPS_BEGIN,
171  BIT_TEMPS_END,
172};
173
174enum {
175  BIT_TEMPS_COUNT = BIT_TEMPS_END - BIT_TEMPS_BEGIN
176};
177
178
179
180struct SYNC_EXPORT_PRIVATE EntryKernel {
181 private:
182  std::string string_fields[STRING_FIELDS_COUNT];
183  sync_pb::EntitySpecifics specifics_fields[PROTO_FIELDS_COUNT];
184  int64 int64_fields[INT64_FIELDS_COUNT];
185  base::Time time_fields[TIME_FIELDS_COUNT];
186  Id id_fields[ID_FIELDS_COUNT];
187  NodeOrdinal ordinal_fields[ORDINAL_FIELDS_COUNT];
188  std::bitset<BIT_FIELDS_COUNT> bit_fields;
189  std::bitset<BIT_TEMPS_COUNT> bit_temps;
190
191 public:
192  EntryKernel();
193  ~EntryKernel();
194
195  // Set the dirty bit, and optionally add this entry's metahandle to
196  // a provided index on dirty bits in |dirty_index|. Parameter may be null,
197  // and will result only in setting the dirty bit of this entry.
198  inline void mark_dirty(syncable::MetahandleSet* dirty_index) {
199    if (!dirty_ && dirty_index) {
200      DCHECK_NE(0, ref(META_HANDLE));
201      dirty_index->insert(ref(META_HANDLE));
202    }
203    dirty_ = true;
204  }
205
206  // Clear the dirty bit, and optionally remove this entry's metahandle from
207  // a provided index on dirty bits in |dirty_index|. Parameter may be null,
208  // and will result only in clearing dirty bit of this entry.
209  inline void clear_dirty(syncable::MetahandleSet* dirty_index) {
210    if (dirty_ && dirty_index) {
211      DCHECK_NE(0, ref(META_HANDLE));
212      dirty_index->erase(ref(META_HANDLE));
213    }
214    dirty_ = false;
215  }
216
217  inline bool is_dirty() const {
218    return dirty_;
219  }
220
221  // Setters.
222  inline void put(MetahandleField field, int64 value) {
223    int64_fields[field - INT64_FIELDS_BEGIN] = value;
224  }
225  inline void put(Int64Field field, int64 value) {
226    int64_fields[field - INT64_FIELDS_BEGIN] = value;
227  }
228  inline void put(TimeField field, const base::Time& value) {
229    // Round-trip to proto time format and back so that we have
230    // consistent time resolutions (ms).
231    time_fields[field - TIME_FIELDS_BEGIN] =
232        ProtoTimeToTime(TimeToProtoTime(value));
233  }
234  inline void put(IdField field, const Id& value) {
235    id_fields[field - ID_FIELDS_BEGIN] = value;
236  }
237  inline void put(BaseVersion field, int64 value) {
238    int64_fields[field - INT64_FIELDS_BEGIN] = value;
239  }
240  inline void put(IndexedBitField field, bool value) {
241    bit_fields[field - BIT_FIELDS_BEGIN] = value;
242  }
243  inline void put(IsDelField field, bool value) {
244    bit_fields[field - BIT_FIELDS_BEGIN] = value;
245  }
246  inline void put(BitField field, bool value) {
247    bit_fields[field - BIT_FIELDS_BEGIN] = value;
248  }
249  inline void put(StringField field, const std::string& value) {
250    string_fields[field - STRING_FIELDS_BEGIN] = value;
251  }
252  inline void put(ProtoField field, const sync_pb::EntitySpecifics& value) {
253    specifics_fields[field - PROTO_FIELDS_BEGIN].CopyFrom(value);
254  }
255  inline void put(OrdinalField field, const NodeOrdinal& value) {
256    ordinal_fields[field - ORDINAL_FIELDS_BEGIN] = value;
257  }
258  inline void put(BitTemp field, bool value) {
259    bit_temps[field - BIT_TEMPS_BEGIN] = value;
260  }
261
262  // Const ref getters.
263  inline int64 ref(MetahandleField field) const {
264    return int64_fields[field - INT64_FIELDS_BEGIN];
265  }
266  inline int64 ref(Int64Field field) const {
267    return int64_fields[field - INT64_FIELDS_BEGIN];
268  }
269  inline const base::Time& ref(TimeField field) const {
270    return time_fields[field - TIME_FIELDS_BEGIN];
271  }
272  inline const Id& ref(IdField field) const {
273    return id_fields[field - ID_FIELDS_BEGIN];
274  }
275  inline int64 ref(BaseVersion field) const {
276    return int64_fields[field - INT64_FIELDS_BEGIN];
277  }
278  inline bool ref(IndexedBitField field) const {
279    return bit_fields[field - BIT_FIELDS_BEGIN];
280  }
281  inline bool ref(IsDelField field) const {
282    return bit_fields[field - BIT_FIELDS_BEGIN];
283  }
284  inline bool ref(BitField field) const {
285    return bit_fields[field - BIT_FIELDS_BEGIN];
286  }
287  inline const std::string& ref(StringField field) const {
288    return string_fields[field - STRING_FIELDS_BEGIN];
289  }
290  inline const sync_pb::EntitySpecifics& ref(ProtoField field) const {
291    return specifics_fields[field - PROTO_FIELDS_BEGIN];
292  }
293  inline const NodeOrdinal& ref(OrdinalField field) const {
294    return ordinal_fields[field - ORDINAL_FIELDS_BEGIN];
295  }
296  inline bool ref(BitTemp field) const {
297    return bit_temps[field - BIT_TEMPS_BEGIN];
298  }
299
300  // Non-const, mutable ref getters for object types only.
301  inline std::string& mutable_ref(StringField field) {
302    return string_fields[field - STRING_FIELDS_BEGIN];
303  }
304  inline sync_pb::EntitySpecifics& mutable_ref(ProtoField field) {
305    return specifics_fields[field - PROTO_FIELDS_BEGIN];
306  }
307  inline Id& mutable_ref(IdField field) {
308    return id_fields[field - ID_FIELDS_BEGIN];
309  }
310  inline NodeOrdinal& mutable_ref(OrdinalField field) {
311    return ordinal_fields[field - ORDINAL_FIELDS_BEGIN];
312  }
313
314  ModelType GetServerModelType() 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
328class 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
336typedef std::set<const EntryKernel*, EntryKernelLessByMetaHandle>
337    EntryKernelSet;
338
339struct EntryKernelMutation {
340  EntryKernel original, mutated;
341};
342
343typedef std::map<int64, EntryKernelMutation> EntryKernelMutationMap;
344
345typedef Immutable<EntryKernelMutationMap> ImmutableEntryKernelMutationMap;
346
347// Caller owns the return value.
348base::DictionaryValue* EntryKernelMutationToValue(
349    const EntryKernelMutation& mutation);
350
351// Caller owns the return value.
352base::ListValue* EntryKernelMutationMapToValue(
353    const EntryKernelMutationMap& mutations);
354
355}  // namespace syncable
356}  // namespace syncer
357
358#endif // SYNC_SYNCABLE_ENTRY_KERNEL_H_
359