1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426
|
// Copyright 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef COMPONENTS_SYNC_SYNCABLE_ENTRY_KERNEL_H_
#define COMPONENTS_SYNC_SYNCABLE_ENTRY_KERNEL_H_
#include <stdint.h>
#include <algorithm>
#include <map>
#include <memory>
#include <set>
#include <string>
#include "base/time/time.h"
#include "base/values.h"
#include "components/sync/base/immutable.h"
#include "components/sync/base/model_type.h"
#include "components/sync/base/proto_value_ptr.h"
#include "components/sync/base/time.h"
#include "components/sync/base/unique_position.h"
#include "components/sync/protocol/attachments.pb.h"
#include "components/sync/protocol/sync.pb.h"
#include "components/sync/syncable/metahandle_set.h"
#include "components/sync/syncable/syncable_id.h"
namespace syncer {
class Cryptographer;
namespace syncable {
// Things you need to update if you change any of the fields below:
// - EntryKernel struct in this file
// - syncable_columns.h
// - syncable_enum_conversions{.h,.cc,_unittest.cc}
// - EntryKernel::EntryKernel(), EntryKernel::ToValue() in entry_kernel.cc
// - operator<< in Entry.cc
// - BindFields() and UnpackEntry() in directory_backing_store.cc
// - kCurrentDBVersion, DirectoryBackingStore::InitializeTables in
// directory_backing_store.cc
// - TestSimpleFieldsPreservedDuringSaveChanges in syncable_unittest.cc
static const int64_t kInvalidMetaHandle = 0;
enum { BEGIN_FIELDS = 0, INT64_FIELDS_BEGIN = BEGIN_FIELDS };
enum MetahandleField {
// Primary key into the table. Keep this as a handle to the meta entry
// across transactions.
META_HANDLE = INT64_FIELDS_BEGIN
};
enum BaseVersion {
// After initial upload, the version is controlled by the server, and is
// increased whenever the data or metadata changes on the server.
BASE_VERSION = META_HANDLE + 1,
};
enum Int64Field {
SERVER_VERSION = BASE_VERSION + 1,
LOCAL_EXTERNAL_ID, // ID of an item in the external local storage that this
// entry is associated with. (such as bookmarks.js)
TRANSACTION_VERSION,
INT64_FIELDS_END
};
enum {
INT64_FIELDS_COUNT = INT64_FIELDS_END - INT64_FIELDS_BEGIN,
TIME_FIELDS_BEGIN = INT64_FIELDS_END,
};
enum TimeField {
MTIME = TIME_FIELDS_BEGIN,
SERVER_MTIME,
CTIME,
SERVER_CTIME,
TIME_FIELDS_END,
};
enum {
TIME_FIELDS_COUNT = TIME_FIELDS_END - TIME_FIELDS_BEGIN,
ID_FIELDS_BEGIN = TIME_FIELDS_END,
};
enum IdField {
// Code in InitializeTables relies on ID being the first IdField value.
ID = ID_FIELDS_BEGIN,
PARENT_ID,
SERVER_PARENT_ID,
ID_FIELDS_END
};
enum {
ID_FIELDS_COUNT = ID_FIELDS_END - ID_FIELDS_BEGIN,
BIT_FIELDS_BEGIN = ID_FIELDS_END
};
enum IndexedBitField {
IS_UNSYNCED = BIT_FIELDS_BEGIN,
IS_UNAPPLIED_UPDATE,
INDEXED_BIT_FIELDS_END,
};
enum IsDelField {
IS_DEL = INDEXED_BIT_FIELDS_END,
};
enum BitField {
IS_DIR = IS_DEL + 1,
SERVER_IS_DIR,
SERVER_IS_DEL,
BIT_FIELDS_END
};
enum {
BIT_FIELDS_COUNT = BIT_FIELDS_END - BIT_FIELDS_BEGIN,
STRING_FIELDS_BEGIN = BIT_FIELDS_END
};
enum StringField {
// Name, will be truncated by server. Can be duplicated in a folder.
NON_UNIQUE_NAME = STRING_FIELDS_BEGIN,
// The server version of |NON_UNIQUE_NAME|.
SERVER_NON_UNIQUE_NAME,
// A tag string which identifies this node as a particular top-level
// permanent object. The tag can be thought of as a unique key that
// identifies a singleton instance.
UNIQUE_SERVER_TAG, // Tagged by the server
UNIQUE_CLIENT_TAG, // Tagged by the client
UNIQUE_BOOKMARK_TAG, // Client tags for bookmark items
STRING_FIELDS_END,
};
enum {
STRING_FIELDS_COUNT = STRING_FIELDS_END - STRING_FIELDS_BEGIN,
PROTO_FIELDS_BEGIN = STRING_FIELDS_END
};
// From looking at the sqlite3 docs, it's not directly stated, but it
// seems the overhead for storing a null blob is very small.
enum ProtoField {
SPECIFICS = PROTO_FIELDS_BEGIN,
SERVER_SPECIFICS,
BASE_SERVER_SPECIFICS,
PROTO_FIELDS_END,
};
enum {
PROTO_FIELDS_COUNT = PROTO_FIELDS_END - PROTO_FIELDS_BEGIN,
UNIQUE_POSITION_FIELDS_BEGIN = PROTO_FIELDS_END
};
enum UniquePositionField {
SERVER_UNIQUE_POSITION = UNIQUE_POSITION_FIELDS_BEGIN,
UNIQUE_POSITION,
UNIQUE_POSITION_FIELDS_END
};
enum {
UNIQUE_POSITION_FIELDS_COUNT =
UNIQUE_POSITION_FIELDS_END - UNIQUE_POSITION_FIELDS_BEGIN,
ATTACHMENT_METADATA_FIELDS_BEGIN = UNIQUE_POSITION_FIELDS_END
};
enum AttachmentMetadataField {
ATTACHMENT_METADATA = ATTACHMENT_METADATA_FIELDS_BEGIN,
SERVER_ATTACHMENT_METADATA,
ATTACHMENT_METADATA_FIELDS_END
};
enum {
ATTACHMENT_METADATA_FIELDS_COUNT =
ATTACHMENT_METADATA_FIELDS_END - ATTACHMENT_METADATA_FIELDS_BEGIN,
FIELD_COUNT = ATTACHMENT_METADATA_FIELDS_END - BEGIN_FIELDS,
// Past this point we have temporaries, stored in memory only.
BEGIN_TEMPS = ATTACHMENT_METADATA_FIELDS_END,
BIT_TEMPS_BEGIN = BEGIN_TEMPS,
};
enum BitTemp {
// Whether a server commit operation was started and has not yet completed
// for this entity.
SYNCING = BIT_TEMPS_BEGIN,
// Whether a local change was made to an entity that had SYNCING set to true,
// and was therefore in the middle of a commit operation.
// Note: must only be set if SYNCING is true.
DIRTY_SYNC,
BIT_TEMPS_END,
};
enum { BIT_TEMPS_COUNT = BIT_TEMPS_END - BIT_TEMPS_BEGIN };
struct EntryKernel {
private:
typedef ProtoValuePtr<sync_pb::EntitySpecifics> EntitySpecificsPtr;
typedef ProtoValuePtr<sync_pb::AttachmentMetadata> AttachmentMetadataPtr;
std::string string_fields[STRING_FIELDS_COUNT];
EntitySpecificsPtr specifics_fields[PROTO_FIELDS_COUNT];
int64_t int64_fields[INT64_FIELDS_COUNT];
base::Time time_fields[TIME_FIELDS_COUNT];
Id id_fields[ID_FIELDS_COUNT];
UniquePosition unique_position_fields[UNIQUE_POSITION_FIELDS_COUNT];
AttachmentMetadataPtr
attachment_metadata_fields[ATTACHMENT_METADATA_FIELDS_COUNT];
std::bitset<BIT_FIELDS_COUNT> bit_fields;
std::bitset<BIT_TEMPS_COUNT> bit_temps;
friend std::ostream& operator<<(std::ostream& s, const EntryKernel& e);
public:
EntryKernel();
EntryKernel(const EntryKernel& other);
~EntryKernel();
// Set the dirty bit, and optionally add this entry's metahandle to
// a provided index on dirty bits in |dirty_index|. Parameter may be null,
// and will result only in setting the dirty bit of this entry.
inline void mark_dirty(syncable::MetahandleSet* dirty_index) {
if (!dirty_ && dirty_index) {
DCHECK_NE(0, ref(META_HANDLE));
dirty_index->insert(ref(META_HANDLE));
}
dirty_ = true;
memory_usage_ = kMemoryUsageUnknown;
}
// Clear the dirty bit, and optionally remove this entry's metahandle from
// a provided index on dirty bits in |dirty_index|. Parameter may be null,
// and will result only in clearing dirty bit of this entry.
inline void clear_dirty(syncable::MetahandleSet* dirty_index) {
if (dirty_ && dirty_index) {
DCHECK_NE(0, ref(META_HANDLE));
dirty_index->erase(ref(META_HANDLE));
}
dirty_ = false;
}
inline bool is_dirty() const { return dirty_; }
// Setters.
inline void put(MetahandleField field, int64_t value) {
int64_fields[field - INT64_FIELDS_BEGIN] = value;
}
inline void put(Int64Field field, int64_t value) {
int64_fields[field - INT64_FIELDS_BEGIN] = value;
}
inline void put(TimeField field, const base::Time& value) {
// Round-trip to proto time format and back so that we have
// consistent time resolutions (ms).
time_fields[field - TIME_FIELDS_BEGIN] =
ProtoTimeToTime(TimeToProtoTime(value));
}
inline void put(IdField field, const Id& value) {
id_fields[field - ID_FIELDS_BEGIN] = value;
}
inline void put(BaseVersion field, int64_t value) {
int64_fields[field - INT64_FIELDS_BEGIN] = value;
}
inline void put(IndexedBitField field, bool value) {
bit_fields[field - BIT_FIELDS_BEGIN] = value;
}
inline void put(IsDelField field, bool value) {
bit_fields[field - BIT_FIELDS_BEGIN] = value;
}
inline void put(BitField field, bool value) {
bit_fields[field - BIT_FIELDS_BEGIN] = value;
}
inline void put(StringField field, const std::string& value) {
string_fields[field - STRING_FIELDS_BEGIN] = value;
}
inline void put(ProtoField field, const sync_pb::EntitySpecifics& value) {
specifics_fields[field - PROTO_FIELDS_BEGIN].set_value(value);
}
inline void put(UniquePositionField field, const UniquePosition& value) {
unique_position_fields[field - UNIQUE_POSITION_FIELDS_BEGIN] = value;
}
inline void put(AttachmentMetadataField field,
const sync_pb::AttachmentMetadata& value) {
attachment_metadata_fields[field - ATTACHMENT_METADATA_FIELDS_BEGIN]
.set_value(value);
}
inline void put(BitTemp field, bool value) {
bit_temps[field - BIT_TEMPS_BEGIN] = value;
}
// Const ref getters.
inline int64_t ref(MetahandleField field) const {
return int64_fields[field - INT64_FIELDS_BEGIN];
}
inline int64_t ref(Int64Field field) const {
return int64_fields[field - INT64_FIELDS_BEGIN];
}
inline const base::Time& ref(TimeField field) const {
return time_fields[field - TIME_FIELDS_BEGIN];
}
inline const Id& ref(IdField field) const {
return id_fields[field - ID_FIELDS_BEGIN];
}
inline int64_t ref(BaseVersion field) const {
return int64_fields[field - INT64_FIELDS_BEGIN];
}
inline bool ref(IndexedBitField field) const {
return bit_fields[field - BIT_FIELDS_BEGIN];
}
inline bool ref(IsDelField field) const {
return bit_fields[field - BIT_FIELDS_BEGIN];
}
inline bool ref(BitField field) const {
return bit_fields[field - BIT_FIELDS_BEGIN];
}
inline const std::string& ref(StringField field) const {
return string_fields[field - STRING_FIELDS_BEGIN];
}
inline const sync_pb::EntitySpecifics& ref(ProtoField field) const {
return specifics_fields[field - PROTO_FIELDS_BEGIN].value();
}
inline const UniquePosition& ref(UniquePositionField field) const {
return unique_position_fields[field - UNIQUE_POSITION_FIELDS_BEGIN];
}
inline const sync_pb::AttachmentMetadata& ref(
AttachmentMetadataField field) const {
return attachment_metadata_fields[field - ATTACHMENT_METADATA_FIELDS_BEGIN]
.value();
}
inline bool ref(BitTemp field) const {
return bit_temps[field - BIT_TEMPS_BEGIN];
}
// Non-const, mutable ref getters for object types only.
inline std::string& mutable_ref(StringField field) {
return string_fields[field - STRING_FIELDS_BEGIN];
}
inline Id& mutable_ref(IdField field) {
return id_fields[field - ID_FIELDS_BEGIN];
}
inline UniquePosition& mutable_ref(UniquePositionField field) {
return unique_position_fields[field - UNIQUE_POSITION_FIELDS_BEGIN];
}
// Deserialization methods for ::google::protobuf::MessageLite derived types.
inline void load(ProtoField field, const void* blob, int length) {
specifics_fields[field - PROTO_FIELDS_BEGIN].load(blob, length);
}
inline void load(AttachmentMetadataField field,
const void* blob,
int length) {
attachment_metadata_fields[field - ATTACHMENT_METADATA_FIELDS_BEGIN].load(
blob, length);
}
// Sharing data methods for ::google::protobuf::MessageLite derived types.
inline void copy(ProtoField src, ProtoField dest) {
DCHECK_NE(src, dest);
specifics_fields[dest - PROTO_FIELDS_BEGIN] =
specifics_fields[src - PROTO_FIELDS_BEGIN];
}
inline void copy(AttachmentMetadataField src, AttachmentMetadataField dest) {
DCHECK_NE(src, dest);
attachment_metadata_fields[dest - ATTACHMENT_METADATA_FIELDS_BEGIN] =
attachment_metadata_fields[src - ATTACHMENT_METADATA_FIELDS_BEGIN];
}
ModelType GetModelType() const;
ModelType GetServerModelType() const;
bool ShouldMaintainPosition() const;
bool ShouldMaintainHierarchy() const;
// Dumps all kernel info into a DictionaryValue and returns it.
// Transfers ownership of the DictionaryValue to the caller.
// Note: |cryptographer| is an optional parameter for use in decrypting
// encrypted specifics. If it is null or the specifics are not decryptsble,
// they will be serialized as empty proto's.
base::DictionaryValue* ToValue(Cryptographer* cryptographer) const;
size_t EstimateMemoryUsage() const;
private:
// Tracks whether this entry needs to be saved to the database.
bool dirty_;
mutable size_t memory_usage_;
constexpr static size_t kMemoryUsageUnknown = size_t(-1);
};
template <typename T>
class EntryKernelLessByMetaHandle {
public:
inline bool operator()(T a, T b) const {
return a->ref(META_HANDLE) < b->ref(META_HANDLE);
}
};
typedef std::set<const EntryKernel*,
EntryKernelLessByMetaHandle<const EntryKernel*>>
EntryKernelSet;
typedef std::set<
std::unique_ptr<EntryKernel>,
EntryKernelLessByMetaHandle<const std::unique_ptr<EntryKernel>&>>
OwnedEntryKernelSet;
struct EntryKernelMutation {
EntryKernel original, mutated;
};
typedef std::map<int64_t, EntryKernelMutation> EntryKernelMutationMap;
typedef Immutable<EntryKernelMutationMap> ImmutableEntryKernelMutationMap;
std::unique_ptr<base::DictionaryValue> EntryKernelMutationToValue(
const EntryKernelMutation& mutation);
std::unique_ptr<base::ListValue> EntryKernelMutationMapToValue(
const EntryKernelMutationMap& mutations);
std::ostream& operator<<(std::ostream& os, const EntryKernel& entry_kernel);
} // namespace syncable
} // namespace syncer
#endif // COMPONENTS_SYNC_SYNCABLE_ENTRY_KERNEL_H_
|