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
22namespace syncer {
23
24class Cryptographer;
25
26namespace 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
39static const int64 kInvalidMetaHandle = 0;
40
41enum {
42  BEGIN_FIELDS = 0,
43  INT64_FIELDS_BEGIN = BEGIN_FIELDS
44};
45
46enum 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
52enum 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
58enum 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
66enum {
67  INT64_FIELDS_COUNT = INT64_FIELDS_END - INT64_FIELDS_BEGIN,
68  TIME_FIELDS_BEGIN = INT64_FIELDS_END,
69};
70
71enum TimeField {
72  MTIME = TIME_FIELDS_BEGIN,
73  SERVER_MTIME,
74  CTIME,
75  SERVER_CTIME,
76  TIME_FIELDS_END,
77};
78
79enum {
80  TIME_FIELDS_COUNT = TIME_FIELDS_END - TIME_FIELDS_BEGIN,
81  ID_FIELDS_BEGIN = TIME_FIELDS_END,
82};
83
84enum 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
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  UNIQUE_BOOKMARK_TAG,  // Client tags for bookmark items
131  STRING_FIELDS_END,
132};
133
134enum {
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.
141enum ProtoField {
142  SPECIFICS = PROTO_FIELDS_BEGIN,
143  SERVER_SPECIFICS,
144  BASE_SERVER_SPECIFICS,
145  PROTO_FIELDS_END,
146};
147
148enum {
149  PROTO_FIELDS_COUNT = PROTO_FIELDS_END - PROTO_FIELDS_BEGIN,
150  UNIQUE_POSITION_FIELDS_BEGIN = PROTO_FIELDS_END
151};
152
153enum UniquePositionField {
154  SERVER_UNIQUE_POSITION = UNIQUE_POSITION_FIELDS_BEGIN,
155  UNIQUE_POSITION,
156  UNIQUE_POSITION_FIELDS_END
157};
158
159enum {
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
165enum AttachmentMetadataField {
166  ATTACHMENT_METADATA = ATTACHMENT_METADATA_FIELDS_BEGIN,
167  ATTACHMENT_METADATA_FIELDS_END
168};
169
170enum {
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
179enum 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
186enum {
187  BIT_TEMPS_COUNT = BIT_TEMPS_END - BIT_TEMPS_BEGIN
188};
189
190
191
192struct 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.
212  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.
223  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
231  inline bool is_dirty() const {
232    return dirty_;
233  }
234
235  // Setters.
236  inline void put(MetahandleField field, int64 value) {
237    int64_fields[field - INT64_FIELDS_BEGIN] = value;
238  }
239  inline void put(Int64Field field, int64 value) {
240    int64_fields[field - INT64_FIELDS_BEGIN] = value;
241  }
242  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  }
248  inline void put(IdField field, const Id& value) {
249    id_fields[field - ID_FIELDS_BEGIN] = value;
250  }
251  inline void put(BaseVersion field, int64 value) {
252    int64_fields[field - INT64_FIELDS_BEGIN] = value;
253  }
254  inline void put(IndexedBitField field, bool value) {
255    bit_fields[field - BIT_FIELDS_BEGIN] = value;
256  }
257  inline void put(IsDelField field, bool value) {
258    bit_fields[field - BIT_FIELDS_BEGIN] = value;
259  }
260  inline void put(BitField field, bool value) {
261    bit_fields[field - BIT_FIELDS_BEGIN] = value;
262  }
263  inline void put(StringField field, const std::string& value) {
264    string_fields[field - STRING_FIELDS_BEGIN] = value;
265  }
266  inline void put(ProtoField field, const sync_pb::EntitySpecifics& value) {
267    specifics_fields[field - PROTO_FIELDS_BEGIN].CopyFrom(value);
268  }
269  inline void put(UniquePositionField field, const UniquePosition& value) {
270    unique_position_fields[field - UNIQUE_POSITION_FIELDS_BEGIN] = value;
271  }
272  inline void put(AttachmentMetadataField field,
273                  const sync_pb::AttachmentMetadata& value) {
274    attachment_metadata_fields[field - ATTACHMENT_METADATA_FIELDS_BEGIN] =
275        value;
276  }
277  inline void put(BitTemp field, bool value) {
278    bit_temps[field - BIT_TEMPS_BEGIN] = value;
279  }
280
281  // Const ref getters.
282  inline int64 ref(MetahandleField field) const {
283    return int64_fields[field - INT64_FIELDS_BEGIN];
284  }
285  inline int64 ref(Int64Field field) const {
286    return int64_fields[field - INT64_FIELDS_BEGIN];
287  }
288  inline const base::Time& ref(TimeField field) const {
289    return time_fields[field - TIME_FIELDS_BEGIN];
290  }
291  inline const Id& ref(IdField field) const {
292    return id_fields[field - ID_FIELDS_BEGIN];
293  }
294  inline int64 ref(BaseVersion field) const {
295    return int64_fields[field - INT64_FIELDS_BEGIN];
296  }
297  inline bool ref(IndexedBitField field) const {
298    return bit_fields[field - BIT_FIELDS_BEGIN];
299  }
300  inline bool ref(IsDelField field) const {
301    return bit_fields[field - BIT_FIELDS_BEGIN];
302  }
303  inline bool ref(BitField field) const {
304    return bit_fields[field - BIT_FIELDS_BEGIN];
305  }
306  inline const std::string& ref(StringField field) const {
307    return string_fields[field - STRING_FIELDS_BEGIN];
308  }
309  inline const sync_pb::EntitySpecifics& ref(ProtoField field) const {
310    return specifics_fields[field - PROTO_FIELDS_BEGIN];
311  }
312  inline const UniquePosition& ref(UniquePositionField field) const {
313    return unique_position_fields[field - UNIQUE_POSITION_FIELDS_BEGIN];
314  }
315  inline const sync_pb::AttachmentMetadata& ref(
316      AttachmentMetadataField field) const {
317    return attachment_metadata_fields[field - ATTACHMENT_METADATA_FIELDS_BEGIN];
318  }
319  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.
324  inline std::string& mutable_ref(StringField field) {
325    return string_fields[field - STRING_FIELDS_BEGIN];
326  }
327  inline sync_pb::EntitySpecifics& mutable_ref(ProtoField field) {
328    return specifics_fields[field - PROTO_FIELDS_BEGIN];
329  }
330  inline Id& mutable_ref(IdField field) {
331    return id_fields[field - ID_FIELDS_BEGIN];
332  }
333  inline UniquePosition& mutable_ref(UniquePositionField field) {
334    return unique_position_fields[field - UNIQUE_POSITION_FIELDS_BEGIN];
335  }
336  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
357class EntryKernelLessByMetaHandle {
358 public:
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
365typedef std::set<const EntryKernel*, EntryKernelLessByMetaHandle>
366    EntryKernelSet;
367
368struct EntryKernelMutation {
369  EntryKernel original, mutated;
370};
371
372typedef std::map<int64, EntryKernelMutation> EntryKernelMutationMap;
373
374typedef Immutable<EntryKernelMutationMap> ImmutableEntryKernelMutationMap;
375
376// Caller owns the return value.
377base::DictionaryValue* EntryKernelMutationToValue(
378    const EntryKernelMutation& mutation);
379
380// Caller owns the return value.
381base::ListValue* EntryKernelMutationMapToValue(
382    const EntryKernelMutationMap& mutations);
383
384}  // namespace syncable
385}  // namespace syncer
386
387#endif // SYNC_SYNCABLE_ENTRY_KERNEL_H_
388