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