1ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// Copyright (c) 2011 The Chromium Authors. All rights reserved. 2c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Use of this source code is governed by a BSD-style license that can be 3c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// found in the LICENSE file. 4c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 5c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#ifndef CHROME_BROWSER_SYNC_SYNCABLE_SYNCABLE_H_ 6c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#define CHROME_BROWSER_SYNC_SYNCABLE_SYNCABLE_H_ 73345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#pragma once 8c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 9c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include <algorithm> 10c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include <bitset> 11c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include <iosfwd> 12c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include <limits> 13c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include <set> 14c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include <string> 15c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include <vector> 16c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 17c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/atomicops.h" 18c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/basictypes.h" 19c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/file_path.h" 20c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/gtest_prod_util.h" 2172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "base/synchronization/lock.h" 22c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/time.h" 23c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/sync/protocol/sync.pb.h" 2421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen#include "chrome/browser/sync/syncable/autofill_migration.h" 25c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/sync/syncable/blob.h" 26c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/sync/syncable/dir_open_result.h" 27c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/sync/syncable/directory_event.h" 28c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/sync/syncable/syncable_id.h" 29c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/sync/syncable/model_type.h" 30c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/sync/util/dbgq.h" 31c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/common/deprecated/event_sys.h" 32c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 33ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenclass DictionaryValue; 34c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstruct PurgeInfo; 35c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 36c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochnamespace sync_api { 37c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochclass ReadTransaction; 38c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochclass WriteNode; 39c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochclass ReadNode; 40c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 41c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 42c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochnamespace syncable { 43ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenclass DirectoryChangeListener; 44c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochclass Entry; 45c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 463345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickstd::ostream& operator<<(std::ostream& s, const Entry& e); 47c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 48c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochclass DirectoryBackingStore; 49c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 50c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstatic const int64 kInvalidMetaHandle = 0; 51c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 52ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// Update syncable_enum_conversions{.h,.cc,_unittest.cc} if you change 53ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// any fields in this file. 54ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 55c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochenum { 56c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch BEGIN_FIELDS = 0, 57c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch INT64_FIELDS_BEGIN = BEGIN_FIELDS 58c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}; 59c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 60c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochenum MetahandleField { 61c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Primary key into the table. Keep this as a handle to the meta entry 62c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // across transactions. 63c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch META_HANDLE = INT64_FIELDS_BEGIN 64c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}; 65c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 66c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochenum BaseVersion { 67c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // After initial upload, the version is controlled by the server, and is 68c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // increased whenever the data or metadata changes on the server. 69c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch BASE_VERSION = META_HANDLE + 1, 70c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}; 71c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 72c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochenum Int64Field { 73c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SERVER_VERSION = BASE_VERSION + 1, 74c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch MTIME, 75c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SERVER_MTIME, 76c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch CTIME, 77c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SERVER_CTIME, 78c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 79c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // A numeric position value that indicates the relative ordering of 80c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // this object among its siblings. 81c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SERVER_POSITION_IN_PARENT, 82c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 83c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch LOCAL_EXTERNAL_ID, // ID of an item in the external local storage that this 84c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // entry is associated with. (such as bookmarks.js) 85c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 86c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch INT64_FIELDS_END 87c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}; 88c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 89c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochenum { 90c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch INT64_FIELDS_COUNT = INT64_FIELDS_END, 91c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ID_FIELDS_BEGIN = INT64_FIELDS_END, 92c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}; 93c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 94c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochenum IdField { 95c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Code in InitializeTables relies on ID being the first IdField value. 96c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ID = ID_FIELDS_BEGIN, 97c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch PARENT_ID, 98c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SERVER_PARENT_ID, 99c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 100c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch PREV_ID, 101c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch NEXT_ID, 102c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ID_FIELDS_END 103c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}; 104c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 105c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochenum { 106c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ID_FIELDS_COUNT = ID_FIELDS_END - ID_FIELDS_BEGIN, 107c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch BIT_FIELDS_BEGIN = ID_FIELDS_END 108c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}; 109c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 110c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochenum IndexedBitField { 111c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch IS_UNSYNCED = BIT_FIELDS_BEGIN, 112c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch IS_UNAPPLIED_UPDATE, 113c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch INDEXED_BIT_FIELDS_END, 114c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}; 115c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 116c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochenum IsDelField { 117c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch IS_DEL = INDEXED_BIT_FIELDS_END, 118c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}; 119c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 120c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochenum BitField { 121c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch IS_DIR = IS_DEL + 1, 122c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SERVER_IS_DIR, 123c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SERVER_IS_DEL, 124c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch BIT_FIELDS_END 125c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}; 126c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 127c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochenum { 128c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch BIT_FIELDS_COUNT = BIT_FIELDS_END - BIT_FIELDS_BEGIN, 129c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch STRING_FIELDS_BEGIN = BIT_FIELDS_END 130c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}; 131c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 132c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochenum StringField { 133c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Name, will be truncated by server. Can be duplicated in a folder. 134c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch NON_UNIQUE_NAME = STRING_FIELDS_BEGIN, 135c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // The server version of |NON_UNIQUE_NAME|. 136c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SERVER_NON_UNIQUE_NAME, 137c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 138c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // A tag string which identifies this node as a particular top-level 139c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // permanent object. The tag can be thought of as a unique key that 140c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // identifies a singleton instance. 141c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch UNIQUE_SERVER_TAG, // Tagged by the server 142c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch UNIQUE_CLIENT_TAG, // Tagged by the client 143c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch STRING_FIELDS_END, 144c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}; 145c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 146c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochenum { 147c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch STRING_FIELDS_COUNT = STRING_FIELDS_END - STRING_FIELDS_BEGIN, 148c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch PROTO_FIELDS_BEGIN = STRING_FIELDS_END 149c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}; 150c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 151c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// From looking at the sqlite3 docs, it's not directly stated, but it 152c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// seems the overhead for storing a NULL blob is very small. 153c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochenum ProtoField { 154c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SPECIFICS = PROTO_FIELDS_BEGIN, 155c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SERVER_SPECIFICS, 156c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch PROTO_FIELDS_END, 157c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}; 158c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 159c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochenum { 160c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch PROTO_FIELDS_COUNT = PROTO_FIELDS_END - PROTO_FIELDS_BEGIN 161c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}; 162c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 163c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochenum { 164c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch FIELD_COUNT = PROTO_FIELDS_END, 165c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Past this point we have temporaries, stored in memory only. 166c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch BEGIN_TEMPS = PROTO_FIELDS_END, 167c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch BIT_TEMPS_BEGIN = BEGIN_TEMPS, 168c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}; 169c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 170c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochenum BitTemp { 171c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SYNCING = BIT_TEMPS_BEGIN, 172c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch BIT_TEMPS_END, 173c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}; 174c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 175c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochenum { 176c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch BIT_TEMPS_COUNT = BIT_TEMPS_END - BIT_TEMPS_BEGIN 177c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}; 178c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 179c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochclass BaseTransaction; 180c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochclass WriteTransaction; 181c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochclass ReadTransaction; 182c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochclass Directory; 183c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochclass ScopedDirLookup; 184c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 185c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Instead of: 186c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Entry e = transaction.GetById(id); 187c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// use: 188c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Entry e(transaction, GET_BY_ID, id); 189c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// 190c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Why? The former would require a copy constructor, and it would be difficult 191c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// to enforce that an entry never outlived its transaction if there were a copy 192c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// constructor. 193c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochenum GetById { 194c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch GET_BY_ID 195c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}; 196c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 197c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochenum GetByClientTag { 198c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch GET_BY_CLIENT_TAG 199c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}; 200c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 201c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochenum GetByServerTag { 202c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch GET_BY_SERVER_TAG 203c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}; 204c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 205c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochenum GetByHandle { 206c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch GET_BY_HANDLE 207c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}; 208c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 209c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochenum Create { 210c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch CREATE 211c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}; 212c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 213c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochenum CreateNewUpdateItem { 214c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch CREATE_NEW_UPDATE_ITEM 215c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}; 216c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 217c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochtypedef std::set<int64> MetahandleSet; 218c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 219c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Why the singular enums? So the code compile-time dispatches instead of 220c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// runtime dispatches as it would with a single enum and an if() statement. 221c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 222c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// The EntryKernel class contains the actual data for an entry. 223c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstruct EntryKernel { 224c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch private: 225c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch std::string string_fields[STRING_FIELDS_COUNT]; 226c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch sync_pb::EntitySpecifics specifics_fields[PROTO_FIELDS_COUNT]; 227c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int64 int64_fields[INT64_FIELDS_COUNT]; 228c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch Id id_fields[ID_FIELDS_COUNT]; 229c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch std::bitset<BIT_FIELDS_COUNT> bit_fields; 230c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch std::bitset<BIT_TEMPS_COUNT> bit_temps; 231c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 232c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch public: 233731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick EntryKernel(); 234731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick ~EntryKernel(); 235c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 236c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Set the dirty bit, and optionally add this entry's metahandle to 237c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // a provided index on dirty bits in |dirty_index|. Parameter may be null, 238c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // and will result only in setting the dirty bit of this entry. 239c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch inline void mark_dirty(syncable::MetahandleSet* dirty_index) { 240c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!dirty_ && dirty_index) { 241c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK_NE(0, ref(META_HANDLE)); 242c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch dirty_index->insert(ref(META_HANDLE)); 243c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 244c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch dirty_ = true; 245c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 246c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 247c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Clear the dirty bit, and optionally remove this entry's metahandle from 248c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // a provided index on dirty bits in |dirty_index|. Parameter may be null, 249c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // and will result only in clearing dirty bit of this entry. 250c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch inline void clear_dirty(syncable::MetahandleSet* dirty_index) { 251c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (dirty_ && dirty_index) { 252c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK_NE(0, ref(META_HANDLE)); 253c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch dirty_index->erase(ref(META_HANDLE)); 254c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 255c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch dirty_ = false; 256c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 257c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 258c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch inline bool is_dirty() const { 259c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return dirty_; 260c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 261c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 262c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Setters. 263c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch inline void put(MetahandleField field, int64 value) { 264c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int64_fields[field - INT64_FIELDS_BEGIN] = value; 265c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 266c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch inline void put(Int64Field field, int64 value) { 267c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int64_fields[field - INT64_FIELDS_BEGIN] = value; 268c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 269c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch inline void put(IdField field, const Id& value) { 270c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch id_fields[field - ID_FIELDS_BEGIN] = value; 271c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 272c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch inline void put(BaseVersion field, int64 value) { 273c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int64_fields[field - INT64_FIELDS_BEGIN] = value; 274c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 275c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch inline void put(IndexedBitField field, bool value) { 276c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch bit_fields[field - BIT_FIELDS_BEGIN] = value; 277c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 278c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch inline void put(IsDelField field, bool value) { 279c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch bit_fields[field - BIT_FIELDS_BEGIN] = value; 280c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 281c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch inline void put(BitField field, bool value) { 282c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch bit_fields[field - BIT_FIELDS_BEGIN] = value; 283c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 284c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch inline void put(StringField field, const std::string& value) { 285c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch string_fields[field - STRING_FIELDS_BEGIN] = value; 286c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 287c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch inline void put(ProtoField field, const sync_pb::EntitySpecifics& value) { 288c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch specifics_fields[field - PROTO_FIELDS_BEGIN].CopyFrom(value); 289c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 290c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch inline void put(BitTemp field, bool value) { 291c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch bit_temps[field - BIT_TEMPS_BEGIN] = value; 292c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 293c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 294c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Const ref getters. 295c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch inline int64 ref(MetahandleField field) const { 296c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return int64_fields[field - INT64_FIELDS_BEGIN]; 297c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 298c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch inline int64 ref(Int64Field field) const { 299c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return int64_fields[field - INT64_FIELDS_BEGIN]; 300c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 301c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch inline const Id& ref(IdField field) const { 302c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return id_fields[field - ID_FIELDS_BEGIN]; 303c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 304c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch inline int64 ref(BaseVersion field) const { 305c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return int64_fields[field - INT64_FIELDS_BEGIN]; 306c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 307c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch inline bool ref(IndexedBitField field) const { 308c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return bit_fields[field - BIT_FIELDS_BEGIN]; 309c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 310c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch inline bool ref(IsDelField field) const { 311c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return bit_fields[field - BIT_FIELDS_BEGIN]; 312c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 313c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch inline bool ref(BitField field) const { 314c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return bit_fields[field - BIT_FIELDS_BEGIN]; 315c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 316c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch inline const std::string& ref(StringField field) const { 317c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return string_fields[field - STRING_FIELDS_BEGIN]; 318c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 319c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch inline const sync_pb::EntitySpecifics& ref(ProtoField field) const { 320c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return specifics_fields[field - PROTO_FIELDS_BEGIN]; 321c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 322c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch inline bool ref(BitTemp field) const { 323c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return bit_temps[field - BIT_TEMPS_BEGIN]; 324c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 325c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 326c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Non-const, mutable ref getters for object types only. 327c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch inline std::string& mutable_ref(StringField field) { 328c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return string_fields[field - STRING_FIELDS_BEGIN]; 329c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 330c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch inline sync_pb::EntitySpecifics& mutable_ref(ProtoField field) { 331c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return specifics_fields[field - PROTO_FIELDS_BEGIN]; 332c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 333c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch inline Id& mutable_ref(IdField field) { 334c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return id_fields[field - ID_FIELDS_BEGIN]; 335c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 336c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 337ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // Dumps all kernel info into a DictionaryValue and returns it. 338ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // Transfers ownership of the DictionaryValue to the caller. 339ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen DictionaryValue* ToValue() const; 340ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 341c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch private: 342c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Tracks whether this entry needs to be saved to the database. 343c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch bool dirty_; 344c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}; 345c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 346c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// A read-only meta entry. 347c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochclass Entry { 348c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch friend class Directory; 3493345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick friend std::ostream& operator << (std::ostream& s, const Entry& e); 350c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 351c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch public: 352c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // After constructing, you must check good() to test whether the Get 353c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // succeeded. 354c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch Entry(BaseTransaction* trans, GetByHandle, int64 handle); 355c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch Entry(BaseTransaction* trans, GetById, const Id& id); 356c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch Entry(BaseTransaction* trans, GetByServerTag, const std::string& tag); 357c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch Entry(BaseTransaction* trans, GetByClientTag, const std::string& tag); 358c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 359c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch bool good() const { return 0 != kernel_; } 360c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 361c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch BaseTransaction* trans() const { return basetrans_; } 362c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 363c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Field accessors. 364c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch inline int64 Get(MetahandleField field) const { 365c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK(kernel_); 366c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return kernel_->ref(field); 367c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 368c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch inline Id Get(IdField field) const { 369c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK(kernel_); 370c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return kernel_->ref(field); 371c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 372c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch inline int64 Get(Int64Field field) const { 373c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK(kernel_); 374c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return kernel_->ref(field); 375c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 376c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch inline int64 Get(BaseVersion field) const { 377c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK(kernel_); 378c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return kernel_->ref(field); 379c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 380c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch inline bool Get(IndexedBitField field) const { 381c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK(kernel_); 382c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return kernel_->ref(field); 383c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 384c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch inline bool Get(IsDelField field) const { 385c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK(kernel_); 386c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return kernel_->ref(field); 387c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 388c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch inline bool Get(BitField field) const { 389c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK(kernel_); 390c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return kernel_->ref(field); 391c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 392c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const std::string& Get(StringField field) const; 393c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch inline const sync_pb::EntitySpecifics& Get(ProtoField field) const { 394c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK(kernel_); 395c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return kernel_->ref(field); 396c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 397c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch inline bool Get(BitTemp field) const { 398c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK(kernel_); 399c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return kernel_->ref(field); 400c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 401c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 402c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ModelType GetServerModelType() const; 403c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ModelType GetModelType() const; 404c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 405c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // If this returns false, we shouldn't bother maintaining 406c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // a position value (sibling ordering) for this item. 407c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch bool ShouldMaintainPosition() const { 408c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return GetModelType() == BOOKMARKS; 409c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 410c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 411c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch inline bool ExistsOnClientBecauseNameIsNonEmpty() const { 412c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK(kernel_); 413c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return !kernel_->ref(NON_UNIQUE_NAME).empty(); 414c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 415c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 416c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch inline bool IsRoot() const { 417c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK(kernel_); 418c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return kernel_->ref(ID).IsRoot(); 419c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 420c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 421c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch Directory* dir() const; 422c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 423c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const EntryKernel GetKernelCopy() const { 424c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return *kernel_; 425c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 426c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 427dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen // Compute a local predecessor position for |update_item|, based on its 428dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen // absolute server position. The returned ID will be a valid predecessor 429dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen // under SERVER_PARENT_ID that is consistent with the 430dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen // SERVER_POSITION_IN_PARENT ordering. 431dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen Id ComputePrevIdFromServerPosition(const Id& parent_id) const; 432dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen 433ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // Dumps all entry info into a DictionaryValue and returns it. 434ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // Transfers ownership of the DictionaryValue to the caller. 435ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen DictionaryValue* ToValue() const; 436ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 437c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch protected: // Don't allow creation on heap, except by sync API wrappers. 438c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch friend class sync_api::ReadNode; 439c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch void* operator new(size_t size) { return (::operator new)(size); } 440c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 4413345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick inline Entry(BaseTransaction* trans) 4423345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick : basetrans_(trans), 4433345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick kernel_(NULL) { } 444c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 445c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch protected: 446c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 447c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch BaseTransaction* const basetrans_; 448c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 449c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch EntryKernel* kernel_; 450c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 451ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen private: 452ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // Like GetServerModelType() but without the DCHECKs. 453ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen ModelType GetServerModelTypeHelper() const; 454ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 455c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DISALLOW_COPY_AND_ASSIGN(Entry); 456c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}; 457c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 458c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// A mutable meta entry. Changes get committed to the database when the 459c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// WriteTransaction is destroyed. 460c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochclass MutableEntry : public Entry { 461c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch friend class WriteTransaction; 462c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch friend class Directory; 463c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch void Init(WriteTransaction* trans, const Id& parent_id, 464c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const std::string& name); 465c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch public: 466c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch MutableEntry(WriteTransaction* trans, Create, const Id& parent_id, 467c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const std::string& name); 468c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch MutableEntry(WriteTransaction* trans, CreateNewUpdateItem, const Id& id); 469c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch MutableEntry(WriteTransaction* trans, GetByHandle, int64); 470c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch MutableEntry(WriteTransaction* trans, GetById, const Id&); 471c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch MutableEntry(WriteTransaction* trans, GetByClientTag, const std::string& tag); 472c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch MutableEntry(WriteTransaction* trans, GetByServerTag, const std::string& tag); 473c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 474c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch inline WriteTransaction* write_transaction() const { 475c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return write_transaction_; 476c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 477c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 478c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Field Accessors. Some of them trigger the re-indexing of the entry. 479c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Return true on success, return false on failure, which means 480c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // that putting the value would have caused a duplicate in the index. 481c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // TODO(chron): Remove some of these unecessary return values. 482c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch bool Put(Int64Field field, const int64& value); 483c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch bool Put(IdField field, const Id& value); 484c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 485c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Do a simple property-only update if the PARENT_ID field. Use with caution. 486c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // 487c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // The normal Put(IS_PARENT) call will move the item to the front of the 488c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // sibling order to maintain the linked list invariants when the parent 489c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // changes. That's usually what you want to do, but it's inappropriate 490c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // when the caller is trying to change the parent ID of a the whole set 491c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // of children (e.g. because the ID changed during a commit). For those 492c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // cases, there's this function. It will corrupt the sibling ordering 493c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // if you're not careful. 494c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch void PutParentIdPropertyOnly(const Id& parent_id); 495c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 496c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch bool Put(StringField field, const std::string& value); 497c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch bool Put(BaseVersion field, int64 value); 498c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 499c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch bool Put(ProtoField field, const sync_pb::EntitySpecifics& value); 500ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen bool Put(BitField field, bool value); 501c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch inline bool Put(IsDelField field, bool value) { 502c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return PutIsDel(value); 503c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 504c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch bool Put(IndexedBitField field, bool value); 505c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 506c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Sets the position of this item, and updates the entry kernels of the 507c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // adjacent siblings so that list invariants are maintained. Returns false 508c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // and fails if |predecessor_id| does not identify a sibling. Pass the root 509c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // ID to put the node in first position. 510c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch bool PutPredecessor(const Id& predecessor_id); 511c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 512ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen bool Put(BitTemp field, bool value); 513c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 514c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch protected: 515c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch syncable::MetahandleSet* GetDirtyIndexHelper(); 516c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 517c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch bool PutIsDel(bool value); 518c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 519c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch private: // Don't allow creation on heap, except by sync API wrappers. 520c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch friend class sync_api::WriteNode; 521c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch void* operator new(size_t size) { return (::operator new)(size); } 522c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 523c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch bool PutImpl(StringField field, const std::string& value); 524c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch bool PutUniqueClientTag(const std::string& value); 525c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 526c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Adjusts the successor and predecessor entries so that they no longer 527c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // refer to this entry. 528c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch void UnlinkFromOrder(); 529c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 530c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Kind of redundant. We should reduce the number of pointers 531c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // floating around if at all possible. Could we store this in Directory? 532c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Scope: Set on construction, never changed after that. 533c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch WriteTransaction* const write_transaction_; 534c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 535c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch protected: 536c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch MutableEntry(); 537c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 538c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DISALLOW_COPY_AND_ASSIGN(MutableEntry); 539c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}; 540c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 541c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochclass LessParentIdAndHandle; 542c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochtemplate <typename FieldType, FieldType field_index> 543c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochclass LessField; 544c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochclass LessEntryMetaHandles { 545c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch public: 546c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch inline bool operator()(const syncable::EntryKernel& a, 547c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const syncable::EntryKernel& b) const { 548c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return a.ref(META_HANDLE) < b.ref(META_HANDLE); 549c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 550c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}; 551c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochtypedef std::set<EntryKernel, LessEntryMetaHandles> OriginalEntries; 552c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 553dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen// How syncable indices & Indexers work. 554dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen// 555dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen// The syncable Directory maintains several indices on the Entries it tracks. 556dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen// The indices follow a common pattern: 557dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen// (a) The index allows efficient lookup of an Entry* with particular 558dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen// field values. This is done by use of a std::set<> and a custom 559dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen// comparator. 560dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen// (b) There may be conditions for inclusion in the index -- for example, 561dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen// deleted items might not be indexed. 562dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen// (c) Because the index set contains only Entry*, one must be careful 563dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen// to remove Entries from the set before updating the value of 564dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen// an indexed field. 565dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen// The traits of an index are a Comparator (to define the set ordering) and a 566dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen// ShouldInclude function (to define the conditions for inclusion). For each 567dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen// index, the traits are grouped into a class called an Indexer which 568dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen// can be used as a template type parameter. 569dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen 570dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen// Traits type for metahandle index. 571dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenstruct MetahandleIndexer { 572dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen // This index is of the metahandle field values. 573dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen typedef LessField<MetahandleField, META_HANDLE> Comparator; 574dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen 575dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen // This index includes all entries. 576dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen inline static bool ShouldInclude(const EntryKernel* a) { 577dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen return true; 578dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen } 579dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen}; 580dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen 581dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen// Traits type for ID field index. 582dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenstruct IdIndexer { 583dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen // This index is of the ID field values. 584dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen typedef LessField<IdField, ID> Comparator; 585dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen 586dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen // This index includes all entries. 587dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen inline static bool ShouldInclude(const EntryKernel* a) { 588dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen return true; 589dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen } 590dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen}; 591dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen 592dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen// Traits type for unique client tag index. 593dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenstruct ClientTagIndexer { 594dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen // This index is of the client-tag values. 595dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen typedef LessField<StringField, UNIQUE_CLIENT_TAG> Comparator; 596dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen 597dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen // Items are only in this index if they have a non-empty client tag value. 598dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen static bool ShouldInclude(const EntryKernel* a); 599dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen}; 600dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen 601dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen// This index contains EntryKernels ordered by parent ID and metahandle. 602dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen// It allows efficient lookup of the children of a given parent. 603dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenstruct ParentIdAndHandleIndexer { 604dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen // This index is of the parent ID and metahandle. We use a custom 605dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen // comparator. 606dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen class Comparator { 607dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen public: 608dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen bool operator() (const syncable::EntryKernel* a, 609dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen const syncable::EntryKernel* b) const; 610dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen }; 611dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen 612dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen // This index does not include deleted items. 613dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen static bool ShouldInclude(const EntryKernel* a); 614dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen}; 615dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen 616dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen// Given an Indexer providing the semantics of an index, defines the 617dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen// set type used to actually contain the index. 618dc0f95d653279beabeb9817299e2902918ba123eKristian Monsentemplate <typename Indexer> 619dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenstruct Index { 620dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen typedef std::set<EntryKernel*, typename Indexer::Comparator> Set; 621dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen}; 622dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen 623c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// a WriteTransaction has a writer tag describing which body of code is doing 624c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// the write. This is defined up here since DirectoryChangeEvent also contains 625c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// one. 626c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochenum WriterTag { 627c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch INVALID, 628c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SYNCER, 629c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch AUTHWATCHER, 630c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch UNITTEST, 631c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch VACUUM_AFTER_SAVE, 632c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch PURGE_ENTRIES, 633c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SYNCAPI 634c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}; 635c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 636c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// The name Directory in this case means the entire directory 637c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// structure within a single user account. 638c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// 639c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Sqlite is a little goofy, in that each thread must access a database 640c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// via its own handle. So, a Directory object should only be accessed 641c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// from a single thread. Use DirectoryManager's Open() method to 642c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// always get a directory that has been properly initialized on the 643c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// current thread. 644c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// 645c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// The db is protected against concurrent modification by a reader/ 646c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// writer lock, negotiated by the ReadTransaction and WriteTransaction 647c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// friend classes. The in-memory indices are protected against 648c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// concurrent modification by the kernel lock. 649c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// 650c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// All methods which require the reader/writer lock to be held either 651c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// are protected and only called from friends in a transaction 652c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// or are public and take a Transaction* argument. 653c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// 654c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// All methods which require the kernel lock to be already held take a 655c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// ScopeKernelLock* argument. 656c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// 657c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// To prevent deadlock, the reader writer transaction lock must always 658c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// be held before acquiring the kernel lock. 659c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochclass ScopedKernelLock; 660c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochclass IdFilter; 661c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochclass DirectoryManager; 662c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 663c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochclass Directory { 664c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch friend class BaseTransaction; 665c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch friend class Entry; 666c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch friend class MutableEntry; 667c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch friend class ReadTransaction; 668c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch friend class ReadTransactionWithoutDB; 669c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch friend class ScopedKernelLock; 670c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch friend class ScopedKernelUnlock; 671c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch friend class WriteTransaction; 672c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch friend class SyncableDirectoryTest; 673c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch FRIEND_TEST_ALL_PREFIXES(SyncableDirectoryTest, 674c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch TakeSnapshotGetsAllDirtyHandlesTest); 675c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch FRIEND_TEST_ALL_PREFIXES(SyncableDirectoryTest, 676c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch TakeSnapshotGetsOnlyDirtyHandlesTest); 677c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch FRIEND_TEST_ALL_PREFIXES(SyncableDirectoryTest, TestPurgeEntriesWithTypeIn); 678c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch FRIEND_TEST_ALL_PREFIXES(SyncableDirectoryTest, 679c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch TakeSnapshotGetsMetahandlesToPurge); 680c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 681c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch public: 682c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch class EventListenerHookup; 683c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 684c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Various data that the Directory::Kernel we are backing (persisting data 685c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // for) needs saved across runs of the application. 686c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch struct PersistedKernelInfo { 68721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen AutofillMigrationDebugInfo autofill_migration_debug_info; 68821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 689731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick PersistedKernelInfo(); 690731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick ~PersistedKernelInfo(); 691731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick 69272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // Set the |download_progress| entry for the given model to a 69372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // "first sync" start point. When such a value is sent to the server, 69472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // a full download of all objects of the model will be initiated. 69572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen void reset_download_progress(ModelType model_type); 69672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 697c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Last sync timestamp fetched from the server. 69872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen sync_pb::DataTypeProgressMarker download_progress[MODEL_TYPE_COUNT]; 699c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // true iff we ever reached the end of the changelog. 700c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ModelTypeBitSet initial_sync_ended; 701c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // The store birthday we were given by the server. Contents are opaque to 702c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // the client. 703c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch std::string store_birthday; 704c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // The next local ID that has not been used with this cache-GUID. 705c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int64 next_id; 706731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick // The persisted notification state. 707731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick std::string notification_state; 70821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 70921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen AutofillMigrationState autofill_migration_state; 710c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch }; 711c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 712c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // What the Directory needs on initialization to create itself and its Kernel. 713c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Filled by DirectoryBackingStore::Load. 714c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch struct KernelLoadInfo { 715c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch PersistedKernelInfo kernel_info; 716c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch std::string cache_guid; // Created on first initialization, never changes. 717c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int64 max_metahandle; // Computed (using sql MAX aggregate) on init. 718c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch KernelLoadInfo() : max_metahandle(0) { 719c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 720c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch }; 721c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 722c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // The dirty/clean state of kernel fields backed by the share_info table. 723c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // This is public so it can be used in SaveChangesSnapshot for persistence. 724c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch enum KernelShareInfoStatus { 725c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch KERNEL_SHARE_INFO_INVALID, 726c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch KERNEL_SHARE_INFO_VALID, 727c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch KERNEL_SHARE_INFO_DIRTY 728c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch }; 729c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 730c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // When the Directory is told to SaveChanges, a SaveChangesSnapshot is 731c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // constructed and forms a consistent snapshot of what needs to be sent to 732c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // the backing store. 733c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch struct SaveChangesSnapshot { 734731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick SaveChangesSnapshot(); 735731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick ~SaveChangesSnapshot(); 736731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick 737c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch KernelShareInfoStatus kernel_info_status; 738c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch PersistedKernelInfo kernel_info; 739c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch OriginalEntries dirty_metas; 740c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch MetahandleSet metahandles_to_purge; 741c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch }; 742c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 743c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch Directory(); 744c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch virtual ~Directory(); 745c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 746c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DirOpenResult Open(const FilePath& file_path, const std::string& name); 747c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 748c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch void Close(); 749c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 750c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int64 NextMetahandle(); 751c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Always returns a negative id. Positive client ids are generated 752c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // by the server only. 753c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch Id NextId(); 754c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 755c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const FilePath& file_path() const { return kernel_->db_path; } 756c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch bool good() const { return NULL != store_; } 757c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 75872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // The download progress is an opaque token provided by the sync server 75972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // to indicate the continuation state of the next GetUpdates operation. 76072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen void GetDownloadProgress( 76172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen ModelType type, 76272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen sync_pb::DataTypeProgressMarker* value_out) const; 76372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen void GetDownloadProgressAsString( 76472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen ModelType type, 76572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen std::string* value_out) const; 76672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen void SetDownloadProgress( 76772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen ModelType type, 76872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen const sync_pb::DataTypeProgressMarker& value); 769c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 770c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch bool initial_sync_ended_for_type(ModelType type) const; 771c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch void set_initial_sync_ended_for_type(ModelType type, bool value); 77221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen AutofillMigrationState get_autofill_migration_state() const; 77321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 77421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen AutofillMigrationDebugInfo get_autofill_migration_debug_info() const; 77521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 77621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen void set_autofill_migration_state(AutofillMigrationState state); 77721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 77821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen void set_autofill_migration_state_debug_info( 77921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen syncable::AutofillMigrationDebugInfo::PropertyToSet property_to_set, 78021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen const syncable::AutofillMigrationDebugInfo& info); 781c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 782c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const std::string& name() const { return kernel_->name; } 783c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 784ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // (Account) Store birthday is opaque to the client, so we keep it in the 785ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // format it is in the proto buffer in case we switch to a binary birthday 786ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // later. 787c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch std::string store_birthday() const; 788ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen void set_store_birthday(const std::string& store_birthday); 789c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 790731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick std::string GetAndClearNotificationState(); 791731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick void SetNotificationState(const std::string& notification_state); 792731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick 793c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Unique to each account / client pair. 794c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch std::string cache_guid() const; 795c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 796ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen void SetChangeListener(DirectoryChangeListener* listener); 797c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 798c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch protected: // for friends, mainly used by Entry constructors 799201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch virtual EntryKernel* GetEntryByHandle(int64 handle); 800201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch virtual EntryKernel* GetEntryByHandle(int64 metahandle, 801201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch ScopedKernelLock* lock); 802201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch virtual EntryKernel* GetEntryById(const Id& id); 803c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch EntryKernel* GetEntryByServerTag(const std::string& tag); 804201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch virtual EntryKernel* GetEntryByClientTag(const std::string& tag); 805c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch EntryKernel* GetRootEntry(); 806c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch bool ReindexId(EntryKernel* const entry, const Id& new_id); 807c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch void ReindexParentId(EntryKernel* const entry, const Id& new_parent_id); 808c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch void ClearDirtyMetahandles(); 809c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 810c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // These don't do semantic checking. 811c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // The semantic checking is implemented higher up. 812c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch void UnlinkEntryFromOrder(EntryKernel* entry, 813c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch WriteTransaction* trans, 814c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ScopedKernelLock* lock); 815c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 816c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Overridden by tests. 817c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch virtual DirectoryBackingStore* CreateBackingStore( 818c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const std::string& dir_name, 819c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const FilePath& backing_filepath); 820c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 821c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch private: 822c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // These private versions expect the kernel lock to already be held 823c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // before calling. 824c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch EntryKernel* GetEntryById(const Id& id, ScopedKernelLock* const lock); 825c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 826c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DirOpenResult OpenImpl(const FilePath& file_path, const std::string& name); 827c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 82821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen template <class T> void TestAndSet(T* kernel_data, const T* data_to_set); 82921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 830c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch struct DirectoryEventTraits { 831c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch typedef DirectoryEvent EventType; 832c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch static inline bool IsChannelShutdownEvent(const DirectoryEvent& event) { 833c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return DIRECTORY_DESTROYED == event; 834c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 835c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch }; 836c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch public: 83772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen typedef EventChannel<DirectoryEventTraits, base::Lock> Channel; 838c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch typedef std::vector<int64> ChildHandles; 839c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 840c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Returns the child meta handles for given parent id. 841c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch void GetChildHandles(BaseTransaction*, const Id& parent_id, 842c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ChildHandles* result); 843c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 844c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Find the first or last child in the positional ordering under a parent, 845c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // and return its id. Returns a root Id if parent has no children. 846201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch virtual Id GetFirstChildId(BaseTransaction* trans, const Id& parent_id); 847c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch Id GetLastChildId(BaseTransaction* trans, const Id& parent_id); 848c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 849dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen // Compute a local predecessor position for |update_item|. The position 850dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen // is determined by the SERVER_POSITION_IN_PARENT value of |update_item|, 851dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen // as well as the SERVER_POSITION_IN_PARENT values of any up-to-date 852dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen // children of |parent_id|. 853dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen Id ComputePrevIdFromServerPosition( 854dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen const EntryKernel* update_item, 855dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen const syncable::Id& parent_id); 856dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen 857c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // SaveChanges works by taking a consistent snapshot of the current Directory 858c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // state and indices (by deep copy) under a ReadTransaction, passing this 859c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // snapshot to the backing store under no transaction, and finally cleaning 860c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // up by either purging entries no longer needed (this part done under a 861c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // WriteTransaction) or rolling back the dirty bits. It also uses 862c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // internal locking to enforce SaveChanges operations are mutually exclusive. 863c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // 864c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // WARNING: THIS METHOD PERFORMS SYNCHRONOUS I/O VIA SQLITE. 865c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch bool SaveChanges(); 866c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 867c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Returns the number of entities with the unsynced bit set. 868c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int64 unsynced_entity_count() const; 869c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 870c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Get GetUnsyncedMetaHandles should only be called after SaveChanges and 871c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // before any new entries have been created. The intention is that the 872c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // syncer should call it from its PerformSyncQueries member. 873c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch typedef std::vector<int64> UnsyncedMetaHandles; 874c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch void GetUnsyncedMetaHandles(BaseTransaction* trans, 875c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch UnsyncedMetaHandles* result); 876c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 877c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Get all the metahandles for unapplied updates 878c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch typedef std::vector<int64> UnappliedUpdateMetaHandles; 879c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch void GetUnappliedUpdateMetaHandles(BaseTransaction* trans, 880c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch UnappliedUpdateMetaHandles* result); 881c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 882c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Get the channel for post save notification, used by the syncer. 883c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch inline Channel* channel() const { 884c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return kernel_->channel; 885c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 886c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 887c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Checks tree metadata consistency. 888c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // If full_scan is false, the function will avoid pulling any entries from the 889c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // db and scan entries currently in ram. 890c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // If full_scan is true, all entries will be pulled from the database. 891c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // No return value, CHECKs will be triggered if we're given bad 892c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // information. 893c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch void CheckTreeInvariants(syncable::BaseTransaction* trans, 894c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch bool full_scan); 895c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 896c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch void CheckTreeInvariants(syncable::BaseTransaction* trans, 897c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const OriginalEntries* originals); 898c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 899c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch void CheckTreeInvariants(syncable::BaseTransaction* trans, 900c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const MetahandleSet& handles, 901c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const IdFilter& idfilter); 902c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 903c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Purges all data associated with any entries whose ModelType or 904c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // ServerModelType is found in |types|, from _both_ memory and disk. 905c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Only valid, "real" model types are allowed in |types| (see model_type.h 906c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // for definitions). "Purge" is just meant to distinguish from "deleting" 907c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // entries, which means something different in the syncable namespace. 908c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // WARNING! This can be real slow, as it iterates over all entries. 909c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // WARNING! Performs synchronous I/O. 910c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch virtual void PurgeEntriesWithTypeIn(const std::set<ModelType>& types); 911c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 912c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch private: 913c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Helper to prime ids_index, parent_id_and_names_index, unsynced_metahandles 914c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // and unapplied_metahandles from metahandles_index. 915c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch void InitializeIndices(); 916c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 917c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Constructs a consistent snapshot of the current Directory state and 918c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // indices (by deep copy) under a ReadTransaction for use in |snapshot|. 919c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // See SaveChanges() for more information. 920c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch void TakeSnapshotForSaveChanges(SaveChangesSnapshot* snapshot); 921c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 922c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Purges from memory any unused, safe to remove entries that were 923c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // successfully deleted on disk as a result of the SaveChanges that processed 924c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // |snapshot|. See SaveChanges() for more information. 925c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch void VacuumAfterSaveChanges(const SaveChangesSnapshot& snapshot); 926c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 927c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Rolls back dirty bits in the event that the SaveChanges that 928c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // processed |snapshot| failed, for example, due to no disk space. 929c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch void HandleSaveChangesFailure(const SaveChangesSnapshot& snapshot); 930c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 931c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // For new entry creation only 932c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch void InsertEntry(EntryKernel* entry, ScopedKernelLock* lock); 933c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch void InsertEntry(EntryKernel* entry); 934c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 935c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Used by CheckTreeInvariants 936c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch void GetAllMetaHandles(BaseTransaction* trans, MetahandleSet* result); 937c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch bool SafeToPurgeFromMemory(const EntryKernel* const entry) const; 938c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 939c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Internal setters that do not acquire a lock internally. These are unsafe 940c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // on their own; caller must guarantee exclusive access manually by holding 941c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // a ScopedKernelLock. 942c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch void set_initial_sync_ended_for_type_unsafe(ModelType type, bool x); 943731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick void SetNotificationStateUnsafe(const std::string& notification_state); 944c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 945c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch Directory& operator = (const Directory&); 946c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 947c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch public: 948dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen typedef Index<MetahandleIndexer>::Set MetahandlesIndex; 949dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen typedef Index<IdIndexer>::Set IdsIndex; 950c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // All entries in memory must be in both the MetahandlesIndex and 951c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // the IdsIndex, but only non-deleted entries will be the 952c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // ParentIdChildIndex. 953dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen typedef Index<ParentIdAndHandleIndexer>::Set ParentIdChildIndex; 954c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 955c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Contains both deleted and existing entries with tags. 956c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // We can't store only existing tags because the client would create 957c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // items that had a duplicated ID in the end, resulting in a DB key 958c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // violation. ID reassociation would fail after an attempted commit. 959dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen typedef Index<ClientTagIndexer>::Set ClientTagIndex; 960c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 961c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch protected: 962c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Used by tests. 963c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch void init_kernel(const std::string& name); 964c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 965c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch private: 966c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 967c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch struct Kernel { 968c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch Kernel(const FilePath& db_path, const std::string& name, 969c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const KernelLoadInfo& info); 970c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 971c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ~Kernel(); 972c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 973c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch void AddRef(); // For convenience. 974c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch void Release(); 975c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 976c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch FilePath const db_path; 977c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // TODO(timsteele): audit use of the member and remove if possible 978c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch volatile base::subtle::AtomicWord refcount; 979c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 980c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Implements ReadTransaction / WriteTransaction using a simple lock. 98172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen base::Lock transaction_mutex; 982c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 983c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // The name of this directory. 984c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch std::string const name; 985c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 986c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Protects all members below. 987c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // The mutex effectively protects all the indices, but not the 988c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // entries themselves. So once a pointer to an entry is pulled 989c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // from the index, the mutex can be unlocked and entry read or written. 990c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // 991c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Never hold the mutex and do anything with the database or any 992c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // other buffered IO. Violating this rule will result in deadlock. 99372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen base::Lock mutex; 994dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen // Entries indexed by metahandle 995dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen MetahandlesIndex* metahandles_index; 996dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen // Entries indexed by id 997dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen IdsIndex* ids_index; 998c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ParentIdChildIndex* parent_id_child_index; 999c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ClientTagIndex* client_tag_index; 1000c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // So we don't have to create an EntryKernel every time we want to 1001c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // look something up in an index. Needle in haystack metaphor. 1002c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch EntryKernel needle; 1003c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1004c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // 3 in-memory indices on bits used extremely frequently by the syncer. 1005c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch MetahandleSet* const unapplied_update_metahandles; 1006c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch MetahandleSet* const unsynced_metahandles; 1007c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Contains metahandles that are most likely dirty (though not 1008c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // necessarily). Dirtyness is confirmed in TakeSnapshotForSaveChanges(). 1009c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch MetahandleSet* const dirty_metahandles; 1010c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1011c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // When a purge takes place, we remove items from all our indices and stash 1012c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // them in here so that SaveChanges can persist their permanent deletion. 1013c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch MetahandleSet* const metahandles_to_purge; 1014c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1015c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // TODO(ncarter): Figure out what the hell this is, and comment it. 1016c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch Channel* const channel; 1017c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1018ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // The listener for directory change events, triggered when the transaction 1019ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // is ending. 1020ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen DirectoryChangeListener* change_listener_; 1021c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1022c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch KernelShareInfoStatus info_status; 1023c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1024c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // These 3 members are backed in the share_info table, and 1025c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // their state is marked by the flag above. 1026c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1027c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // A structure containing the Directory state that is written back into the 1028c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // database on SaveChanges. 1029c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch PersistedKernelInfo persisted_info; 1030c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1031c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // A unique identifier for this account's cache db, used to generate 1032c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // unique server IDs. No need to lock, only written at init time. 1033c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch std::string cache_guid; 1034c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1035c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // It doesn't make sense for two threads to run SaveChanges at the same 1036c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // time; this mutex protects that activity. 103772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen base::Lock save_changes_mutex; 1038c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1039c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // The next metahandle is protected by kernel mutex. 1040c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int64 next_metahandle; 1041c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1042c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Keep a history of recently flushed metahandles for debugging 1043c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // purposes. Protected by the save_changes_mutex. 1044c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DebugQueue<int64, 1000> flushed_metahandles; 1045c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch }; 1046c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1047dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen // Helper method used to do searches on |parent_id_child_index|. 1048dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen ParentIdChildIndex::iterator LocateInParentChildIndex( 1049dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen const ScopedKernelLock& lock, 1050dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen const Id& parent_id, 1051dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen int64 position_in_parent, 1052dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen const Id& item_id_for_tiebreaking); 1053dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen 1054dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen // Return an iterator to the beginning of the range of the children of 1055dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen // |parent_id| in the kernel's parent_id_child_index. 1056dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen ParentIdChildIndex::iterator GetParentChildIndexLowerBound( 1057dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen const ScopedKernelLock& lock, 1058dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen const Id& parent_id); 1059dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen 1060dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen // Return an iterator to just past the end of the range of the 1061dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen // children of |parent_id| in the kernel's parent_id_child_index. 1062dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen ParentIdChildIndex::iterator GetParentChildIndexUpperBound( 1063dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen const ScopedKernelLock& lock, 1064dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen const Id& parent_id); 1065dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen 1066c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch Kernel* kernel_; 1067c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1068c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DirectoryBackingStore* store_; 1069c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}; 1070c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1071c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochclass ScopedKernelLock { 1072c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch public: 1073c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch explicit ScopedKernelLock(const Directory*); 1074c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ~ScopedKernelLock() {} 1075c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 107672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen base::AutoLock scoped_lock_; 1077c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch Directory* const dir_; 1078c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DISALLOW_COPY_AND_ASSIGN(ScopedKernelLock); 1079c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}; 1080c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1081c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Transactions are now processed FIFO with a straight lock 1082c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochclass BaseTransaction { 1083c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch friend class Entry; 1084c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch public: 1085c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch inline Directory* directory() const { return directory_; } 1086c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch inline Id root_id() const { return Id(); } 1087c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1088c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch virtual ~BaseTransaction(); 1089c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1090c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch protected: 1091c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch BaseTransaction(Directory* directory, const char* name, 1092c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const char* source_file, int line, WriterTag writer); 1093c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1094201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch // For unit testing. Everything will be mocked out no point initializing. 1095201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch explicit BaseTransaction(Directory* directory); 1096201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch 1097c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch void UnlockAndLog(OriginalEntries* entries); 1098ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen virtual bool NotifyTransactionChangingAndEnding( 1099ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen OriginalEntries* entries, 1100ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen ModelTypeBitSet* models_with_changes); 1101ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen virtual void NotifyTransactionComplete(ModelTypeBitSet models_with_changes); 1102c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1103c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch Directory* const directory_; 1104c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch Directory::Kernel* const dirkernel_; // for brevity 1105c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const char* const name_; 1106c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch base::TimeTicks time_acquired_; 1107c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const char* const source_file_; 1108c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const int line_; 1109c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch WriterTag writer_; 1110c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1111c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch private: 1112c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch void Lock(); 1113c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1114c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DISALLOW_COPY_AND_ASSIGN(BaseTransaction); 1115c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}; 1116c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1117c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Locks db in constructor, unlocks in destructor. 1118c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochclass ReadTransaction : public BaseTransaction { 1119c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch public: 1120c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ReadTransaction(Directory* directory, const char* source_file, 1121c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int line); 1122c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ReadTransaction(const ScopedDirLookup& scoped_dir, 1123c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const char* source_file, int line); 1124c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1125c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch virtual ~ReadTransaction(); 1126c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1127c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch protected: // Don't allow creation on heap, except by sync API wrapper. 1128c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch friend class sync_api::ReadTransaction; 1129c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch void* operator new(size_t size) { return (::operator new)(size); } 1130c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1131c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DISALLOW_COPY_AND_ASSIGN(ReadTransaction); 1132c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}; 1133c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1134c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Locks db in constructor, unlocks in destructor. 1135c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochclass WriteTransaction : public BaseTransaction { 1136c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch friend class MutableEntry; 1137c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch public: 1138c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch explicit WriteTransaction(Directory* directory, WriterTag writer, 1139c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const char* source_file, int line); 1140c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch explicit WriteTransaction(const ScopedDirLookup& directory, 1141c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch WriterTag writer, const char* source_file, 1142c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int line); 1143c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch virtual ~WriteTransaction(); 1144c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1145c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch void SaveOriginal(EntryKernel* entry); 1146c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1147c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch protected: 1148c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Before an entry gets modified, we copy the original into a list 1149c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // so that we can issue change notifications when the transaction 1150c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // is done. 1151c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch OriginalEntries* const originals_; 1152c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1153201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch explicit WriteTransaction(Directory *directory); 1154201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch 1155c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DISALLOW_COPY_AND_ASSIGN(WriteTransaction); 1156c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}; 1157c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1158c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool IsLegalNewParent(BaseTransaction* trans, const Id& id, const Id& parentid); 1159c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1160c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochint64 Now(); 1161c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1162c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// This function sets only the flags needed to get this entry to sync. 1163c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid MarkForSyncing(syncable::MutableEntry* e); 1164c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1165c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// This is not a reset. It just sets the numeric fields which are not 1166c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// initialized by the constructor to zero. 1167c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid ZeroFields(EntryKernel* entry, int first_field); 1168c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1169c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} // namespace syncable 1170c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1171c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstd::ostream& operator <<(std::ostream&, const syncable::Blob&); 1172c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1173c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#endif // CHROME_BROWSER_SYNC_SYNCABLE_SYNCABLE_H_ 1174