1868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)// Copyright (c) 2013 The Chromium Authors. All rights reserved.
2868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
3868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)// found in the LICENSE file.
4868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
5868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "content/browser/indexed_db/indexed_db_backing_store.h"
6868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
7c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch#include "base/files/file_path.h"
81320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "base/files/file_util.h"
95c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu#include "base/format_macros.h"
10e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch#include "base/json/json_reader.h"
11e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch#include "base/json/json_writer.h"
12868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/logging.h"
13868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/metrics/histogram.h"
147dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "base/strings/string_util.h"
155c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu#include "base/strings/stringprintf.h"
16868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/utf_string_conversions.h"
170529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch#include "content/browser/child_process_security_policy_impl.h"
180529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch#include "content/browser/indexed_db/indexed_db_blob_info.h"
19f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#include "content/browser/indexed_db/indexed_db_class_factory.h"
20e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch#include "content/browser/indexed_db/indexed_db_database_error.h"
21868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "content/browser/indexed_db/indexed_db_leveldb_coding.h"
22868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "content/browser/indexed_db/indexed_db_metadata.h"
23868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "content/browser/indexed_db/indexed_db_tracing.h"
2423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)#include "content/browser/indexed_db/indexed_db_value.h"
25868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "content/browser/indexed_db/leveldb/leveldb_comparator.h"
26868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "content/browser/indexed_db/leveldb/leveldb_database.h"
27116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "content/browser/indexed_db/leveldb/leveldb_factory.h"
28868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "content/browser/indexed_db/leveldb/leveldb_iterator.h"
29868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "content/browser/indexed_db/leveldb/leveldb_transaction.h"
30868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "content/common/indexed_db/indexed_db_key.h"
31868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "content/common/indexed_db/indexed_db_key_path.h"
32868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "content/common/indexed_db/indexed_db_key_range.h"
335c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu#include "content/public/browser/browser_thread.h"
345c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu#include "net/url_request/url_request_context.h"
351320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "storage/browser/blob/blob_data_handle.h"
361320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "storage/browser/fileapi/file_stream_writer.h"
371320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "storage/browser/fileapi/file_writer_delegate.h"
381320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "storage/browser/fileapi/local_file_stream_writer.h"
391320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "storage/common/database/database_identifier.h"
40ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch#include "third_party/WebKit/public/platform/WebIDBTypes.h"
414e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include "third_party/WebKit/public/web/WebSerializedScriptValueVersion.h"
42ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch#include "third_party/leveldatabase/env_chromium.h"
43868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
445c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liuusing base::FilePath;
45868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)using base::StringPiece;
4603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)using storage::FileWriterDelegate;
47868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
48868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)namespace content {
49868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
501e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)namespace {
511e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
525c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo LiuFilePath GetBlobDirectoryName(const FilePath& pathBase, int64 database_id) {
535c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  return pathBase.AppendASCII(base::StringPrintf("%" PRIx64, database_id));
545c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu}
555c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
565c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo LiuFilePath GetBlobDirectoryNameForKey(const FilePath& pathBase,
575c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu                                    int64 database_id,
585c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu                                    int64 key) {
595c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  FilePath path = GetBlobDirectoryName(pathBase, database_id);
605c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  path = path.AppendASCII(base::StringPrintf(
615c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      "%02x", static_cast<int>(key & 0x000000000000ff00) >> 8));
625c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  return path;
635c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu}
645c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
655c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo LiuFilePath GetBlobFileNameForKey(const FilePath& pathBase,
665c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu                               int64 database_id,
675c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu                               int64 key) {
685c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  FilePath path = GetBlobDirectoryNameForKey(pathBase, database_id, key);
695c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  path = path.AppendASCII(base::StringPrintf("%" PRIx64, key));
705c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  return path;
715c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu}
725c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
735c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liubool MakeIDBBlobDirectory(const FilePath& pathBase,
745c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu                          int64 database_id,
755c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu                          int64 key) {
765c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  FilePath path = GetBlobDirectoryNameForKey(pathBase, database_id, key);
775c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  return base::CreateDirectory(path);
785c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu}
795c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
801e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)static std::string ComputeOriginIdentifier(const GURL& origin_url) {
8103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  return storage::GetIdentifierFromOrigin(origin_url) + "@1";
821e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)}
831e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
841e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)static base::FilePath ComputeFileName(const GURL& origin_url) {
851e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  return base::FilePath()
8603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      .AppendASCII(storage::GetIdentifierFromOrigin(origin_url))
871e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      .AddExtension(FILE_PATH_LITERAL(".indexeddb.leveldb"));
881e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)}
891e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
900529e5d033099cbfc42635f6f6183833b09dff6eBen Murdochstatic base::FilePath ComputeBlobPath(const GURL& origin_url) {
910529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  return base::FilePath()
9203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      .AppendASCII(storage::GetIdentifierFromOrigin(origin_url))
930529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch      .AddExtension(FILE_PATH_LITERAL(".indexeddb.blob"));
940529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch}
950529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch
96e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdochstatic base::FilePath ComputeCorruptionFileName(const GURL& origin_url) {
97e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  return ComputeFileName(origin_url)
98e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch      .Append(FILE_PATH_LITERAL("corruption_info.json"));
99e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch}
100e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch
1011e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)}  // namespace
1021e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
103868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)static const int64 kKeyGeneratorInitialNumber =
104868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    1;  // From the IndexedDB specification.
105868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
106868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)enum IndexedDBBackingStoreErrorSource {
107868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // 0 - 2 are no longer used.
108868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  FIND_KEY_IN_INDEX = 3,
109868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  GET_IDBDATABASE_METADATA,
110868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  GET_INDEXES,
111868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  GET_KEY_GENERATOR_CURRENT_NUMBER,
112868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  GET_OBJECT_STORES,
113868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  GET_RECORD,
114868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  KEY_EXISTS_IN_OBJECT_STORE,
115868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  LOAD_CURRENT_ROW,
116868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  SET_UP_METADATA,
117868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  GET_PRIMARY_KEY_VIA_INDEX,
118868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  KEY_EXISTS_IN_INDEX,
119868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  VERSION_EXISTS,
120868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DELETE_OBJECT_STORE,
121868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  SET_MAX_OBJECT_STORE_ID,
122868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  SET_MAX_INDEX_ID,
123868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  GET_NEW_DATABASE_ID,
124868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  GET_NEW_VERSION_NUMBER,
125868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  CREATE_IDBDATABASE_METADATA,
126868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DELETE_DATABASE,
127868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  TRANSACTION_COMMIT_METHOD,  // TRANSACTION_COMMIT is a WinNT.h macro
128ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  GET_DATABASE_NAMES,
1290529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  DELETE_INDEX,
1300529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  CLEAR_OBJECT_STORE,
131010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  READ_BLOB_JOURNAL,
132010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  DECODE_BLOB_JOURNAL,
133cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  GET_BLOB_KEY_GENERATOR_CURRENT_NUMBER,
134cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  GET_BLOB_INFO_FOR_RECORD,
135868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  INTERNAL_ERROR_MAX,
136868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)};
137868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
138868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)static void RecordInternalError(const char* type,
139868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                IndexedDBBackingStoreErrorSource location) {
140eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  std::string name;
141eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  name.append("WebCore.IndexedDB.BackingStore.").append(type).append("Error");
142eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  base::Histogram::FactoryGet(name,
143868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                              1,
144868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                              INTERNAL_ERROR_MAX,
145868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                              INTERNAL_ERROR_MAX + 1,
146868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                              base::HistogramBase::kUmaTargetedHistogramFlag)
147868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      ->Add(location);
148868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
149868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
150e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch// Use to signal conditions caused by data corruption.
151e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch// A macro is used instead of an inline function so that the assert and log
152e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch// report the line number.
153868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#define REPORT_ERROR(type, location)                      \
154868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  do {                                                    \
155868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    LOG(ERROR) << "IndexedDB " type " Error: " #location; \
156868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    RecordInternalError(type, location);                  \
157868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  } while (0)
158868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
159868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#define INTERNAL_READ_ERROR(location) REPORT_ERROR("Read", location)
160868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#define INTERNAL_CONSISTENCY_ERROR(location) \
161868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  REPORT_ERROR("Consistency", location)
162868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#define INTERNAL_WRITE_ERROR(location) REPORT_ERROR("Write", location)
163868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
164e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch// Use to signal conditions that usually indicate developer error, but
165e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch// could be caused by data corruption.  A macro is used instead of an
166e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch// inline function so that the assert and log report the line number.
167f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// TODO(cmumford): Improve test coverage so that all error conditions are
168f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// "tested" and then delete this macro.
169e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch#define REPORT_ERROR_UNTESTED(type, location)             \
170e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  do {                                                    \
171e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    LOG(ERROR) << "IndexedDB " type " Error: " #location; \
172e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    NOTREACHED();                                         \
173e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    RecordInternalError(type, location);                  \
174e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  } while (0)
175e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch
176e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch#define INTERNAL_READ_ERROR_UNTESTED(location) \
177e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  REPORT_ERROR_UNTESTED("Read", location)
178e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch#define INTERNAL_CONSISTENCY_ERROR_UNTESTED(location) \
179e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  REPORT_ERROR_UNTESTED("Consistency", location)
180e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch#define INTERNAL_WRITE_ERROR_UNTESTED(location) \
181e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  REPORT_ERROR_UNTESTED("Write", location)
182e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch
183868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)static void PutBool(LevelDBTransaction* transaction,
1847dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch                    const StringPiece& key,
185868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                    bool value) {
1867dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  std::string buffer;
187868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  EncodeBool(value, &buffer);
188868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  transaction->Put(key, &buffer);
189868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
190868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
191a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// Was able to use LevelDB to read the data w/o error, but the data read was not
192a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// in the expected format.
193a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)static leveldb::Status InternalInconsistencyStatus() {
194a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  return leveldb::Status::Corruption("Internal inconsistency");
195a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)}
196a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
197a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)static leveldb::Status InvalidDBKeyStatus() {
198a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  return leveldb::Status::InvalidArgument("Invalid database key ID");
199a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)}
200a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
201010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)static leveldb::Status IOErrorStatus() {
202010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  return leveldb::Status::IOError("IO Error");
203010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)}
204010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
205868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)template <typename DBOrTransaction>
206a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)static leveldb::Status GetInt(DBOrTransaction* db,
207a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                              const StringPiece& key,
208a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                              int64* found_int,
209a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                              bool* found) {
210868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  std::string result;
211a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  leveldb::Status s = db->Get(key, &result, found);
212a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  if (!s.ok())
213a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    return s;
214868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (!*found)
215a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    return leveldb::Status::OK();
216868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  StringPiece slice(result);
217a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  if (DecodeInt(&slice, found_int) && slice.empty())
218a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    return s;
219a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  return InternalInconsistencyStatus();
220868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
221868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
222868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)static void PutInt(LevelDBTransaction* transaction,
2237dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch                   const StringPiece& key,
224868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                   int64 value) {
225868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DCHECK_GE(value, 0);
2267dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  std::string buffer;
227868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  EncodeInt(value, &buffer);
228868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  transaction->Put(key, &buffer);
229868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
230868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
231868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)template <typename DBOrTransaction>
232a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)WARN_UNUSED_RESULT static leveldb::Status GetVarInt(DBOrTransaction* db,
233a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                                                    const StringPiece& key,
234a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                                                    int64* found_int,
235a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                                                    bool* found) {
236868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  std::string result;
237a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  leveldb::Status s = db->Get(key, &result, found);
238a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  if (!s.ok())
239a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    return s;
240868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (!*found)
241a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    return leveldb::Status::OK();
242868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  StringPiece slice(result);
243a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  if (DecodeVarInt(&slice, found_int) && slice.empty())
244a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    return s;
245a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  return InternalInconsistencyStatus();
246868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
247868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
248868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)static void PutVarInt(LevelDBTransaction* transaction,
2497dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch                      const StringPiece& key,
250868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                      int64 value) {
2517dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  std::string buffer;
252868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  EncodeVarInt(value, &buffer);
253868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  transaction->Put(key, &buffer);
254868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
255868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
256868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)template <typename DBOrTransaction>
257a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)WARN_UNUSED_RESULT static leveldb::Status GetString(
258a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    DBOrTransaction* db,
259a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    const StringPiece& key,
260a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    base::string16* found_string,
261a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    bool* found) {
262868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  std::string result;
263868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  *found = false;
264a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  leveldb::Status s = db->Get(key, &result, found);
265a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  if (!s.ok())
266a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    return s;
267868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (!*found)
268a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    return leveldb::Status::OK();
269868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  StringPiece slice(result);
270a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  if (DecodeString(&slice, found_string) && slice.empty())
271a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    return s;
272a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  return InternalInconsistencyStatus();
273868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
274868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
275868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)static void PutString(LevelDBTransaction* transaction,
2767dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch                      const StringPiece& key,
277a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                      const base::string16& value) {
2787dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  std::string buffer;
279868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  EncodeString(value, &buffer);
280868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  transaction->Put(key, &buffer);
281868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
282868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
283868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)static void PutIDBKeyPath(LevelDBTransaction* transaction,
2847dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch                          const StringPiece& key,
285868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                          const IndexedDBKeyPath& value) {
2867dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  std::string buffer;
287868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  EncodeIDBKeyPath(value, &buffer);
288868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  transaction->Put(key, &buffer);
289868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
290868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
2917dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochstatic int CompareKeys(const StringPiece& a, const StringPiece& b) {
292eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  return Compare(a, b, false /*index_keys*/);
293868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
294868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
2957dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochstatic int CompareIndexKeys(const StringPiece& a, const StringPiece& b) {
296eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  return Compare(a, b, true /*index_keys*/);
297868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
298868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
299effb81e5f8246d0db0270817048dc992db66e9fbBen Murdochint IndexedDBBackingStore::Comparator::Compare(const StringPiece& a,
300effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch                                               const StringPiece& b) const {
301effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  return content::Compare(a, b, false /*index_keys*/);
302effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch}
303effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch
304effb81e5f8246d0db0270817048dc992db66e9fbBen Murdochconst char* IndexedDBBackingStore::Comparator::Name() const {
305effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  return "idb_cmp1";
306effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch}
307868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
308868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)// 0 - Initial version.
309868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)// 1 - Adds UserIntVersion to DatabaseMetaData.
310868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)// 2 - Adds DataVersion to to global metadata.
311cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// 3 - Adds metadata needed for blob support.
312cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)static const int64 kLatestKnownSchemaVersion = 3;
313868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)WARN_UNUSED_RESULT static bool IsSchemaKnown(LevelDBDatabase* db, bool* known) {
314868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  int64 db_schema_version = 0;
315868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  bool found = false;
316a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  leveldb::Status s =
317a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      GetInt(db, SchemaVersionKey::Encode(), &db_schema_version, &found);
318a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  if (!s.ok())
319868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return false;
320868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (!found) {
321868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    *known = true;
322868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return true;
323868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
324868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (db_schema_version > kLatestKnownSchemaVersion) {
325868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    *known = false;
326868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return true;
327868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
328868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
3294e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  const uint32 latest_known_data_version =
330f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      blink::kSerializedScriptValueVersion;
331868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  int64 db_data_version = 0;
332a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  s = GetInt(db, DataVersionKey::Encode(), &db_data_version, &found);
333a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  if (!s.ok())
334868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return false;
335868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (!found) {
336868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    *known = true;
337868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return true;
338868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
339868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
340868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (db_data_version > latest_known_data_version) {
341868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    *known = false;
342868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return true;
343868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
344868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
345868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  *known = true;
346868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  return true;
347868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
348868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
349cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// TODO(ericu): Move this down into the member section of this file.  I'm
350cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// leaving it here for this CL as it's easier to see the diffs in place.
351116680a4aac90f2aa7413d9095a592090648e557Ben MurdochWARN_UNUSED_RESULT leveldb::Status IndexedDBBackingStore::SetUpMetadata() {
3524e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  const uint32 latest_known_data_version =
353f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      blink::kSerializedScriptValueVersion;
3547dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  const std::string schema_version_key = SchemaVersionKey::Encode();
3557dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  const std::string data_version_key = DataVersionKey::Encode();
356868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
357cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  scoped_refptr<LevelDBTransaction> transaction =
358f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      IndexedDBClassFactory::Get()->CreateLevelDBTransaction(db_.get());
359868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
360868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  int64 db_schema_version = 0;
361868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  int64 db_data_version = 0;
362868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  bool found = false;
363a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  leveldb::Status s =
3647dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      GetInt(transaction.get(), schema_version_key, &db_schema_version, &found);
365a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  if (!s.ok()) {
366e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    INTERNAL_READ_ERROR_UNTESTED(SET_UP_METADATA);
367116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    return s;
368868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
369868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (!found) {
370868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    // Initialize new backing store.
371868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    db_schema_version = kLatestKnownSchemaVersion;
3727dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    PutInt(transaction.get(), schema_version_key, db_schema_version);
373868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    db_data_version = latest_known_data_version;
3747dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    PutInt(transaction.get(), data_version_key, db_data_version);
375cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    // If a blob directory already exists for this database, blow it away.  It's
376cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    // leftover from a partially-purged previous generation of data.
377cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    if (!base::DeleteFile(blob_path_, true)) {
378cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      INTERNAL_WRITE_ERROR_UNTESTED(SET_UP_METADATA);
379116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      return IOErrorStatus();
380cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    }
381868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  } else {
382868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    // Upgrade old backing store.
383868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    DCHECK_LE(db_schema_version, kLatestKnownSchemaVersion);
384868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    if (db_schema_version < 1) {
385868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      db_schema_version = 1;
3867dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      PutInt(transaction.get(), schema_version_key, db_schema_version);
3877dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      const std::string start_key =
388cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)          DatabaseNameKey::EncodeMinKeyForOrigin(origin_identifier_);
3897dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      const std::string stop_key =
390cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)          DatabaseNameKey::EncodeStopKeyForOrigin(origin_identifier_);
391cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      scoped_ptr<LevelDBIterator> it = db_->CreateIterator();
3920529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch      for (s = it->Seek(start_key);
3930529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch           s.ok() && it->IsValid() && CompareKeys(it->Key(), stop_key) < 0;
3940529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch           s = it->Next()) {
395868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        int64 database_id = 0;
396868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        found = false;
397a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)        s = GetInt(transaction.get(), it->Key(), &database_id, &found);
398a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)        if (!s.ok()) {
399e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch          INTERNAL_READ_ERROR_UNTESTED(SET_UP_METADATA);
400116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch          return s;
401868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        }
402868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        if (!found) {
403e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch          INTERNAL_CONSISTENCY_ERROR_UNTESTED(SET_UP_METADATA);
404116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch          return InternalInconsistencyStatus();
405868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        }
4067dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch        std::string int_version_key = DatabaseMetaDataKey::Encode(
407868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)            database_id, DatabaseMetaDataKey::USER_INT_VERSION);
408868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        PutVarInt(transaction.get(),
4097dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch                  int_version_key,
410868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                  IndexedDBDatabaseMetadata::DEFAULT_INT_VERSION);
411868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      }
412868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    }
4130529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    if (s.ok() && db_schema_version < 2) {
414868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      db_schema_version = 2;
4157dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      PutInt(transaction.get(), schema_version_key, db_schema_version);
416f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      db_data_version = blink::kSerializedScriptValueVersion;
4177dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      PutInt(transaction.get(), data_version_key, db_data_version);
418868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    }
419cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    if (db_schema_version < 3) {
420cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      db_schema_version = 3;
421cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      if (!base::DeleteFile(blob_path_, true)) {
422cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        INTERNAL_WRITE_ERROR_UNTESTED(SET_UP_METADATA);
423116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch        return IOErrorStatus();
424cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      }
425cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    }
426868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
427868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
4280529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  if (!s.ok()) {
4290529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    INTERNAL_READ_ERROR_UNTESTED(SET_UP_METADATA);
430116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    return s;
4310529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  }
4320529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch
433868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // All new values will be written using this serialization version.
434868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  found = false;
435a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  s = GetInt(transaction.get(), data_version_key, &db_data_version, &found);
436a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  if (!s.ok()) {
437e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    INTERNAL_READ_ERROR_UNTESTED(SET_UP_METADATA);
438116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    return s;
439868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
440868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (!found) {
441e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    INTERNAL_CONSISTENCY_ERROR_UNTESTED(SET_UP_METADATA);
442116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    return InternalInconsistencyStatus();
443868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
444868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (db_data_version < latest_known_data_version) {
445868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    db_data_version = latest_known_data_version;
4467dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    PutInt(transaction.get(), data_version_key, db_data_version);
447868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
448868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
449868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DCHECK_EQ(db_schema_version, kLatestKnownSchemaVersion);
450868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DCHECK_EQ(db_data_version, latest_known_data_version);
451868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
452a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  s = transaction->Commit();
453116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  if (!s.ok())
454e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    INTERNAL_WRITE_ERROR_UNTESTED(SET_UP_METADATA);
455116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  return s;
456868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
457868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
458868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)template <typename DBOrTransaction>
459a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)WARN_UNUSED_RESULT static leveldb::Status GetMaxObjectStoreId(
460a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    DBOrTransaction* db,
461a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    int64 database_id,
462a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    int64* max_object_store_id) {
4637dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  const std::string max_object_store_id_key = DatabaseMetaDataKey::Encode(
464868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      database_id, DatabaseMetaDataKey::MAX_OBJECT_STORE_ID);
465a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  return GetMaxObjectStoreId(db, max_object_store_id_key, max_object_store_id);
466868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
467868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
468868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)template <typename DBOrTransaction>
469a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)WARN_UNUSED_RESULT static leveldb::Status GetMaxObjectStoreId(
470868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    DBOrTransaction* db,
4717dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    const std::string& max_object_store_id_key,
472868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    int64* max_object_store_id) {
473868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  *max_object_store_id = -1;
474868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  bool found = false;
475a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  leveldb::Status s =
476a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      GetInt(db, max_object_store_id_key, max_object_store_id, &found);
477a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  if (!s.ok())
478a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    return s;
479868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (!found)
480868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    *max_object_store_id = 0;
481868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
482868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DCHECK_GE(*max_object_store_id, 0);
483a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  return s;
484868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
485868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
486868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)class DefaultLevelDBFactory : public LevelDBFactory {
487868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) public:
488f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  DefaultLevelDBFactory() {}
489424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  virtual leveldb::Status OpenLevelDB(const base::FilePath& file_name,
490424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)                                      const LevelDBComparator* comparator,
491424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)                                      scoped_ptr<LevelDBDatabase>* db,
492424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)                                      bool* is_disk_full) OVERRIDE {
493ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    return LevelDBDatabase::Open(file_name, comparator, db, is_disk_full);
494868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
495a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  virtual leveldb::Status DestroyLevelDB(const base::FilePath& file_name)
496a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      OVERRIDE {
497868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return LevelDBDatabase::Destroy(file_name);
498868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
499f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
500f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) private:
501f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(DefaultLevelDBFactory);
502868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)};
503868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
504cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)static bool GetBlobKeyGeneratorCurrentNumber(
505cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    LevelDBTransaction* leveldb_transaction,
506cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    int64 database_id,
507cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    int64* blob_key_generator_current_number) {
508cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  const std::string key_gen_key = DatabaseMetaDataKey::Encode(
509cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      database_id, DatabaseMetaDataKey::BLOB_KEY_GENERATOR_CURRENT_NUMBER);
510cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
511cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // Default to initial number if not found.
512cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  int64 cur_number = DatabaseMetaDataKey::kBlobKeyGeneratorInitialNumber;
513cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  std::string data;
514cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
515cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  bool found = false;
516cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  bool ok = leveldb_transaction->Get(key_gen_key, &data, &found).ok();
517cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (!ok) {
518cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    INTERNAL_READ_ERROR_UNTESTED(GET_BLOB_KEY_GENERATOR_CURRENT_NUMBER);
519cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    return false;
520cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  }
521cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (found) {
522cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    StringPiece slice(data);
523cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    if (!DecodeVarInt(&slice, &cur_number) || !slice.empty() ||
524cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        !DatabaseMetaDataKey::IsValidBlobKey(cur_number)) {
525cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      INTERNAL_READ_ERROR_UNTESTED(GET_BLOB_KEY_GENERATOR_CURRENT_NUMBER);
526cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      return false;
527cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    }
528cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  }
529cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  *blob_key_generator_current_number = cur_number;
530cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  return true;
531cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
532cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
533cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)static bool UpdateBlobKeyGeneratorCurrentNumber(
534cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    LevelDBTransaction* leveldb_transaction,
535cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    int64 database_id,
536cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    int64 blob_key_generator_current_number) {
537cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#ifndef NDEBUG
538cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  int64 old_number;
539cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (!GetBlobKeyGeneratorCurrentNumber(
540cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)          leveldb_transaction, database_id, &old_number))
541cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    return false;
542cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  DCHECK_LT(old_number, blob_key_generator_current_number);
543cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#endif
544cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  DCHECK(
545cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      DatabaseMetaDataKey::IsValidBlobKey(blob_key_generator_current_number));
546cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  const std::string key = DatabaseMetaDataKey::Encode(
547cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      database_id, DatabaseMetaDataKey::BLOB_KEY_GENERATOR_CURRENT_NUMBER);
548cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
549cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  PutVarInt(leveldb_transaction, key, blob_key_generator_current_number);
550cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  return true;
551cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
552cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
553010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)// TODO(ericu): Error recovery. If we persistently can't read the
554010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)// blob journal, the safe thing to do is to clear it and leak the blobs,
555010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)// though that may be costly. Still, database/directory deletion should always
556010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)// clean things up, and we can write an fsck that will do a full correction if
557010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)// need be.
558010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)template <typename T>
559010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)static leveldb::Status GetBlobJournal(const StringPiece& leveldb_key,
560010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)                                      T* leveldb_transaction,
561010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)                                      BlobJournalType* journal) {
562010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  std::string data;
563010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  bool found = false;
564010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  leveldb::Status s = leveldb_transaction->Get(leveldb_key, &data, &found);
565010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  if (!s.ok()) {
566116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    INTERNAL_READ_ERROR(READ_BLOB_JOURNAL);
567010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    return s;
568010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  }
569010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  journal->clear();
570010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  if (!found || !data.size())
571010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    return leveldb::Status::OK();
572010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  StringPiece slice(data);
573010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  if (!DecodeBlobJournal(&slice, journal)) {
574116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    INTERNAL_CONSISTENCY_ERROR_UNTESTED(DECODE_BLOB_JOURNAL);
575010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    s = InternalInconsistencyStatus();
576010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  }
577010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  return s;
578010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)}
579010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
580010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)static void ClearBlobJournal(LevelDBTransaction* leveldb_transaction,
581010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)                             const std::string& level_db_key) {
582010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  leveldb_transaction->Remove(level_db_key);
583010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)}
584010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
585010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)static void UpdatePrimaryJournalWithBlobList(
586010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    LevelDBTransaction* leveldb_transaction,
587010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    const BlobJournalType& journal) {
588010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  const std::string leveldb_key = BlobJournalKey::Encode();
589010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  std::string data;
590010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  EncodeBlobJournal(journal, &data);
591010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  leveldb_transaction->Put(leveldb_key, &data);
592010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)}
593010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
594010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)static void UpdateLiveBlobJournalWithBlobList(
595010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    LevelDBTransaction* leveldb_transaction,
596010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    const BlobJournalType& journal) {
597010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  const std::string leveldb_key = LiveBlobJournalKey::Encode();
598010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  std::string data;
599010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  EncodeBlobJournal(journal, &data);
600010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  leveldb_transaction->Put(leveldb_key, &data);
601010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)}
602010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
603010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)static leveldb::Status MergeBlobsIntoLiveBlobJournal(
604010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    LevelDBTransaction* leveldb_transaction,
605010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    const BlobJournalType& journal) {
606010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  BlobJournalType old_journal;
607010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  const std::string key = LiveBlobJournalKey::Encode();
608010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  leveldb::Status s = GetBlobJournal(key, leveldb_transaction, &old_journal);
609010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  if (!s.ok())
610010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    return s;
611010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
612010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  old_journal.insert(old_journal.end(), journal.begin(), journal.end());
613010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
614010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  UpdateLiveBlobJournalWithBlobList(leveldb_transaction, old_journal);
615010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  return leveldb::Status::OK();
616010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)}
617010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
618010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)static void UpdateBlobJournalWithDatabase(
619010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    LevelDBDirectTransaction* leveldb_transaction,
620010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    int64 database_id) {
621010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  BlobJournalType journal;
622010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  journal.push_back(
623010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      std::make_pair(database_id, DatabaseMetaDataKey::kAllBlobsKey));
624010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  const std::string key = BlobJournalKey::Encode();
625010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  std::string data;
626010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  EncodeBlobJournal(journal, &data);
627010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  leveldb_transaction->Put(key, &data);
628010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)}
629010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
630010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)static leveldb::Status MergeDatabaseIntoLiveBlobJournal(
631010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    LevelDBDirectTransaction* leveldb_transaction,
632010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    int64 database_id) {
633010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  BlobJournalType journal;
634010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  const std::string key = LiveBlobJournalKey::Encode();
635010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  leveldb::Status s = GetBlobJournal(key, leveldb_transaction, &journal);
636010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  if (!s.ok())
637010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    return s;
638010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  journal.push_back(
639010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      std::make_pair(database_id, DatabaseMetaDataKey::kAllBlobsKey));
640010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  std::string data;
641010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  EncodeBlobJournal(journal, &data);
642010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  leveldb_transaction->Put(key, &data);
643010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  return leveldb::Status::OK();
644010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)}
645010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
646cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// Blob Data is encoded as a series of:
647cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)//   { is_file [bool], key [int64 as varInt],
648cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)//     type [string-with-length, may be empty],
649cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)//     (for Blobs only) size [int64 as varInt]
650cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)//     (for Files only) fileName [string-with-length]
651cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)//   }
652cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// There is no length field; just read until you run out of data.
653cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)static std::string EncodeBlobData(
654cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    const std::vector<IndexedDBBlobInfo*>& blob_info) {
655cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  std::string ret;
656cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  std::vector<IndexedDBBlobInfo*>::const_iterator iter;
657cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  for (iter = blob_info.begin(); iter != blob_info.end(); ++iter) {
658cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    const IndexedDBBlobInfo& info = **iter;
659cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    EncodeBool(info.is_file(), &ret);
660cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    EncodeVarInt(info.key(), &ret);
661cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    EncodeStringWithLength(info.type(), &ret);
662cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    if (info.is_file())
663cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      EncodeStringWithLength(info.file_name(), &ret);
664cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    else
665cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      EncodeVarInt(info.size(), &ret);
666cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  }
667cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  return ret;
668cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
669cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
670cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)static bool DecodeBlobData(const std::string& data,
671cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                           std::vector<IndexedDBBlobInfo>* output) {
672cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  std::vector<IndexedDBBlobInfo> ret;
673cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  output->clear();
674cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  StringPiece slice(data);
675cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  while (!slice.empty()) {
676cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    bool is_file;
677cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    int64 key;
678cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    base::string16 type;
679cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    int64 size;
680cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    base::string16 file_name;
681cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
682cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    if (!DecodeBool(&slice, &is_file))
683cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      return false;
684cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    if (!DecodeVarInt(&slice, &key) ||
685cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        !DatabaseMetaDataKey::IsValidBlobKey(key))
686cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      return false;
687cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    if (!DecodeStringWithLength(&slice, &type))
688cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      return false;
689cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    if (is_file) {
690cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      if (!DecodeStringWithLength(&slice, &file_name))
691cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        return false;
692cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      ret.push_back(IndexedDBBlobInfo(key, type, file_name));
693cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    } else {
694cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      if (!DecodeVarInt(&slice, &size) || size < 0)
695cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        return false;
696cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      ret.push_back(IndexedDBBlobInfo(type, static_cast<uint64>(size), key));
697cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    }
698cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  }
699cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  output->swap(ret);
700cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
701cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  return true;
702cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
703cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
704868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)IndexedDBBackingStore::IndexedDBBackingStore(
705c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    IndexedDBFactory* indexed_db_factory,
7061e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    const GURL& origin_url,
7070529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    const base::FilePath& blob_path,
7085c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    net::URLRequestContext* request_context,
709868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    scoped_ptr<LevelDBDatabase> db,
710c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    scoped_ptr<LevelDBComparator> comparator,
7115f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    base::SequencedTaskRunner* task_runner)
712c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    : indexed_db_factory_(indexed_db_factory),
713c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      origin_url_(origin_url),
7140529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch      blob_path_(blob_path),
7151e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      origin_identifier_(ComputeOriginIdentifier(origin_url)),
7165c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      request_context_(request_context),
717c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      task_runner_(task_runner),
7181e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      db_(db.Pass()),
719c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      comparator_(comparator.Pass()),
720cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      active_blob_registry_(this) {
721cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
722868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
723868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)IndexedDBBackingStore::~IndexedDBBackingStore() {
7240529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  if (!blob_path_.empty() && !child_process_ids_granted_.empty()) {
7250529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    ChildProcessSecurityPolicyImpl* policy =
7260529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch        ChildProcessSecurityPolicyImpl::GetInstance();
7270529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    std::set<int>::const_iterator iter;
7280529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    for (iter = child_process_ids_granted_.begin();
7290529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch         iter != child_process_ids_granted_.end();
7300529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch         ++iter) {
7310529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch      policy->RevokeAllPermissionsForFile(*iter, blob_path_);
7320529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    }
7330529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  }
734cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  STLDeleteContainerPairSecondPointers(incognito_blob_map_.begin(),
735cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                                       incognito_blob_map_.end());
736868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // db_'s destructor uses comparator_. The order of destruction is important.
737868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  db_.reset();
738868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  comparator_.reset();
739868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
740868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
741868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)IndexedDBBackingStore::RecordIdentifier::RecordIdentifier(
7427dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    const std::string& primary_key,
743868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    int64 version)
744868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    : primary_key_(primary_key), version_(version) {
745868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DCHECK(!primary_key.empty());
746868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
747868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)IndexedDBBackingStore::RecordIdentifier::RecordIdentifier()
748868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    : primary_key_(), version_(-1) {}
749868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)IndexedDBBackingStore::RecordIdentifier::~RecordIdentifier() {}
750868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
751868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)IndexedDBBackingStore::Cursor::CursorOptions::CursorOptions() {}
752868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)IndexedDBBackingStore::Cursor::CursorOptions::~CursorOptions() {}
753868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
7544e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)enum IndexedDBBackingStoreOpenResult {
7554e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  INDEXED_DB_BACKING_STORE_OPEN_MEMORY_SUCCESS,
7564e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  INDEXED_DB_BACKING_STORE_OPEN_SUCCESS,
7574e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  INDEXED_DB_BACKING_STORE_OPEN_FAILED_DIRECTORY,
7584e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  INDEXED_DB_BACKING_STORE_OPEN_FAILED_UNKNOWN_SCHEMA,
7594e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  INDEXED_DB_BACKING_STORE_OPEN_CLEANUP_DESTROY_FAILED,
7604e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  INDEXED_DB_BACKING_STORE_OPEN_CLEANUP_REOPEN_FAILED,
7614e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  INDEXED_DB_BACKING_STORE_OPEN_CLEANUP_REOPEN_SUCCESS,
7624e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  INDEXED_DB_BACKING_STORE_OPEN_FAILED_IO_ERROR_CHECKING_SCHEMA,
7634e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  INDEXED_DB_BACKING_STORE_OPEN_FAILED_UNKNOWN_ERR,
7644e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  INDEXED_DB_BACKING_STORE_OPEN_MEMORY_FAILED,
7654e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  INDEXED_DB_BACKING_STORE_OPEN_ATTEMPT_NON_ASCII,
7664e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  INDEXED_DB_BACKING_STORE_OPEN_DISK_FULL_DEPRECATED,
7674e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  INDEXED_DB_BACKING_STORE_OPEN_ORIGIN_TOO_LONG,
7684e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  INDEXED_DB_BACKING_STORE_OPEN_NO_RECOVERY,
769e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  INDEXED_DB_BACKING_STORE_OPEN_FAILED_PRIOR_CORRUPTION,
770cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  INDEXED_DB_BACKING_STORE_OPEN_FAILED_CLEANUP_JOURNAL_ERROR,
7714e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  INDEXED_DB_BACKING_STORE_OPEN_MAX,
772868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)};
773868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
7741e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)// static
775868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)scoped_refptr<IndexedDBBackingStore> IndexedDBBackingStore::Open(
776c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    IndexedDBFactory* indexed_db_factory,
7771e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    const GURL& origin_url,
778868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    const base::FilePath& path_base,
7795c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    net::URLRequestContext* request_context,
780f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    blink::WebIDBDataLoss* data_loss,
7810f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)    std::string* data_loss_message,
782c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    bool* disk_full,
7835f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    base::SequencedTaskRunner* task_runner,
784116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    bool clean_journal,
785116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    leveldb::Status* status) {
786f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  *data_loss = blink::WebIDBDataLossNone;
787868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DefaultLevelDBFactory leveldb_factory;
788c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  return IndexedDBBackingStore::Open(indexed_db_factory,
789c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch                                     origin_url,
7900f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)                                     path_base,
7915c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu                                     request_context,
7920f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)                                     data_loss,
7930f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)                                     data_loss_message,
7940f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)                                     disk_full,
795c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch                                     &leveldb_factory,
7965c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu                                     task_runner,
797116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                                     clean_journal,
798116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                                     status);
799868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
800868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
801f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)static std::string OriginToCustomHistogramSuffix(const GURL& origin_url) {
802f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  if (origin_url.host() == "docs.google.com")
803f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    return ".Docs";
804f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  return std::string();
805f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)}
806f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
807f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)static void HistogramOpenStatus(IndexedDBBackingStoreOpenResult result,
808f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                                const GURL& origin_url) {
8094e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  UMA_HISTOGRAM_ENUMERATION("WebCore.IndexedDB.BackingStore.OpenStatus",
8104e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                            result,
8114e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                            INDEXED_DB_BACKING_STORE_OPEN_MAX);
812f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  const std::string suffix = OriginToCustomHistogramSuffix(origin_url);
813f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // Data from the WebCore.IndexedDB.BackingStore.OpenStatus histogram is used
814f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // to generate a graph. So as not to alter the meaning of that graph,
815f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // continue to collect all stats there (above) but also now collect docs stats
816f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // separately (below).
817f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  if (!suffix.empty()) {
818f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    base::LinearHistogram::FactoryGet(
819f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        "WebCore.IndexedDB.BackingStore.OpenStatus" + suffix,
820f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        1,
821f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        INDEXED_DB_BACKING_STORE_OPEN_MAX,
822f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        INDEXED_DB_BACKING_STORE_OPEN_MAX + 1,
823f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        base::HistogramBase::kUmaTargetedHistogramFlag)->Add(result);
824f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  }
8254e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)}
8264e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
8274e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)static bool IsPathTooLong(const base::FilePath& leveldb_dir) {
828a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  int limit = base::GetMaximumPathComponentLength(leveldb_dir.DirName());
8294e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  if (limit == -1) {
8304e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    DLOG(WARNING) << "GetMaximumPathComponentLength returned -1";
8314e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    // In limited testing, ChromeOS returns 143, other OSes 255.
8324e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#if defined(OS_CHROMEOS)
8334e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    limit = 143;
8344e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#else
8354e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    limit = 255;
8364e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#endif
8374e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  }
8384e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  size_t component_length = leveldb_dir.BaseName().value().length();
8394e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  if (component_length > static_cast<uint32_t>(limit)) {
8404e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    DLOG(WARNING) << "Path component length (" << component_length
8414e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                  << ") exceeds maximum (" << limit
8424e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                  << ") allowed by this filesystem.";
8434e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    const int min = 140;
8444e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    const int max = 300;
8454e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    const int num_buckets = 12;
8464e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    UMA_HISTOGRAM_CUSTOM_COUNTS(
8474e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)        "WebCore.IndexedDB.BackingStore.OverlyLargeOriginLength",
8484e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)        component_length,
8494e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)        min,
8504e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)        max,
8514e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)        num_buckets);
8524e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    return true;
8534e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  }
8544e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  return false;
8554e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)}
8564e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
857e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdochleveldb::Status IndexedDBBackingStore::DestroyBackingStore(
858e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    const base::FilePath& path_base,
859e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    const GURL& origin_url) {
860e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  const base::FilePath file_path =
861e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch      path_base.Append(ComputeFileName(origin_url));
862e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  DefaultLevelDBFactory leveldb_factory;
863e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  return leveldb_factory.DestroyLevelDB(file_path);
864e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch}
865e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch
866e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdochbool IndexedDBBackingStore::ReadCorruptionInfo(const base::FilePath& path_base,
867e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch                                               const GURL& origin_url,
8685f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                               std::string* message) {
869e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  const base::FilePath info_path =
870e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch      path_base.Append(ComputeCorruptionFileName(origin_url));
871e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch
872e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  if (IsPathTooLong(info_path))
873e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    return false;
874e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch
875e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  const int64 max_json_len = 4096;
876e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  int64 file_size(0);
877e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  if (!GetFileSize(info_path, &file_size) || file_size > max_json_len)
878e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    return false;
879e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  if (!file_size) {
880e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    NOTREACHED();
881e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    return false;
882e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  }
883e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch
884c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  base::File file(info_path, base::File::FLAG_OPEN | base::File::FLAG_READ);
885e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  bool success = false;
886c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  if (file.IsValid()) {
887e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    std::vector<char> bytes(file_size);
888c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    if (file_size == file.Read(0, &bytes[0], file_size)) {
889e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch      std::string input_js(&bytes[0], file_size);
890e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch      base::JSONReader reader;
891e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch      scoped_ptr<base::Value> val(reader.ReadToValue(input_js));
892e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch      if (val && val->GetType() == base::Value::TYPE_DICTIONARY) {
893e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch        base::DictionaryValue* dict_val =
894e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch            static_cast<base::DictionaryValue*>(val.get());
8955f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        success = dict_val->GetString("message", message);
896e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch      }
897e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    }
898c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    file.Close();
899e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  }
900e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch
901e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  base::DeleteFile(info_path, false);
902e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch
903e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  return success;
904e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch}
905e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch
906e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdochbool IndexedDBBackingStore::RecordCorruptionInfo(
907e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    const base::FilePath& path_base,
908e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    const GURL& origin_url,
909e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    const std::string& message) {
910e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  const base::FilePath info_path =
911e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch      path_base.Append(ComputeCorruptionFileName(origin_url));
912e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  if (IsPathTooLong(info_path))
913e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    return false;
914e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch
915e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  base::DictionaryValue root_dict;
916e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  root_dict.SetString("message", message);
917e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  std::string output_js;
918e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  base::JSONWriter::Write(&root_dict, &output_js);
919e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch
920c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  base::File file(info_path,
921c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch                  base::File::FLAG_CREATE_ALWAYS | base::File::FLAG_WRITE);
922c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  if (!file.IsValid())
923e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    return false;
924c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  int written = file.Write(0, output_js.c_str(), output_js.length());
925e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  return size_t(written) == output_js.length();
926e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch}
927e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch
9281e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)// static
929868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)scoped_refptr<IndexedDBBackingStore> IndexedDBBackingStore::Open(
930c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    IndexedDBFactory* indexed_db_factory,
9311e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    const GURL& origin_url,
932868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    const base::FilePath& path_base,
9335c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    net::URLRequestContext* request_context,
934f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    blink::WebIDBDataLoss* data_loss,
9350f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)    std::string* data_loss_message,
93668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    bool* is_disk_full,
937c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    LevelDBFactory* leveldb_factory,
9385f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    base::SequencedTaskRunner* task_runner,
939116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    bool clean_journal,
940116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    leveldb::Status* status) {
941eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  IDB_TRACE("IndexedDBBackingStore::Open");
942868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DCHECK(!path_base.empty());
943f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  *data_loss = blink::WebIDBDataLossNone;
9440f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)  *data_loss_message = "";
94568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  *is_disk_full = false;
946868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
947116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  *status = leveldb::Status::OK();
948116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
949868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  scoped_ptr<LevelDBComparator> comparator(new Comparator());
950868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
951010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  if (!base::IsStringASCII(path_base.AsUTF8Unsafe())) {
952f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    HistogramOpenStatus(INDEXED_DB_BACKING_STORE_OPEN_ATTEMPT_NON_ASCII,
953f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                        origin_url);
954868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
955a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  if (!base::CreateDirectory(path_base)) {
956116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    *status =
957116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch        leveldb::Status::IOError("Unable to create IndexedDB database path");
958116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    LOG(ERROR) << status->ToString() << ": \"" << path_base.AsUTF8Unsafe()
959116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch               << "\"";
960f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    HistogramOpenStatus(INDEXED_DB_BACKING_STORE_OPEN_FAILED_DIRECTORY,
961f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                        origin_url);
962868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return scoped_refptr<IndexedDBBackingStore>();
963868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
964868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
9651e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  const base::FilePath file_path =
9661e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      path_base.Append(ComputeFileName(origin_url));
9670529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  const base::FilePath blob_path =
9680529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch      path_base.Append(ComputeBlobPath(origin_url));
969eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
9704e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  if (IsPathTooLong(file_path)) {
971116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    *status = leveldb::Status::IOError("File path too long");
972f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    HistogramOpenStatus(INDEXED_DB_BACKING_STORE_OPEN_ORIGIN_TOO_LONG,
973f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                        origin_url);
974868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return scoped_refptr<IndexedDBBackingStore>();
975868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
976868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
977ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  scoped_ptr<LevelDBDatabase> db;
978116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  *status = leveldb_factory->OpenLevelDB(
97968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      file_path, comparator.get(), &db, is_disk_full);
98068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
981116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  DCHECK(!db == !status->ok());
982116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  if (!status->ok()) {
983116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    if (leveldb_env::IndicatesDiskFull(*status)) {
9840f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)      *is_disk_full = true;
985116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    } else if (leveldb_env::IsCorruption(*status)) {
986f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      *data_loss = blink::WebIDBDataLossTotal;
987116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      *data_loss_message = leveldb_env::GetCorruptionMessage(*status);
9880f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)    }
98968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  }
990868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
9910f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)  bool is_schema_known = false;
992868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (db) {
993e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    std::string corruption_message;
9945f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    if (ReadCorruptionInfo(path_base, origin_url, &corruption_message)) {
995e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch      LOG(ERROR) << "IndexedDB recovering from a corrupted (and deleted) "
996e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch                    "database.";
997e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch      HistogramOpenStatus(INDEXED_DB_BACKING_STORE_OPEN_FAILED_PRIOR_CORRUPTION,
998e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch                          origin_url);
999e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch      db.reset();
1000e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch      *data_loss = blink::WebIDBDataLossTotal;
1001e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch      *data_loss_message =
1002e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch          "IndexedDB (database was corrupt): " + corruption_message;
1003e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    } else if (!IsSchemaKnown(db.get(), &is_schema_known)) {
1004868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      LOG(ERROR) << "IndexedDB had IO error checking schema, treating it as "
1005868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                    "failure to open";
10064e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      HistogramOpenStatus(
1007f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)          INDEXED_DB_BACKING_STORE_OPEN_FAILED_IO_ERROR_CHECKING_SCHEMA,
1008f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)          origin_url);
1009868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      db.reset();
1010f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      *data_loss = blink::WebIDBDataLossTotal;
10110f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)      *data_loss_message = "I/O error checking schema";
10120f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)    } else if (!is_schema_known) {
1013868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      LOG(ERROR) << "IndexedDB backing store had unknown schema, treating it "
1014868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                    "as failure to open";
1015f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      HistogramOpenStatus(INDEXED_DB_BACKING_STORE_OPEN_FAILED_UNKNOWN_SCHEMA,
1016f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                          origin_url);
1017868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      db.reset();
1018f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      *data_loss = blink::WebIDBDataLossTotal;
10190f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)      *data_loss_message = "Unknown schema";
1020868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    }
1021868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
1022868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1023116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  DCHECK(status->ok() || !is_schema_known || leveldb_env::IsIOError(*status) ||
1024116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch         leveldb_env::IsCorruption(*status));
10250f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)
1026868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (db) {
1027f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    HistogramOpenStatus(INDEXED_DB_BACKING_STORE_OPEN_SUCCESS, origin_url);
1028116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  } else if (leveldb_env::IsIOError(*status)) {
102968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    LOG(ERROR) << "Unable to open backing store, not trying to recover - "
1030116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch               << status->ToString();
1031f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    HistogramOpenStatus(INDEXED_DB_BACKING_STORE_OPEN_NO_RECOVERY, origin_url);
1032ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    return scoped_refptr<IndexedDBBackingStore>();
1033868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  } else {
1034116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    DCHECK(!is_schema_known || leveldb_env::IsCorruption(*status));
1035868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    LOG(ERROR) << "IndexedDB backing store open failed, attempting cleanup";
1036116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    *status = leveldb_factory->DestroyLevelDB(file_path);
1037116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    if (!status->ok()) {
1038868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      LOG(ERROR) << "IndexedDB backing store cleanup failed";
1039f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      HistogramOpenStatus(INDEXED_DB_BACKING_STORE_OPEN_CLEANUP_DESTROY_FAILED,
1040f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                          origin_url);
1041868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      return scoped_refptr<IndexedDBBackingStore>();
1042868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    }
1043868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1044868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    LOG(ERROR) << "IndexedDB backing store cleanup succeeded, reopening";
1045ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    leveldb_factory->OpenLevelDB(file_path, comparator.get(), &db, NULL);
1046868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    if (!db) {
1047868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      LOG(ERROR) << "IndexedDB backing store reopen after recovery failed";
1048f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      HistogramOpenStatus(INDEXED_DB_BACKING_STORE_OPEN_CLEANUP_REOPEN_FAILED,
1049f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                          origin_url);
1050868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      return scoped_refptr<IndexedDBBackingStore>();
1051868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    }
1052f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    HistogramOpenStatus(INDEXED_DB_BACKING_STORE_OPEN_CLEANUP_REOPEN_SUCCESS,
1053f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                        origin_url);
1054868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
1055868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1056868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (!db) {
1057868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    NOTREACHED();
1058f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    HistogramOpenStatus(INDEXED_DB_BACKING_STORE_OPEN_FAILED_UNKNOWN_ERR,
1059f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                        origin_url);
1060868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return scoped_refptr<IndexedDBBackingStore>();
1061868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
1062868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1063cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  scoped_refptr<IndexedDBBackingStore> backing_store =
1064cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      Create(indexed_db_factory,
1065cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)             origin_url,
1066cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)             blob_path,
1067cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)             request_context,
1068cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)             db.Pass(),
1069cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)             comparator.Pass(),
1070116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch             task_runner,
1071116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch             status);
1072cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
10731320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (clean_journal && backing_store.get() &&
1074cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      !backing_store->CleanUpBlobJournal(LiveBlobJournalKey::Encode()).ok()) {
1075cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    HistogramOpenStatus(
1076cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        INDEXED_DB_BACKING_STORE_OPEN_FAILED_CLEANUP_JOURNAL_ERROR, origin_url);
1077cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    return scoped_refptr<IndexedDBBackingStore>();
1078cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  }
1079cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  return backing_store;
1080868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
1081868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
10821e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)// static
1083868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)scoped_refptr<IndexedDBBackingStore> IndexedDBBackingStore::OpenInMemory(
1084c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    const GURL& origin_url,
10855f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    base::SequencedTaskRunner* task_runner,
1086116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    leveldb::Status* status) {
1087868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DefaultLevelDBFactory leveldb_factory;
1088c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  return IndexedDBBackingStore::OpenInMemory(
1089116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      origin_url, &leveldb_factory, task_runner, status);
1090868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
1091868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
10921e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)// static
1093868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)scoped_refptr<IndexedDBBackingStore> IndexedDBBackingStore::OpenInMemory(
10941e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    const GURL& origin_url,
1095c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    LevelDBFactory* leveldb_factory,
10965f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    base::SequencedTaskRunner* task_runner,
1097116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    leveldb::Status* status) {
1098eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  IDB_TRACE("IndexedDBBackingStore::OpenInMemory");
1099868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1100868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  scoped_ptr<LevelDBComparator> comparator(new Comparator());
1101868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  scoped_ptr<LevelDBDatabase> db =
1102868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      LevelDBDatabase::OpenInMemory(comparator.get());
1103868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (!db) {
1104eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    LOG(ERROR) << "LevelDBDatabase::OpenInMemory failed.";
1105f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    HistogramOpenStatus(INDEXED_DB_BACKING_STORE_OPEN_MEMORY_FAILED,
1106f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                        origin_url);
1107868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return scoped_refptr<IndexedDBBackingStore>();
1108868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
1109f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  HistogramOpenStatus(INDEXED_DB_BACKING_STORE_OPEN_MEMORY_SUCCESS, origin_url);
1110868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1111c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  return Create(NULL /* indexed_db_factory */,
1112c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch                origin_url,
11130529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch                base::FilePath(),
11145c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu                NULL /* request_context */,
1115c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch                db.Pass(),
1116c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch                comparator.Pass(),
1117116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                task_runner,
1118116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                status);
1119868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
1120868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
11211e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)// static
1122868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)scoped_refptr<IndexedDBBackingStore> IndexedDBBackingStore::Create(
1123c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    IndexedDBFactory* indexed_db_factory,
11241e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    const GURL& origin_url,
11250529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    const base::FilePath& blob_path,
11265c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    net::URLRequestContext* request_context,
1127868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    scoped_ptr<LevelDBDatabase> db,
1128c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    scoped_ptr<LevelDBComparator> comparator,
11295f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    base::SequencedTaskRunner* task_runner,
1130116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    leveldb::Status* status) {
1131868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // TODO(jsbell): Handle comparator name changes.
11321e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  scoped_refptr<IndexedDBBackingStore> backing_store(
1133c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      new IndexedDBBackingStore(indexed_db_factory,
1134c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch                                origin_url,
11350529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch                                blob_path,
11365c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu                                request_context,
1137c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch                                db.Pass(),
1138c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch                                comparator.Pass(),
1139c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch                                task_runner));
1140116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  *status = backing_store->SetUpMetadata();
1141116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  if (!status->ok())
1142868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return scoped_refptr<IndexedDBBackingStore>();
1143868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1144868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  return backing_store;
1145868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
1146868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
11470529e5d033099cbfc42635f6f6183833b09dff6eBen Murdochvoid IndexedDBBackingStore::GrantChildProcessPermissions(int child_process_id) {
11480529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  if (!child_process_ids_granted_.count(child_process_id)) {
11490529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    child_process_ids_granted_.insert(child_process_id);
11500529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    ChildProcessSecurityPolicyImpl::GetInstance()->GrantReadFile(
11510529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch        child_process_id, blob_path_);
11520529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  }
11530529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch}
11540529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch
11550529e5d033099cbfc42635f6f6183833b09dff6eBen Murdochstd::vector<base::string16> IndexedDBBackingStore::GetDatabaseNames(
11560529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    leveldb::Status* s) {
11570529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  *s = leveldb::Status::OK();
1158a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  std::vector<base::string16> found_names;
11597dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  const std::string start_key =
11601e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      DatabaseNameKey::EncodeMinKeyForOrigin(origin_identifier_);
11617dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  const std::string stop_key =
11621e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      DatabaseNameKey::EncodeStopKeyForOrigin(origin_identifier_);
1163868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1164868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DCHECK(found_names.empty());
1165868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1166868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  scoped_ptr<LevelDBIterator> it = db_->CreateIterator();
11670529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  for (*s = it->Seek(start_key);
11680529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch       s->ok() && it->IsValid() && CompareKeys(it->Key(), stop_key) < 0;
11690529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch       *s = it->Next()) {
11706e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    // Decode database name (in iterator key).
1171ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    StringPiece slice(it->Key());
1172868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    DatabaseNameKey database_name_key;
1173cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    if (!DatabaseNameKey::Decode(&slice, &database_name_key) ||
1174cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        !slice.empty()) {
1175e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch      INTERNAL_CONSISTENCY_ERROR_UNTESTED(GET_DATABASE_NAMES);
1176ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch      continue;
1177ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    }
11786e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
11796e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    // Decode database id (in iterator value).
11806e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    int64 database_id = 0;
11816e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    StringPiece valueSlice(it->Value());
11821320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    if (!DecodeInt(&valueSlice, &database_id) || !valueSlice.empty()) {
11836e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      INTERNAL_CONSISTENCY_ERROR_UNTESTED(GET_DATABASE_NAMES);
11846e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      continue;
11856e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    }
11866e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
11876e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    // Look up version by id.
11886e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    bool found = false;
11896e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    int64 database_version = IndexedDBDatabaseMetadata::DEFAULT_INT_VERSION;
11906e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    *s = GetVarInt(db_.get(),
11916e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)                   DatabaseMetaDataKey::Encode(
11926e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)                       database_id, DatabaseMetaDataKey::USER_INT_VERSION),
11936e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)                   &database_version,
11946e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)                   &found);
11956e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    if (!s->ok() || !found) {
11966e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      INTERNAL_READ_ERROR_UNTESTED(GET_DATABASE_NAMES);
11976e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      continue;
11986e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    }
11996e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
12006e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    // Ignore stale metadata from failed initial opens.
12016e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    if (database_version != IndexedDBDatabaseMetadata::DEFAULT_INT_VERSION)
12026e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      found_names.push_back(database_name_key.database_name());
1203868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
12040529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch
12050529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  if (!s->ok())
1206116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    INTERNAL_READ_ERROR(GET_DATABASE_NAMES);
12070529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch
1208868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  return found_names;
1209868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
1210868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1211a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)leveldb::Status IndexedDBBackingStore::GetIDBDatabaseMetaData(
1212a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    const base::string16& name,
1213868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    IndexedDBDatabaseMetadata* metadata,
1214868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    bool* found) {
12151e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  const std::string key = DatabaseNameKey::Encode(origin_identifier_, name);
1216868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  *found = false;
1217868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1218a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  leveldb::Status s = GetInt(db_.get(), key, &metadata->id, found);
1219a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  if (!s.ok()) {
12200529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    INTERNAL_READ_ERROR(GET_IDBDATABASE_METADATA);
1221a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    return s;
1222868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
1223868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (!*found)
1224a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    return leveldb::Status::OK();
1225a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
1226a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  s = GetString(db_.get(),
1227a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                DatabaseMetaDataKey::Encode(metadata->id,
1228a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                                            DatabaseMetaDataKey::USER_VERSION),
1229a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                &metadata->version,
1230a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                found);
1231a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  if (!s.ok()) {
1232e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    INTERNAL_READ_ERROR_UNTESTED(GET_IDBDATABASE_METADATA);
1233a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    return s;
1234868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
1235868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (!*found) {
1236e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    INTERNAL_CONSISTENCY_ERROR_UNTESTED(GET_IDBDATABASE_METADATA);
1237a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    return InternalInconsistencyStatus();
1238868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
1239868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1240a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  s = GetVarInt(db_.get(),
1241a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                DatabaseMetaDataKey::Encode(
1242a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                    metadata->id, DatabaseMetaDataKey::USER_INT_VERSION),
1243a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                &metadata->int_version,
1244a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                found);
1245a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  if (!s.ok()) {
1246e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    INTERNAL_READ_ERROR_UNTESTED(GET_IDBDATABASE_METADATA);
1247a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    return s;
1248868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
1249868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (!*found) {
1250e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    INTERNAL_CONSISTENCY_ERROR_UNTESTED(GET_IDBDATABASE_METADATA);
1251a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    return InternalInconsistencyStatus();
1252868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
1253868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1254868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (metadata->int_version == IndexedDBDatabaseMetadata::DEFAULT_INT_VERSION)
1255868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    metadata->int_version = IndexedDBDatabaseMetadata::NO_INT_VERSION;
1256868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1257a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  s = GetMaxObjectStoreId(
1258868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      db_.get(), metadata->id, &metadata->max_object_store_id);
1259a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  if (!s.ok()) {
1260e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    INTERNAL_READ_ERROR_UNTESTED(GET_IDBDATABASE_METADATA);
1261868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
1262868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1263cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // We don't cache this, we just check it if it's there.
1264cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  int64 blob_key_generator_current_number =
1265cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      DatabaseMetaDataKey::kInvalidBlobKey;
1266cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
1267cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  s = GetVarInt(
1268cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      db_.get(),
1269cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      DatabaseMetaDataKey::Encode(
1270cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)          metadata->id, DatabaseMetaDataKey::BLOB_KEY_GENERATOR_CURRENT_NUMBER),
1271cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      &blob_key_generator_current_number,
1272cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      found);
1273cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (!s.ok()) {
1274cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    INTERNAL_READ_ERROR_UNTESTED(GET_IDBDATABASE_METADATA);
1275cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    return s;
1276cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  }
1277cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (!*found) {
1278cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    // This database predates blob support.
1279cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    *found = true;
1280cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  } else if (!DatabaseMetaDataKey::IsValidBlobKey(
1281cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                 blob_key_generator_current_number)) {
1282cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    INTERNAL_CONSISTENCY_ERROR_UNTESTED(GET_IDBDATABASE_METADATA);
1283cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    return InternalInconsistencyStatus();
1284cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  }
1285cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
1286a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  return s;
1287868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
1288868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1289a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)WARN_UNUSED_RESULT static leveldb::Status GetNewDatabaseId(
1290a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    LevelDBTransaction* transaction,
1291a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    int64* new_id) {
1292868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  *new_id = -1;
1293868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  int64 max_database_id = -1;
1294868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  bool found = false;
1295a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  leveldb::Status s =
12961e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      GetInt(transaction, MaxDatabaseIdKey::Encode(), &max_database_id, &found);
1297a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  if (!s.ok()) {
1298e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    INTERNAL_READ_ERROR_UNTESTED(GET_NEW_DATABASE_ID);
1299a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    return s;
1300868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
1301868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (!found)
1302868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    max_database_id = 0;
1303868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1304868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DCHECK_GE(max_database_id, 0);
1305868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1306868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  int64 database_id = max_database_id + 1;
13074e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  PutInt(transaction, MaxDatabaseIdKey::Encode(), database_id);
1308868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  *new_id = database_id;
1309a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  return leveldb::Status::OK();
1310868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
1311868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1312a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)leveldb::Status IndexedDBBackingStore::CreateIDBDatabaseMetaData(
1313a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    const base::string16& name,
1314a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    const base::string16& version,
1315a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    int64 int_version,
1316a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    int64* row_id) {
13176e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  // TODO(jsbell): Don't persist metadata if open fails. http://crbug.com/395472
13184e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  scoped_refptr<LevelDBTransaction> transaction =
1319f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      IndexedDBClassFactory::Get()->CreateLevelDBTransaction(db_.get());
13204e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
1321a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  leveldb::Status s = GetNewDatabaseId(transaction.get(), row_id);
1322a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  if (!s.ok())
1323a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    return s;
1324868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DCHECK_GE(*row_id, 0);
1325868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1326868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (int_version == IndexedDBDatabaseMetadata::NO_INT_VERSION)
1327868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    int_version = IndexedDBDatabaseMetadata::DEFAULT_INT_VERSION;
1328868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
13291e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  PutInt(transaction.get(),
13301e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)         DatabaseNameKey::Encode(origin_identifier_, name),
13311e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)         *row_id);
13327dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  PutString(
13337dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      transaction.get(),
13347dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      DatabaseMetaDataKey::Encode(*row_id, DatabaseMetaDataKey::USER_VERSION),
13357dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      version);
1336868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  PutVarInt(transaction.get(),
13377dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch            DatabaseMetaDataKey::Encode(*row_id,
13387dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch                                        DatabaseMetaDataKey::USER_INT_VERSION),
1339868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)            int_version);
1340cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  PutVarInt(
1341cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      transaction.get(),
1342cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      DatabaseMetaDataKey::Encode(
1343cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)          *row_id, DatabaseMetaDataKey::BLOB_KEY_GENERATOR_CURRENT_NUMBER),
1344cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      DatabaseMetaDataKey::kBlobKeyGeneratorInitialNumber);
1345cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
1346a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  s = transaction->Commit();
1347a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  if (!s.ok())
1348e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    INTERNAL_WRITE_ERROR_UNTESTED(CREATE_IDBDATABASE_METADATA);
1349a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  return s;
1350868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
1351868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1352868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)bool IndexedDBBackingStore::UpdateIDBDatabaseIntVersion(
1353868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    IndexedDBBackingStore::Transaction* transaction,
1354868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    int64 row_id,
1355868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    int64 int_version) {
1356868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (int_version == IndexedDBDatabaseMetadata::NO_INT_VERSION)
1357868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    int_version = IndexedDBDatabaseMetadata::DEFAULT_INT_VERSION;
1358868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DCHECK_GE(int_version, 0) << "int_version was " << int_version;
13594e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  PutVarInt(transaction->transaction(),
13607dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch            DatabaseMetaDataKey::Encode(row_id,
13617dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch                                        DatabaseMetaDataKey::USER_INT_VERSION),
1362868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)            int_version);
1363868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  return true;
1364868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
1365868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
136646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)// If you're deleting a range that contains user keys that have blob info, this
136746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)// won't clean up the blobs.
136846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)static leveldb::Status DeleteRangeBasic(LevelDBTransaction* transaction,
136946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)                                        const std::string& begin,
137046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)                                        const std::string& end,
137146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)                                        bool upper_open) {
1372868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  scoped_ptr<LevelDBIterator> it = transaction->CreateIterator();
13730529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  leveldb::Status s;
137446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  for (s = it->Seek(begin); s.ok() && it->IsValid() &&
137546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)                                (upper_open ? CompareKeys(it->Key(), end) < 0
137646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)                                            : CompareKeys(it->Key(), end) <= 0);
13770529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch       s = it->Next())
1378868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    transaction->Remove(it->Key());
13790529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  return s;
1380868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
1381868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
138246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)static leveldb::Status DeleteBlobsInRange(
1383cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    IndexedDBBackingStore::Transaction* transaction,
1384cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    int64 database_id,
138546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    int64 object_store_id,
138646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    const std::string& start_key,
138746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    const std::string& end_key,
138846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    bool upper_open) {
1389cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  scoped_ptr<LevelDBIterator> it = transaction->transaction()->CreateIterator();
1390cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  leveldb::Status s = it->Seek(start_key);
139146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  for (; s.ok() && it->IsValid() &&
139246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)             (upper_open ? CompareKeys(it->Key(), end_key) < 0
139346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)                         : CompareKeys(it->Key(), end_key) <= 0);
1394cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)       s = it->Next()) {
1395cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    StringPiece key_piece(it->Key());
1396cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    std::string user_key =
1397cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        BlobEntryKey::ReencodeToObjectStoreDataKey(&key_piece);
1398cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    if (!user_key.size()) {
1399cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      INTERNAL_CONSISTENCY_ERROR_UNTESTED(GET_IDBDATABASE_METADATA);
1400cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      return InternalInconsistencyStatus();
1401cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    }
1402cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    transaction->PutBlobInfo(
1403cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        database_id, object_store_id, user_key, NULL, NULL);
1404cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  }
1405cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  return s;
1406cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
1407cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
140846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)static leveldb::Status DeleteBlobsInObjectStore(
140946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    IndexedDBBackingStore::Transaction* transaction,
141046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    int64 database_id,
141146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    int64 object_store_id) {
141246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  std::string start_key, stop_key;
141346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  start_key =
141446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      BlobEntryKey::EncodeMinKeyForObjectStore(database_id, object_store_id);
141546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  stop_key =
141646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      BlobEntryKey::EncodeStopKeyForObjectStore(database_id, object_store_id);
141746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  return DeleteBlobsInRange(
141846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      transaction, database_id, object_store_id, start_key, stop_key, true);
141946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)}
142046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
1421a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)leveldb::Status IndexedDBBackingStore::DeleteDatabase(
1422a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    const base::string16& name) {
1423eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  IDB_TRACE("IndexedDBBackingStore::DeleteDatabase");
1424a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  scoped_ptr<LevelDBDirectTransaction> transaction =
1425a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      LevelDBDirectTransaction::Create(db_.get());
1426868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1427cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  leveldb::Status s;
1428cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  s = CleanUpBlobJournal(BlobJournalKey::Encode());
1429cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (!s.ok())
1430cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    return s;
1431cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
1432868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  IndexedDBDatabaseMetadata metadata;
1433868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  bool success = false;
1434cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  s = GetIDBDatabaseMetaData(name, &metadata, &success);
1435a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  if (!s.ok())
1436a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    return s;
1437868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (!success)
1438a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    return leveldb::Status::OK();
1439868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
14407dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  const std::string start_key = DatabaseMetaDataKey::Encode(
1441868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      metadata.id, DatabaseMetaDataKey::ORIGIN_NAME);
14427dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  const std::string stop_key = DatabaseMetaDataKey::Encode(
1443868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      metadata.id + 1, DatabaseMetaDataKey::ORIGIN_NAME);
1444868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  scoped_ptr<LevelDBIterator> it = db_->CreateIterator();
14450529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  for (s = it->Seek(start_key);
14460529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch       s.ok() && it->IsValid() && CompareKeys(it->Key(), stop_key) < 0;
14470529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch       s = it->Next())
1448868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    transaction->Remove(it->Key());
14490529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  if (!s.ok()) {
14500529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    INTERNAL_WRITE_ERROR_UNTESTED(DELETE_DATABASE);
14510529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    return s;
14520529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  }
1453868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
14541e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  const std::string key = DatabaseNameKey::Encode(origin_identifier_, name);
14557dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  transaction->Remove(key);
1456868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1457cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  bool need_cleanup = false;
1458cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (active_blob_registry()->MarkDeletedCheckIfUsed(
1459cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)          metadata.id, DatabaseMetaDataKey::kAllBlobsKey)) {
1460cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    s = MergeDatabaseIntoLiveBlobJournal(transaction.get(), metadata.id);
1461cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    if (!s.ok())
1462cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      return s;
1463cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  } else {
1464cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    UpdateBlobJournalWithDatabase(transaction.get(), metadata.id);
1465cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    need_cleanup = true;
1466cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  }
1467cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
1468a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  s = transaction->Commit();
1469a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  if (!s.ok()) {
1470e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    INTERNAL_WRITE_ERROR_UNTESTED(DELETE_DATABASE);
1471a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    return s;
1472868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
1473cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
1474cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (need_cleanup)
1475cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    CleanUpBlobJournal(BlobJournalKey::Encode());
1476cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
14775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  db_->Compact(start_key, stop_key);
1478a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  return s;
1479868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
1480868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1481868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)static bool CheckObjectStoreAndMetaDataType(const LevelDBIterator* it,
14827dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch                                            const std::string& stop_key,
1483868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                            int64 object_store_id,
1484868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                            int64 meta_data_type) {
14857dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if (!it->IsValid() || CompareKeys(it->Key(), stop_key) >= 0)
1486868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return false;
1487868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1488ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  StringPiece slice(it->Key());
1489868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  ObjectStoreMetaDataKey meta_data_key;
149046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  bool ok =
149146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      ObjectStoreMetaDataKey::Decode(&slice, &meta_data_key) && slice.empty();
1492ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  DCHECK(ok);
1493868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (meta_data_key.ObjectStoreId() != object_store_id)
1494868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return false;
1495868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (meta_data_key.MetaDataType() != meta_data_type)
1496868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return false;
149746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  return ok;
1498868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
1499868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1500868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)// TODO(jsbell): This should do some error handling rather than
1501868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)// plowing ahead when bad data is encountered.
1502a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)leveldb::Status IndexedDBBackingStore::GetObjectStores(
1503868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    int64 database_id,
1504868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    IndexedDBDatabaseMetadata::ObjectStoreMap* object_stores) {
1505eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  IDB_TRACE("IndexedDBBackingStore::GetObjectStores");
1506868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (!KeyPrefix::IsValidDatabaseId(database_id))
1507a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    return InvalidDBKeyStatus();
15087dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  const std::string start_key =
1509868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      ObjectStoreMetaDataKey::Encode(database_id, 1, 0);
15107dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  const std::string stop_key =
1511868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      ObjectStoreMetaDataKey::EncodeMaxKey(database_id);
1512868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1513868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DCHECK(object_stores->empty());
1514868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1515868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  scoped_ptr<LevelDBIterator> it = db_->CreateIterator();
15160529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  leveldb::Status s = it->Seek(start_key);
15170529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  while (s.ok() && it->IsValid() && CompareKeys(it->Key(), stop_key) < 0) {
1518ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    StringPiece slice(it->Key());
1519868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    ObjectStoreMetaDataKey meta_data_key;
1520cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    bool ok =
1521cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        ObjectStoreMetaDataKey::Decode(&slice, &meta_data_key) && slice.empty();
1522ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    DCHECK(ok);
1523cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    if (!ok || meta_data_key.MetaDataType() != ObjectStoreMetaDataKey::NAME) {
1524e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch      INTERNAL_CONSISTENCY_ERROR_UNTESTED(GET_OBJECT_STORES);
1525868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      // Possible stale metadata, but don't fail the load.
15260529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch      s = it->Next();
15270529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch      if (!s.ok())
15280529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch        break;
1529868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      continue;
1530868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    }
1531868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1532868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    int64 object_store_id = meta_data_key.ObjectStoreId();
1533868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1534868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    // TODO(jsbell): Do this by direct key lookup rather than iteration, to
1535868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    // simplify.
1536a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    base::string16 object_store_name;
1537868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    {
15387dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      StringPiece slice(it->Value());
1539868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      if (!DecodeString(&slice, &object_store_name) || !slice.empty())
1540e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch        INTERNAL_CONSISTENCY_ERROR_UNTESTED(GET_OBJECT_STORES);
1541868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    }
1542868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
15430529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    s = it->Next();
15440529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    if (!s.ok())
15450529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch      break;
1546868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    if (!CheckObjectStoreAndMetaDataType(it.get(),
1547868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                         stop_key,
1548868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                         object_store_id,
1549868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                         ObjectStoreMetaDataKey::KEY_PATH)) {
1550e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch      INTERNAL_CONSISTENCY_ERROR_UNTESTED(GET_OBJECT_STORES);
1551868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      break;
1552868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    }
1553868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    IndexedDBKeyPath key_path;
1554868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    {
15557dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      StringPiece slice(it->Value());
1556868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      if (!DecodeIDBKeyPath(&slice, &key_path) || !slice.empty())
1557e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch        INTERNAL_CONSISTENCY_ERROR_UNTESTED(GET_OBJECT_STORES);
1558868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    }
1559868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
15600529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    s = it->Next();
15610529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    if (!s.ok())
15620529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch      break;
1563868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    if (!CheckObjectStoreAndMetaDataType(
1564424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)             it.get(),
1565424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)             stop_key,
1566424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)             object_store_id,
1567424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)             ObjectStoreMetaDataKey::AUTO_INCREMENT)) {
1568e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch      INTERNAL_CONSISTENCY_ERROR_UNTESTED(GET_OBJECT_STORES);
1569868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      break;
1570868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    }
1571868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    bool auto_increment;
1572868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    {
15737dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      StringPiece slice(it->Value());
1574868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      if (!DecodeBool(&slice, &auto_increment) || !slice.empty())
1575e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch        INTERNAL_CONSISTENCY_ERROR_UNTESTED(GET_OBJECT_STORES);
1576868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    }
1577868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
15780529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    s = it->Next();  // Is evictable.
15790529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    if (!s.ok())
15800529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch      break;
1581868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    if (!CheckObjectStoreAndMetaDataType(it.get(),
1582868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                         stop_key,
1583868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                         object_store_id,
1584868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                         ObjectStoreMetaDataKey::EVICTABLE)) {
1585e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch      INTERNAL_CONSISTENCY_ERROR_UNTESTED(GET_OBJECT_STORES);
1586868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      break;
1587868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    }
1588868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
15890529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    s = it->Next();  // Last version.
15900529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    if (!s.ok())
15910529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch      break;
1592868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    if (!CheckObjectStoreAndMetaDataType(
1593424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)             it.get(),
1594424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)             stop_key,
1595424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)             object_store_id,
1596424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)             ObjectStoreMetaDataKey::LAST_VERSION)) {
1597e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch      INTERNAL_CONSISTENCY_ERROR_UNTESTED(GET_OBJECT_STORES);
1598868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      break;
1599868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    }
1600868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
16010529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    s = it->Next();  // Maximum index id allocated.
16020529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    if (!s.ok())
16030529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch      break;
1604868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    if (!CheckObjectStoreAndMetaDataType(
1605424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)             it.get(),
1606424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)             stop_key,
1607424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)             object_store_id,
1608424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)             ObjectStoreMetaDataKey::MAX_INDEX_ID)) {
1609e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch      INTERNAL_CONSISTENCY_ERROR_UNTESTED(GET_OBJECT_STORES);
1610868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      break;
1611868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    }
1612868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    int64 max_index_id;
1613868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    {
16147dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      StringPiece slice(it->Value());
1615868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      if (!DecodeInt(&slice, &max_index_id) || !slice.empty())
1616e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch        INTERNAL_CONSISTENCY_ERROR_UNTESTED(GET_OBJECT_STORES);
1617868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    }
1618868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
16190529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    s = it->Next();  // [optional] has key path (is not null)
16200529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    if (!s.ok())
16210529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch      break;
1622868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    if (CheckObjectStoreAndMetaDataType(it.get(),
1623868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                        stop_key,
1624868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                        object_store_id,
1625868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                        ObjectStoreMetaDataKey::HAS_KEY_PATH)) {
1626868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      bool has_key_path;
1627868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      {
16287dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch        StringPiece slice(it->Value());
1629868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        if (!DecodeBool(&slice, &has_key_path))
1630e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch          INTERNAL_CONSISTENCY_ERROR_UNTESTED(GET_OBJECT_STORES);
1631868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      }
1632868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      // This check accounts for two layers of legacy coding:
1633868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      // (1) Initially, has_key_path was added to distinguish null vs. string.
1634868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      // (2) Later, null vs. string vs. array was stored in the key_path itself.
1635868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      // So this check is only relevant for string-type key_paths.
1636868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      if (!has_key_path &&
1637f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)          (key_path.type() == blink::WebIDBKeyPathTypeString &&
1638868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)           !key_path.string().empty())) {
1639e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch        INTERNAL_CONSISTENCY_ERROR_UNTESTED(GET_OBJECT_STORES);
1640868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        break;
1641868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      }
1642868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      if (!has_key_path)
1643868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        key_path = IndexedDBKeyPath();
16440529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch      s = it->Next();
16450529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch      if (!s.ok())
16460529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch        break;
1647868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    }
1648868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1649868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    int64 key_generator_current_number = -1;
1650868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    if (CheckObjectStoreAndMetaDataType(
1651868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)            it.get(),
1652868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)            stop_key,
1653868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)            object_store_id,
1654868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)            ObjectStoreMetaDataKey::KEY_GENERATOR_CURRENT_NUMBER)) {
16557dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      StringPiece slice(it->Value());
1656868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      if (!DecodeInt(&slice, &key_generator_current_number) || !slice.empty())
1657e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch        INTERNAL_CONSISTENCY_ERROR_UNTESTED(GET_OBJECT_STORES);
1658868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1659868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      // TODO(jsbell): Return key_generator_current_number, cache in
1660868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      // object store, and write lazily to backing store.  For now,
1661868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      // just assert that if it was written it was valid.
1662868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      DCHECK_GE(key_generator_current_number, kKeyGeneratorInitialNumber);
16630529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch      s = it->Next();
16640529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch      if (!s.ok())
16650529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch        break;
1666868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    }
1667868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1668868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    IndexedDBObjectStoreMetadata metadata(object_store_name,
1669868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                          object_store_id,
1670868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                          key_path,
1671868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                          auto_increment,
1672868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                          max_index_id);
16730529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    s = GetIndexes(database_id, object_store_id, &metadata.indexes);
1674a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    if (!s.ok())
16750529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch      break;
1676868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    (*object_stores)[object_store_id] = metadata;
1677868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
16780529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch
16790529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  if (!s.ok())
16800529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    INTERNAL_READ_ERROR_UNTESTED(GET_OBJECT_STORES);
16810529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch
16820529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  return s;
1683868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
1684868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1685a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)WARN_UNUSED_RESULT static leveldb::Status SetMaxObjectStoreId(
1686868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    LevelDBTransaction* transaction,
1687868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    int64 database_id,
1688868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    int64 object_store_id) {
16897dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  const std::string max_object_store_id_key = DatabaseMetaDataKey::Encode(
1690868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      database_id, DatabaseMetaDataKey::MAX_OBJECT_STORE_ID);
1691868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  int64 max_object_store_id = -1;
1692a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  leveldb::Status s = GetMaxObjectStoreId(
1693868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      transaction, max_object_store_id_key, &max_object_store_id);
1694a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  if (!s.ok()) {
1695e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    INTERNAL_READ_ERROR_UNTESTED(SET_MAX_OBJECT_STORE_ID);
1696a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    return s;
1697868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
1698868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1699868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (object_store_id <= max_object_store_id) {
1700e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    INTERNAL_CONSISTENCY_ERROR_UNTESTED(SET_MAX_OBJECT_STORE_ID);
1701a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    return InternalInconsistencyStatus();
1702868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
17037dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  PutInt(transaction, max_object_store_id_key, object_store_id);
1704a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  return s;
1705868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
1706868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1707e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdochvoid IndexedDBBackingStore::Compact() { db_->CompactAll(); }
1708e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch
1709a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)leveldb::Status IndexedDBBackingStore::CreateObjectStore(
1710868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    IndexedDBBackingStore::Transaction* transaction,
1711868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    int64 database_id,
1712868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    int64 object_store_id,
1713a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    const base::string16& name,
1714868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    const IndexedDBKeyPath& key_path,
1715868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    bool auto_increment) {
1716eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  IDB_TRACE("IndexedDBBackingStore::CreateObjectStore");
1717868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (!KeyPrefix::ValidIds(database_id, object_store_id))
1718a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    return InvalidDBKeyStatus();
17194e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  LevelDBTransaction* leveldb_transaction = transaction->transaction();
1720a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  leveldb::Status s =
1721a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      SetMaxObjectStoreId(leveldb_transaction, database_id, object_store_id);
1722a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  if (!s.ok())
1723a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    return s;
1724868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
17257dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  const std::string name_key = ObjectStoreMetaDataKey::Encode(
1726868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      database_id, object_store_id, ObjectStoreMetaDataKey::NAME);
17277dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  const std::string key_path_key = ObjectStoreMetaDataKey::Encode(
1728868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      database_id, object_store_id, ObjectStoreMetaDataKey::KEY_PATH);
17297dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  const std::string auto_increment_key = ObjectStoreMetaDataKey::Encode(
1730868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      database_id, object_store_id, ObjectStoreMetaDataKey::AUTO_INCREMENT);
17317dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  const std::string evictable_key = ObjectStoreMetaDataKey::Encode(
1732868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      database_id, object_store_id, ObjectStoreMetaDataKey::EVICTABLE);
17337dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  const std::string last_version_key = ObjectStoreMetaDataKey::Encode(
1734868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      database_id, object_store_id, ObjectStoreMetaDataKey::LAST_VERSION);
17357dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  const std::string max_index_id_key = ObjectStoreMetaDataKey::Encode(
1736868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      database_id, object_store_id, ObjectStoreMetaDataKey::MAX_INDEX_ID);
17377dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  const std::string has_key_path_key = ObjectStoreMetaDataKey::Encode(
1738868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      database_id, object_store_id, ObjectStoreMetaDataKey::HAS_KEY_PATH);
17397dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  const std::string key_generator_current_number_key =
1740868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      ObjectStoreMetaDataKey::Encode(
1741868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)          database_id,
1742868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)          object_store_id,
1743868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)          ObjectStoreMetaDataKey::KEY_GENERATOR_CURRENT_NUMBER);
17447dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  const std::string names_key = ObjectStoreNamesKey::Encode(database_id, name);
17457dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
17467dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  PutString(leveldb_transaction, name_key, name);
17477dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  PutIDBKeyPath(leveldb_transaction, key_path_key, key_path);
17487dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  PutInt(leveldb_transaction, auto_increment_key, auto_increment);
17497dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  PutInt(leveldb_transaction, evictable_key, false);
17507dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  PutInt(leveldb_transaction, last_version_key, 1);
17517dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  PutInt(leveldb_transaction, max_index_id_key, kMinimumIndexId);
17527dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  PutBool(leveldb_transaction, has_key_path_key, !key_path.IsNull());
1753868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  PutInt(leveldb_transaction,
17547dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch         key_generator_current_number_key,
1755868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)         kKeyGeneratorInitialNumber);
17567dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  PutInt(leveldb_transaction, names_key, object_store_id);
1757a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  return s;
1758868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
1759868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1760a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)leveldb::Status IndexedDBBackingStore::DeleteObjectStore(
1761868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    IndexedDBBackingStore::Transaction* transaction,
1762868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    int64 database_id,
1763868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    int64 object_store_id) {
1764eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  IDB_TRACE("IndexedDBBackingStore::DeleteObjectStore");
1765868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (!KeyPrefix::ValidIds(database_id, object_store_id))
1766a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    return InvalidDBKeyStatus();
17674e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  LevelDBTransaction* leveldb_transaction = transaction->transaction();
1768868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1769a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  base::string16 object_store_name;
1770868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  bool found = false;
1771a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  leveldb::Status s =
1772a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      GetString(leveldb_transaction,
1773a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                ObjectStoreMetaDataKey::Encode(
1774a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                    database_id, object_store_id, ObjectStoreMetaDataKey::NAME),
1775a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                &object_store_name,
1776a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                &found);
1777a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  if (!s.ok()) {
1778e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    INTERNAL_READ_ERROR_UNTESTED(DELETE_OBJECT_STORE);
1779a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    return s;
1780868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
1781868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (!found) {
1782e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    INTERNAL_CONSISTENCY_ERROR_UNTESTED(DELETE_OBJECT_STORE);
1783a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    return InternalInconsistencyStatus();
1784868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
1785868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1786cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  s = DeleteBlobsInObjectStore(transaction, database_id, object_store_id);
1787cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (!s.ok()) {
1788cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    INTERNAL_CONSISTENCY_ERROR_UNTESTED(DELETE_OBJECT_STORE);
1789cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    return s;
1790cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  }
1791cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
179246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  s = DeleteRangeBasic(
1793868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      leveldb_transaction,
1794868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      ObjectStoreMetaDataKey::Encode(database_id, object_store_id, 0),
179546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      ObjectStoreMetaDataKey::EncodeMaxKey(database_id, object_store_id),
179646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      true);
1797868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
17980529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  if (s.ok()) {
17990529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    leveldb_transaction->Remove(
18000529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch        ObjectStoreNamesKey::Encode(database_id, object_store_name));
1801868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
180246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    s = DeleteRangeBasic(
18030529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch        leveldb_transaction,
18040529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch        IndexFreeListKey::Encode(database_id, object_store_id, 0),
180546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)        IndexFreeListKey::EncodeMaxKey(database_id, object_store_id),
180646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)        true);
18070529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  }
18080529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch
18090529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  if (s.ok()) {
181046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    s = DeleteRangeBasic(
18110529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch        leveldb_transaction,
18120529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch        IndexMetaDataKey::Encode(database_id, object_store_id, 0, 0),
181346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)        IndexMetaDataKey::EncodeMaxKey(database_id, object_store_id),
181446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)        true);
18150529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  }
18160529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch
18170529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  if (!s.ok()) {
18180529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    INTERNAL_WRITE_ERROR_UNTESTED(DELETE_OBJECT_STORE);
18190529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    return s;
18200529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  }
1821868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1822868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  return ClearObjectStore(transaction, database_id, object_store_id);
1823868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
1824868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1825a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)leveldb::Status IndexedDBBackingStore::GetRecord(
1826868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    IndexedDBBackingStore::Transaction* transaction,
1827868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    int64 database_id,
1828868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    int64 object_store_id,
1829868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    const IndexedDBKey& key,
183023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    IndexedDBValue* record) {
1831eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  IDB_TRACE("IndexedDBBackingStore::GetRecord");
1832868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (!KeyPrefix::ValidIds(database_id, object_store_id))
1833a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    return InvalidDBKeyStatus();
18344e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  LevelDBTransaction* leveldb_transaction = transaction->transaction();
1835868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
18367dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  const std::string leveldb_key =
1837868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      ObjectStoreDataKey::Encode(database_id, object_store_id, key);
1838868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  std::string data;
1839868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1840868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  record->clear();
1841868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1842868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  bool found = false;
1843a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  leveldb::Status s = leveldb_transaction->Get(leveldb_key, &data, &found);
1844a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  if (!s.ok()) {
1845868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    INTERNAL_READ_ERROR(GET_RECORD);
1846a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    return s;
1847868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
1848868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (!found)
1849a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    return s;
1850868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (data.empty()) {
1851e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    INTERNAL_READ_ERROR_UNTESTED(GET_RECORD);
1852a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    return leveldb::Status::NotFound("Record contained no data");
1853868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
1854868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1855868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  int64 version;
1856868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  StringPiece slice(data);
1857868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (!DecodeVarInt(&slice, &version)) {
1858e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    INTERNAL_READ_ERROR_UNTESTED(GET_RECORD);
1859a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    return InternalInconsistencyStatus();
1860868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
1861868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
186223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  record->bits = slice.as_string();
1863cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  return transaction->GetBlobInfoForRecord(database_id, leveldb_key, record);
1864868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
1865868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1866a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)WARN_UNUSED_RESULT static leveldb::Status GetNewVersionNumber(
1867868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    LevelDBTransaction* transaction,
1868868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    int64 database_id,
1869868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    int64 object_store_id,
1870868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    int64* new_version_number) {
18717dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  const std::string last_version_key = ObjectStoreMetaDataKey::Encode(
1872868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      database_id, object_store_id, ObjectStoreMetaDataKey::LAST_VERSION);
1873868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1874868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  *new_version_number = -1;
1875868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  int64 last_version = -1;
1876868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  bool found = false;
1877a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  leveldb::Status s =
1878a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      GetInt(transaction, last_version_key, &last_version, &found);
1879a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  if (!s.ok()) {
1880e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    INTERNAL_READ_ERROR_UNTESTED(GET_NEW_VERSION_NUMBER);
1881a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    return s;
1882868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
1883868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (!found)
1884868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    last_version = 0;
1885868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1886868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DCHECK_GE(last_version, 0);
1887868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1888868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  int64 version = last_version + 1;
18897dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  PutInt(transaction, last_version_key, version);
1890868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1891eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // TODO(jsbell): Think about how we want to handle the overflow scenario.
1892eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  DCHECK(version > last_version);
1893868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1894868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  *new_version_number = version;
1895a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  return s;
1896868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
1897868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1898a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)leveldb::Status IndexedDBBackingStore::PutRecord(
1899868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    IndexedDBBackingStore::Transaction* transaction,
1900868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    int64 database_id,
1901868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    int64 object_store_id,
1902868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    const IndexedDBKey& key,
19035f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    IndexedDBValue* value,
190403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    ScopedVector<storage::BlobDataHandle>* handles,
1905868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    RecordIdentifier* record_identifier) {
1906eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  IDB_TRACE("IndexedDBBackingStore::PutRecord");
1907868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (!KeyPrefix::ValidIds(database_id, object_store_id))
1908a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    return InvalidDBKeyStatus();
1909868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DCHECK(key.IsValid());
1910868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
19114e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  LevelDBTransaction* leveldb_transaction = transaction->transaction();
1912868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  int64 version = -1;
1913a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  leveldb::Status s = GetNewVersionNumber(
1914868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      leveldb_transaction, database_id, object_store_id, &version);
1915a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  if (!s.ok())
1916a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    return s;
1917868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DCHECK_GE(version, 0);
191823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  const std::string object_store_data_key =
1919868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      ObjectStoreDataKey::Encode(database_id, object_store_id, key);
1920868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
19217dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  std::string v;
1922868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  EncodeVarInt(version, &v);
19235f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  v.append(value->bits);
1924868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
192523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  leveldb_transaction->Put(object_store_data_key, &v);
1926f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  s = transaction->PutBlobInfoIfNeeded(database_id,
1927f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                                       object_store_id,
1928f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                                       object_store_data_key,
19295f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                       &value->blob_info,
1930f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                                       handles);
1931f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  if (!s.ok())
1932f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    return s;
19330529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  DCHECK(!handles->size());
1934868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
19357dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  const std::string exists_entry_key =
1936868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      ExistsEntryKey::Encode(database_id, object_store_id, key);
19377dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  std::string version_encoded;
1938868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  EncodeInt(version, &version_encoded);
19397dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  leveldb_transaction->Put(exists_entry_key, &version_encoded);
1940868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
19417dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  std::string key_encoded;
1942868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  EncodeIDBKey(key, &key_encoded);
1943868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  record_identifier->Reset(key_encoded, version);
1944a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  return s;
1945868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
1946868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1947a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)leveldb::Status IndexedDBBackingStore::ClearObjectStore(
1948868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    IndexedDBBackingStore::Transaction* transaction,
1949868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    int64 database_id,
1950868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    int64 object_store_id) {
1951eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  IDB_TRACE("IndexedDBBackingStore::ClearObjectStore");
1952868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (!KeyPrefix::ValidIds(database_id, object_store_id))
1953a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    return InvalidDBKeyStatus();
19547dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  const std::string start_key =
1955868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      KeyPrefix(database_id, object_store_id).Encode();
19567dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  const std::string stop_key =
1957868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      KeyPrefix(database_id, object_store_id + 1).Encode();
1958868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
19590529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  leveldb::Status s =
196046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      DeleteRangeBasic(transaction->transaction(), start_key, stop_key, true);
1961cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (!s.ok()) {
19620529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    INTERNAL_WRITE_ERROR(CLEAR_OBJECT_STORE);
1963cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    return s;
1964cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  }
1965cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  return DeleteBlobsInObjectStore(transaction, database_id, object_store_id);
1966868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
1967868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1968a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)leveldb::Status IndexedDBBackingStore::DeleteRecord(
1969868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    IndexedDBBackingStore::Transaction* transaction,
1970868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    int64 database_id,
1971868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    int64 object_store_id,
1972868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    const RecordIdentifier& record_identifier) {
1973eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  IDB_TRACE("IndexedDBBackingStore::DeleteRecord");
1974868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (!KeyPrefix::ValidIds(database_id, object_store_id))
1975a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    return InvalidDBKeyStatus();
19764e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  LevelDBTransaction* leveldb_transaction = transaction->transaction();
1977868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
19787dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  const std::string object_store_data_key = ObjectStoreDataKey::Encode(
1979868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      database_id, object_store_id, record_identifier.primary_key());
19807dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  leveldb_transaction->Remove(object_store_data_key);
1981f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  leveldb::Status s = transaction->PutBlobInfoIfNeeded(
19820529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch      database_id, object_store_id, object_store_data_key, NULL, NULL);
1983f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  if (!s.ok())
1984f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    return s;
1985868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
19867dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  const std::string exists_entry_key = ExistsEntryKey::Encode(
1987868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      database_id, object_store_id, record_identifier.primary_key());
19887dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  leveldb_transaction->Remove(exists_entry_key);
1989a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  return leveldb::Status::OK();
1990868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
1991868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
199246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)leveldb::Status IndexedDBBackingStore::DeleteRange(
199346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    IndexedDBBackingStore::Transaction* transaction,
199446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    int64 database_id,
199546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    int64 object_store_id,
199646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    const IndexedDBKeyRange& key_range) {
199746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  leveldb::Status s;
199846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  scoped_ptr<IndexedDBBackingStore::Cursor> start_cursor =
199946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      OpenObjectStoreCursor(transaction,
200046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)                            database_id,
200146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)                            object_store_id,
200246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)                            key_range,
2003116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                            blink::WebIDBCursorDirectionNext,
200446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)                            &s);
200546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  if (!s.ok())
200646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    return s;
200746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  if (!start_cursor)
200846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    return leveldb::Status::OK();  // Empty range == delete success.
200946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
201046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  scoped_ptr<IndexedDBBackingStore::Cursor> end_cursor =
201146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      OpenObjectStoreCursor(transaction,
201246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)                            database_id,
201346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)                            object_store_id,
201446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)                            key_range,
2015116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                            blink::WebIDBCursorDirectionPrev,
201646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)                            &s);
201746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
201846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  if (!s.ok())
201946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    return s;
202046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  if (!end_cursor)
202146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    return leveldb::Status::OK();  // Empty range == delete success.
202246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
202346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  BlobEntryKey start_blob_key, end_blob_key;
202446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
202546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  std::string start_key = ObjectStoreDataKey::Encode(
202646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      database_id, object_store_id, start_cursor->key());
202746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  base::StringPiece start_key_piece(start_key);
202846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  if (!BlobEntryKey::FromObjectStoreDataKey(&start_key_piece, &start_blob_key))
202946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    return InternalInconsistencyStatus();
203046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  std::string stop_key = ObjectStoreDataKey::Encode(
203146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      database_id, object_store_id, end_cursor->key());
203246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  base::StringPiece stop_key_piece(stop_key);
203346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  if (!BlobEntryKey::FromObjectStoreDataKey(&stop_key_piece, &end_blob_key))
203446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    return InternalInconsistencyStatus();
203546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
203646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  s = DeleteBlobsInRange(transaction,
203746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)                         database_id,
203846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)                         object_store_id,
203946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)                         start_blob_key.Encode(),
204046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)                         end_blob_key.Encode(),
204146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)                         false);
204246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  if (!s.ok())
204346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    return s;
204446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  s = DeleteRangeBasic(transaction->transaction(), start_key, stop_key, false);
204546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  if (!s.ok())
204646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    return s;
204746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  start_key =
204846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      ExistsEntryKey::Encode(database_id, object_store_id, start_cursor->key());
204946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  stop_key =
205046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      ExistsEntryKey::Encode(database_id, object_store_id, end_cursor->key());
205146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  return DeleteRangeBasic(
205246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      transaction->transaction(), start_key, stop_key, false);
205346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)}
205446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
2055a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)leveldb::Status IndexedDBBackingStore::GetKeyGeneratorCurrentNumber(
2056868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    IndexedDBBackingStore::Transaction* transaction,
2057868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    int64 database_id,
2058868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    int64 object_store_id,
2059868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    int64* key_generator_current_number) {
2060868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (!KeyPrefix::ValidIds(database_id, object_store_id))
2061a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    return InvalidDBKeyStatus();
20624e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  LevelDBTransaction* leveldb_transaction = transaction->transaction();
2063868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
20647dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  const std::string key_generator_current_number_key =
2065868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      ObjectStoreMetaDataKey::Encode(
2066868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)          database_id,
2067868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)          object_store_id,
2068868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)          ObjectStoreMetaDataKey::KEY_GENERATOR_CURRENT_NUMBER);
2069868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
2070868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  *key_generator_current_number = -1;
2071868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  std::string data;
2072868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
2073868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  bool found = false;
2074a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  leveldb::Status s =
20757dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      leveldb_transaction->Get(key_generator_current_number_key, &data, &found);
2076a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  if (!s.ok()) {
2077e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    INTERNAL_READ_ERROR_UNTESTED(GET_KEY_GENERATOR_CURRENT_NUMBER);
2078a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    return s;
2079868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
2080868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (found && !data.empty()) {
2081868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    StringPiece slice(data);
2082868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    if (!DecodeInt(&slice, key_generator_current_number) || !slice.empty()) {
2083e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch      INTERNAL_READ_ERROR_UNTESTED(GET_KEY_GENERATOR_CURRENT_NUMBER);
2084a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      return InternalInconsistencyStatus();
2085868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    }
2086a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    return s;
2087868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
2088868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
2089868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // Previously, the key generator state was not stored explicitly
2090868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // but derived from the maximum numeric key present in existing
2091868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // data. This violates the spec as the data may be cleared but the
2092868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // key generator state must be preserved.
2093868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // TODO(jsbell): Fix this for all stores on database open?
20947dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  const std::string start_key =
2095868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      ObjectStoreDataKey::Encode(database_id, object_store_id, MinIDBKey());
20967dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  const std::string stop_key =
2097868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      ObjectStoreDataKey::Encode(database_id, object_store_id, MaxIDBKey());
2098868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
2099868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  scoped_ptr<LevelDBIterator> it = leveldb_transaction->CreateIterator();
2100868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  int64 max_numeric_key = 0;
2101868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
21020529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  for (s = it->Seek(start_key);
21030529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch       s.ok() && it->IsValid() && CompareKeys(it->Key(), stop_key) < 0;
21040529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch       s = it->Next()) {
2105ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    StringPiece slice(it->Key());
2106868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    ObjectStoreDataKey data_key;
2107cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    if (!ObjectStoreDataKey::Decode(&slice, &data_key) || !slice.empty()) {
2108e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch      INTERNAL_READ_ERROR_UNTESTED(GET_KEY_GENERATOR_CURRENT_NUMBER);
2109a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      return InternalInconsistencyStatus();
2110ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    }
2111868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    scoped_ptr<IndexedDBKey> user_key = data_key.user_key();
2112f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    if (user_key->type() == blink::WebIDBKeyTypeNumber) {
2113868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      int64 n = static_cast<int64>(user_key->number());
2114868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      if (n > max_numeric_key)
2115868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        max_numeric_key = n;
2116868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    }
2117868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
2118868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
21190529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  if (s.ok())
21200529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    *key_generator_current_number = max_numeric_key + 1;
21210529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  else
21220529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    INTERNAL_READ_ERROR_UNTESTED(GET_KEY_GENERATOR_CURRENT_NUMBER);
21230529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch
2124a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  return s;
2125868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
2126868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
2127a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)leveldb::Status IndexedDBBackingStore::MaybeUpdateKeyGeneratorCurrentNumber(
2128868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    IndexedDBBackingStore::Transaction* transaction,
2129868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    int64 database_id,
2130868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    int64 object_store_id,
2131868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    int64 new_number,
2132868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    bool check_current) {
2133868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (!KeyPrefix::ValidIds(database_id, object_store_id))
2134a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    return InvalidDBKeyStatus();
2135868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
2136868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (check_current) {
2137868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    int64 current_number;
2138a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    leveldb::Status s = GetKeyGeneratorCurrentNumber(
2139868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        transaction, database_id, object_store_id, &current_number);
2140a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    if (!s.ok())
2141a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      return s;
2142868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    if (new_number <= current_number)
2143a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      return s;
2144868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
2145868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
21467dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  const std::string key_generator_current_number_key =
2147868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      ObjectStoreMetaDataKey::Encode(
2148868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)          database_id,
2149868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)          object_store_id,
2150868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)          ObjectStoreMetaDataKey::KEY_GENERATOR_CURRENT_NUMBER);
21514e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  PutInt(
21524e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      transaction->transaction(), key_generator_current_number_key, new_number);
2153a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  return leveldb::Status::OK();
2154868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
2155868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
2156a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)leveldb::Status IndexedDBBackingStore::KeyExistsInObjectStore(
2157868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    IndexedDBBackingStore::Transaction* transaction,
2158868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    int64 database_id,
2159868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    int64 object_store_id,
2160868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    const IndexedDBKey& key,
2161868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    RecordIdentifier* found_record_identifier,
2162868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    bool* found) {
2163eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  IDB_TRACE("IndexedDBBackingStore::KeyExistsInObjectStore");
2164868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (!KeyPrefix::ValidIds(database_id, object_store_id))
2165a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    return InvalidDBKeyStatus();
2166868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  *found = false;
21677dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  const std::string leveldb_key =
2168868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      ObjectStoreDataKey::Encode(database_id, object_store_id, key);
2169868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  std::string data;
2170868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
2171a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  leveldb::Status s =
2172a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      transaction->transaction()->Get(leveldb_key, &data, found);
2173a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  if (!s.ok()) {
2174e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    INTERNAL_READ_ERROR_UNTESTED(KEY_EXISTS_IN_OBJECT_STORE);
2175a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    return s;
2176868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
2177868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (!*found)
2178a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    return leveldb::Status::OK();
2179868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (!data.size()) {
2180e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    INTERNAL_READ_ERROR_UNTESTED(KEY_EXISTS_IN_OBJECT_STORE);
2181a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    return InternalInconsistencyStatus();
2182868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
2183868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
2184868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  int64 version;
2185868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  StringPiece slice(data);
2186868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (!DecodeVarInt(&slice, &version))
2187a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    return InternalInconsistencyStatus();
2188868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
21897dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  std::string encoded_key;
2190868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  EncodeIDBKey(key, &encoded_key);
2191868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  found_record_identifier->Reset(encoded_key, version);
2192a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  return s;
2193868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
2194868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
21955c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liuclass IndexedDBBackingStore::Transaction::ChainedBlobWriterImpl
21965c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    : public IndexedDBBackingStore::Transaction::ChainedBlobWriter {
21975c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu public:
21985c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  typedef IndexedDBBackingStore::Transaction::WriteDescriptorVec
21995c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      WriteDescriptorVec;
22005c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  ChainedBlobWriterImpl(
22015c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      int64 database_id,
22026d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)      IndexedDBBackingStore* backing_store,
22035f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      WriteDescriptorVec* blobs,
22045c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      scoped_refptr<IndexedDBBackingStore::BlobWriteCallback> callback)
22055c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      : waiting_for_callback_(false),
22065c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu        database_id_(database_id),
22076d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)        backing_store_(backing_store),
22085c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu        callback_(callback),
22095c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu        aborted_(false) {
22105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    blobs_.swap(*blobs);
22115c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    iter_ = blobs_.begin();
22126d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)    backing_store->task_runner()->PostTask(
22136d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)        FROM_HERE, base::Bind(&ChainedBlobWriterImpl::WriteNextFile, this));
22145c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  }
22155c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
22165c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  virtual void set_delegate(scoped_ptr<FileWriterDelegate> delegate) OVERRIDE {
22175c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    delegate_.reset(delegate.release());
22185c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  }
22195c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
22205c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  virtual void ReportWriteCompletion(bool succeeded,
22215c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu                                     int64 bytes_written) OVERRIDE {
22225c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    DCHECK(waiting_for_callback_);
22235c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    DCHECK(!succeeded || bytes_written >= 0);
22245c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    waiting_for_callback_ = false;
22255c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    if (delegate_.get())  // Only present for Blob, not File.
22265c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      content::BrowserThread::DeleteSoon(
22275c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu          content::BrowserThread::IO, FROM_HERE, delegate_.release());
22285c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    if (aborted_) {
22295c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      self_ref_ = NULL;
22305c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      return;
22315c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    }
22326d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)    if (iter_->size() != -1 && iter_->size() != bytes_written)
22336d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)      succeeded = false;
22346d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)    if (succeeded) {
22356d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)      ++iter_;
22365c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      WriteNextFile();
22376d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)    } else {
22385c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      callback_->Run(false);
22396d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)    }
22405c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  }
22415c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
22425c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  virtual void Abort() OVERRIDE {
22435c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    if (!waiting_for_callback_)
22445c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      return;
22455c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    self_ref_ = this;
22465c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    aborted_ = true;
22475c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  }
22485c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
22495c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu private:
22505c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  virtual ~ChainedBlobWriterImpl() {}
22515c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
22525c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  void WriteNextFile() {
22535c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    DCHECK(!waiting_for_callback_);
22545c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    DCHECK(!aborted_);
22555c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    if (iter_ == blobs_.end()) {
22561320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      DCHECK(!self_ref_.get());
22575c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      callback_->Run(true);
22585c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      return;
22595c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    } else {
22605c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      if (!backing_store_->WriteBlobFile(database_id_, *iter_, this)) {
22615c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu        callback_->Run(false);
22625c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu        return;
22635c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      }
22645c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      waiting_for_callback_ = true;
22655c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    }
22665c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  }
22675c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
22685c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  bool waiting_for_callback_;
22695c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  scoped_refptr<ChainedBlobWriterImpl> self_ref_;
22705c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  WriteDescriptorVec blobs_;
22715c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  WriteDescriptorVec::const_iterator iter_;
22725c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  int64 database_id_;
22735c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  IndexedDBBackingStore* backing_store_;
22745c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  scoped_refptr<IndexedDBBackingStore::BlobWriteCallback> callback_;
22755c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  scoped_ptr<FileWriterDelegate> delegate_;
22765c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  bool aborted_;
2277f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
2278f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(ChainedBlobWriterImpl);
22795c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu};
22805c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
22815c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liuclass LocalWriteClosure : public FileWriterDelegate::DelegateWriteCallback,
22825f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                          public base::RefCountedThreadSafe<LocalWriteClosure> {
22835c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu public:
22845c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  LocalWriteClosure(IndexedDBBackingStore::Transaction::ChainedBlobWriter*
2285f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                        chained_blob_writer,
22865f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    base::SequencedTaskRunner* task_runner)
2287f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      : chained_blob_writer_(chained_blob_writer),
22885c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu        task_runner_(task_runner),
22896d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)        bytes_written_(0) {}
22905c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
22915c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  void Run(base::File::Error rv,
22925c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu           int64 bytes,
22935c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu           FileWriterDelegate::WriteProgressStatus write_status) {
22946d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)    DCHECK_GE(bytes, 0);
22956d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)    bytes_written_ += bytes;
22965c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    if (write_status == FileWriterDelegate::SUCCESS_IO_PENDING)
22975c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      return;  // We don't care about progress events.
22985c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    if (rv == base::File::FILE_OK) {
2299f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      DCHECK_EQ(write_status, FileWriterDelegate::SUCCESS_COMPLETED);
23005c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    } else {
23015c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      DCHECK(write_status == FileWriterDelegate::ERROR_WRITE_STARTED ||
23025c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu             write_status == FileWriterDelegate::ERROR_WRITE_NOT_STARTED);
23035c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    }
23045c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    task_runner_->PostTask(
23055c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu        FROM_HERE,
23065f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        base::Bind(&IndexedDBBackingStore::Transaction::ChainedBlobWriter::
23075f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                       ReportWriteCompletion,
23085f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                   chained_blob_writer_,
23095f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                   write_status == FileWriterDelegate::SUCCESS_COMPLETED,
23105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                   bytes_written_));
23115c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  }
23125c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
23135c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  void writeBlobToFileOnIOThread(const FilePath& file_path,
23145c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu                                 const GURL& blob_url,
23155c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu                                 net::URLRequestContext* request_context) {
23165c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
231703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    scoped_ptr<storage::FileStreamWriter> writer(
231803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)        storage::FileStreamWriter::CreateForLocalFile(
23191320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci            task_runner_.get(),
232003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)            file_path,
232103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)            0,
232203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)            storage::FileStreamWriter::CREATE_NEW_FILE));
23235c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    scoped_ptr<FileWriterDelegate> delegate(
2324010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)        new FileWriterDelegate(writer.Pass(),
2325010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)                               FileWriterDelegate::FLUSH_ON_COMPLETION));
23265c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
23275c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    DCHECK(blob_url.is_valid());
23285c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    scoped_ptr<net::URLRequest> blob_request(request_context->CreateRequest(
23295c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu        blob_url, net::DEFAULT_PRIORITY, delegate.get(), NULL));
23305c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
23315c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    delegate->Start(blob_request.Pass(),
23325c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu                    base::Bind(&LocalWriteClosure::Run, this));
23335c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    chained_blob_writer_->set_delegate(delegate.Pass());
23345c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  }
23355c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
23365c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu private:
23375f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  virtual ~LocalWriteClosure() {
23385f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    // Make sure the last reference to a ChainedBlobWriter is released (and
23395f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    // deleted) on the IDB thread since it owns a transaction which has thread
23405f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    // affinity.
23415f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    IndexedDBBackingStore::Transaction::ChainedBlobWriter* raw_tmp =
23425f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        chained_blob_writer_.get();
23435f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    raw_tmp->AddRef();
23445f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    chained_blob_writer_ = NULL;
23455f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    task_runner_->ReleaseSoon(FROM_HERE, raw_tmp);
23465f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  }
23475f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  friend class base::RefCountedThreadSafe<LocalWriteClosure>;
23485f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
23495f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  scoped_refptr<IndexedDBBackingStore::Transaction::ChainedBlobWriter>
23505f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      chained_blob_writer_;
23515f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  scoped_refptr<base::SequencedTaskRunner> task_runner_;
23525c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  int64 bytes_written_;
2353f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
2354f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(LocalWriteClosure);
23555c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu};
23565c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
23575c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liubool IndexedDBBackingStore::WriteBlobFile(
23585c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    int64 database_id,
23595c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    const Transaction::WriteDescriptor& descriptor,
23605c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    Transaction::ChainedBlobWriter* chained_blob_writer) {
23615c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
23625c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  if (!MakeIDBBlobDirectory(blob_path_, database_id, descriptor.key()))
23635c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    return false;
23645c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
23655c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  FilePath path = GetBlobFileName(database_id, descriptor.key());
23665c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
23675c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  if (descriptor.is_file()) {
23685c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    DCHECK(!descriptor.file_path().empty());
23695c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    if (!base::CopyFile(descriptor.file_path(), path))
23705c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      return false;
23715c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
23725c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    base::File::Info info;
23735c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    if (base::GetFileInfo(descriptor.file_path(), &info)) {
23746d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)      if (descriptor.size() != -1) {
23756d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)        if (descriptor.size() != info.size)
23766d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)          return false;
23776d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)        // The round-trip can be lossy; round to nearest millisecond.
23786d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)        int64 delta = (descriptor.last_modified() -
23796d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)            info.last_modified).InMilliseconds();
23806d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)        if (std::abs(delta) > 1)
23816d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)          return false;
23826d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)      }
23835c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      if (!base::TouchFile(path, info.last_accessed, info.last_modified)) {
23845c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu        // TODO(ericu): Complain quietly; timestamp's probably not vital.
23855c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      }
23865c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    } else {
23875c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      // TODO(ericu): Complain quietly; timestamp's probably not vital.
23885c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    }
23895c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
23905c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    task_runner_->PostTask(
23915c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu        FROM_HERE,
23925c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu        base::Bind(&Transaction::ChainedBlobWriter::ReportWriteCompletion,
23935c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu                   chained_blob_writer,
23945c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu                   true,
23955c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu                   info.size));
23965c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  } else {
23975c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    DCHECK(descriptor.url().is_valid());
23985c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    scoped_refptr<LocalWriteClosure> write_closure(
23991320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        new LocalWriteClosure(chained_blob_writer, task_runner_.get()));
24005c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    content::BrowserThread::PostTask(
24015c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu        content::BrowserThread::IO,
24025c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu        FROM_HERE,
24035c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu        base::Bind(&LocalWriteClosure::writeBlobToFileOnIOThread,
24045c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu                   write_closure.get(),
24055c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu                   path,
24065c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu                   descriptor.url(),
24075c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu                   request_context_));
24085c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  }
24095c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  return true;
24105c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu}
24115c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
2412010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)void IndexedDBBackingStore::ReportBlobUnused(int64 database_id,
2413010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)                                             int64 blob_key) {
2414010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  DCHECK(KeyPrefix::IsValidDatabaseId(database_id));
2415010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  bool all_blobs = blob_key == DatabaseMetaDataKey::kAllBlobsKey;
2416010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  DCHECK(all_blobs || DatabaseMetaDataKey::IsValidBlobKey(blob_key));
2417010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  scoped_refptr<LevelDBTransaction> transaction =
2418f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      IndexedDBClassFactory::Get()->CreateLevelDBTransaction(db_.get());
2419010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
2420010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  std::string live_blob_key = LiveBlobJournalKey::Encode();
2421010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  BlobJournalType live_blob_journal;
2422010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  if (!GetBlobJournal(live_blob_key, transaction.get(), &live_blob_journal)
2423010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)           .ok())
2424010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    return;
2425010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  DCHECK(live_blob_journal.size());
2426010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
2427010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  std::string primary_key = BlobJournalKey::Encode();
2428010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  BlobJournalType primary_journal;
2429010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  if (!GetBlobJournal(primary_key, transaction.get(), &primary_journal).ok())
2430010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    return;
2431010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
2432010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  // There are several cases to handle.  If blob_key is kAllBlobsKey, we want to
2433010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  // remove all entries with database_id from the live_blob journal and add only
2434010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  // kAllBlobsKey to the primary journal.  Otherwise if IsValidBlobKey(blob_key)
2435010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  // and we hit kAllBlobsKey for the right database_id in the journal, we leave
2436010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  // the kAllBlobsKey entry in the live_blob journal but add the specific blob
2437010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  // to the primary.  Otherwise if IsValidBlobKey(blob_key) and we find a
2438010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  // matching (database_id, blob_key) tuple, we should move it to the primary
2439010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  // journal.
2440010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  BlobJournalType new_live_blob_journal;
2441010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  for (BlobJournalType::iterator journal_iter = live_blob_journal.begin();
2442010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)       journal_iter != live_blob_journal.end();
2443010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)       ++journal_iter) {
2444010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    int64 current_database_id = journal_iter->first;
2445010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    int64 current_blob_key = journal_iter->second;
2446010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    bool current_all_blobs =
2447010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)        current_blob_key == DatabaseMetaDataKey::kAllBlobsKey;
2448010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    DCHECK(KeyPrefix::IsValidDatabaseId(current_database_id) ||
2449010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)           current_all_blobs);
2450010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    if (current_database_id == database_id &&
2451010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)        (all_blobs || current_all_blobs || blob_key == current_blob_key)) {
2452010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      if (!all_blobs) {
2453010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)        primary_journal.push_back(
2454010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)            std::make_pair(database_id, current_blob_key));
2455010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)        if (current_all_blobs)
2456010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)          new_live_blob_journal.push_back(*journal_iter);
2457010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)        new_live_blob_journal.insert(new_live_blob_journal.end(),
2458010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)                                     ++journal_iter,
2459010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)                                     live_blob_journal.end());  // All the rest.
2460010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)        break;
2461010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      }
2462010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    } else {
2463010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      new_live_blob_journal.push_back(*journal_iter);
2464010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    }
2465010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  }
2466010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  if (all_blobs) {
2467010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    primary_journal.push_back(
2468010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)        std::make_pair(database_id, DatabaseMetaDataKey::kAllBlobsKey));
2469010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  }
2470010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  UpdatePrimaryJournalWithBlobList(transaction.get(), primary_journal);
2471010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  UpdateLiveBlobJournalWithBlobList(transaction.get(), new_live_blob_journal);
2472010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  transaction->Commit();
2473010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  // We could just do the deletions/cleaning here, but if there are a lot of
2474010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  // blobs about to be garbage collected, it'd be better to wait and do them all
2475010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  // at once.
2476010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  StartJournalCleaningTimer();
2477010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)}
2478010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
2479010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)// The this reference is a raw pointer that's declared Unretained inside the
2480010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)// timer code, so this won't confuse IndexedDBFactory's check for
2481010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)// HasLastBackingStoreReference.  It's safe because if the backing store is
2482010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)// deleted, the timer will automatically be canceled on destruction.
2483010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)void IndexedDBBackingStore::StartJournalCleaningTimer() {
2484010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  journal_cleaning_timer_.Start(
2485010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      FROM_HERE,
2486010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      base::TimeDelta::FromSeconds(5),
2487010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      this,
2488010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      &IndexedDBBackingStore::CleanPrimaryJournalIgnoreReturn);
2489010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)}
2490010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
24915c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu// This assumes a file path of dbId/second-to-LSB-of-counter/counter.
24925c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo LiuFilePath IndexedDBBackingStore::GetBlobFileName(int64 database_id, int64 key) {
24935c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  return GetBlobFileNameForKey(blob_path_, database_id, key);
24945c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu}
24955c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
2496868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)static bool CheckIndexAndMetaDataKey(const LevelDBIterator* it,
24977dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch                                     const std::string& stop_key,
2498868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                     int64 index_id,
2499868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                     unsigned char meta_data_type) {
25007dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if (!it->IsValid() || CompareKeys(it->Key(), stop_key) >= 0)
2501868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return false;
2502868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
2503ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  StringPiece slice(it->Key());
2504868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  IndexMetaDataKey meta_data_key;
2505ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  bool ok = IndexMetaDataKey::Decode(&slice, &meta_data_key);
2506ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  DCHECK(ok);
2507868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (meta_data_key.IndexId() != index_id)
2508868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return false;
2509868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (meta_data_key.meta_data_type() != meta_data_type)
2510868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return false;
2511868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  return true;
2512868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
2513868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
2514868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)// TODO(jsbell): This should do some error handling rather than plowing ahead
2515868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)// when bad data is encountered.
2516a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)leveldb::Status IndexedDBBackingStore::GetIndexes(
2517868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    int64 database_id,
2518868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    int64 object_store_id,
2519868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    IndexedDBObjectStoreMetadata::IndexMap* indexes) {
2520eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  IDB_TRACE("IndexedDBBackingStore::GetIndexes");
2521868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (!KeyPrefix::ValidIds(database_id, object_store_id))
2522a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    return InvalidDBKeyStatus();
25237dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  const std::string start_key =
2524868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      IndexMetaDataKey::Encode(database_id, object_store_id, 0, 0);
25257dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  const std::string stop_key =
2526868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      IndexMetaDataKey::Encode(database_id, object_store_id + 1, 0, 0);
2527868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
2528868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DCHECK(indexes->empty());
2529868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
2530868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  scoped_ptr<LevelDBIterator> it = db_->CreateIterator();
25310529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  leveldb::Status s = it->Seek(start_key);
25320529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  while (s.ok() && it->IsValid() && CompareKeys(it->Key(), stop_key) < 0) {
2533ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    StringPiece slice(it->Key());
2534868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    IndexMetaDataKey meta_data_key;
2535ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    bool ok = IndexMetaDataKey::Decode(&slice, &meta_data_key);
2536ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    DCHECK(ok);
2537868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    if (meta_data_key.meta_data_type() != IndexMetaDataKey::NAME) {
2538e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch      INTERNAL_CONSISTENCY_ERROR_UNTESTED(GET_INDEXES);
2539868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      // Possible stale metadata due to http://webkit.org/b/85557 but don't fail
2540868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      // the load.
25410529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch      s = it->Next();
25420529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch      if (!s.ok())
25430529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch        break;
2544868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      continue;
2545868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    }
2546868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
2547868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    // TODO(jsbell): Do this by direct key lookup rather than iteration, to
2548868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    // simplify.
2549868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    int64 index_id = meta_data_key.IndexId();
2550a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    base::string16 index_name;
2551868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    {
25527dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      StringPiece slice(it->Value());
2553868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      if (!DecodeString(&slice, &index_name) || !slice.empty())
2554e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch        INTERNAL_CONSISTENCY_ERROR_UNTESTED(GET_INDEXES);
2555868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    }
2556868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
25570529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    s = it->Next();  // unique flag
25580529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    if (!s.ok())
25590529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch      break;
2560868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    if (!CheckIndexAndMetaDataKey(
2561424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)             it.get(), stop_key, index_id, IndexMetaDataKey::UNIQUE)) {
2562e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch      INTERNAL_CONSISTENCY_ERROR_UNTESTED(GET_INDEXES);
2563868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      break;
2564868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    }
2565868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    bool index_unique;
2566868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    {
25677dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      StringPiece slice(it->Value());
2568868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      if (!DecodeBool(&slice, &index_unique) || !slice.empty())
2569e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch        INTERNAL_CONSISTENCY_ERROR_UNTESTED(GET_INDEXES);
2570868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    }
2571868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
25720529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    s = it->Next();  // key_path
25730529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    if (!s.ok())
25740529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch      break;
2575868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    if (!CheckIndexAndMetaDataKey(
2576424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)             it.get(), stop_key, index_id, IndexMetaDataKey::KEY_PATH)) {
2577e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch      INTERNAL_CONSISTENCY_ERROR_UNTESTED(GET_INDEXES);
2578868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      break;
2579868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    }
2580868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    IndexedDBKeyPath key_path;
2581868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    {
25827dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      StringPiece slice(it->Value());
2583868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      if (!DecodeIDBKeyPath(&slice, &key_path) || !slice.empty())
2584e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch        INTERNAL_CONSISTENCY_ERROR_UNTESTED(GET_INDEXES);
2585868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    }
2586868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
25870529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    s = it->Next();  // [optional] multi_entry flag
25880529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    if (!s.ok())
25890529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch      break;
2590868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    bool index_multi_entry = false;
2591868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    if (CheckIndexAndMetaDataKey(
2592868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)            it.get(), stop_key, index_id, IndexMetaDataKey::MULTI_ENTRY)) {
25937dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      StringPiece slice(it->Value());
2594868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      if (!DecodeBool(&slice, &index_multi_entry) || !slice.empty())
2595e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch        INTERNAL_CONSISTENCY_ERROR_UNTESTED(GET_INDEXES);
2596868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
25970529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch      s = it->Next();
25980529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch      if (!s.ok())
25990529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch        break;
2600868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    }
2601868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
2602868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    (*indexes)[index_id] = IndexedDBIndexMetadata(
2603868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        index_name, index_id, key_path, index_unique, index_multi_entry);
2604868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
26050529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch
26060529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  if (!s.ok())
26070529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    INTERNAL_READ_ERROR_UNTESTED(GET_INDEXES);
26080529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch
26090529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  return s;
2610868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
2611868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
26125c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liubool IndexedDBBackingStore::RemoveBlobFile(int64 database_id, int64 key) {
26135c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  FilePath fileName = GetBlobFileName(database_id, key);
26145c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  return base::DeleteFile(fileName, false);
26155c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu}
26165c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
26175c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liubool IndexedDBBackingStore::RemoveBlobDirectory(int64 database_id) {
26185c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  FilePath dirName = GetBlobDirectoryName(blob_path_, database_id);
26195c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  return base::DeleteFile(dirName, true);
26205c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu}
26215c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
2622010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)leveldb::Status IndexedDBBackingStore::CleanUpBlobJournal(
2623010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    const std::string& level_db_key) {
2624010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  scoped_refptr<LevelDBTransaction> journal_transaction =
2625f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      IndexedDBClassFactory::Get()->CreateLevelDBTransaction(db_.get());
2626010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  BlobJournalType journal;
2627010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  leveldb::Status s =
2628010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      GetBlobJournal(level_db_key, journal_transaction.get(), &journal);
2629010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  if (!s.ok())
2630010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    return s;
2631010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  if (!journal.size())
2632010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    return leveldb::Status::OK();
2633010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  BlobJournalType::iterator journal_iter;
2634010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  for (journal_iter = journal.begin(); journal_iter != journal.end();
2635010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)       ++journal_iter) {
2636010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    int64 database_id = journal_iter->first;
2637010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    int64 blob_key = journal_iter->second;
2638010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    DCHECK(KeyPrefix::IsValidDatabaseId(database_id));
2639010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    if (blob_key == DatabaseMetaDataKey::kAllBlobsKey) {
2640010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      if (!RemoveBlobDirectory(database_id))
2641010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)        return IOErrorStatus();
2642010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    } else {
2643010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      DCHECK(DatabaseMetaDataKey::IsValidBlobKey(blob_key));
2644010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      if (!RemoveBlobFile(database_id, blob_key))
2645010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)        return IOErrorStatus();
2646010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    }
2647010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  }
2648010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  ClearBlobJournal(journal_transaction.get(), level_db_key);
2649010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  return journal_transaction->Commit();
2650010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)}
2651010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
2652cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)leveldb::Status IndexedDBBackingStore::Transaction::GetBlobInfoForRecord(
2653cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    int64 database_id,
2654cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    const std::string& object_store_data_key,
2655cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    IndexedDBValue* value) {
2656cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  BlobChangeRecord* change_record = NULL;
2657cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  BlobChangeMap::const_iterator blob_iter =
2658cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      blob_change_map_.find(object_store_data_key);
2659cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (blob_iter != blob_change_map_.end()) {
2660cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    change_record = blob_iter->second;
2661cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  } else {
2662cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    blob_iter = incognito_blob_map_.find(object_store_data_key);
2663cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    if (blob_iter != incognito_blob_map_.end())
2664cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      change_record = blob_iter->second;
2665cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  }
2666cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (change_record) {
2667cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    // Either we haven't written the blob to disk yet or we're in incognito
2668cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    // mode, so we have to send back the one they sent us.  This change record
2669cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    // includes the original UUID.
2670cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    value->blob_info = change_record->blob_info();
2671cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    return leveldb::Status::OK();
2672cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  }
2673cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
2674cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  BlobEntryKey blob_entry_key;
2675cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  StringPiece leveldb_key_piece(object_store_data_key);
2676cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (!BlobEntryKey::FromObjectStoreDataKey(&leveldb_key_piece,
2677cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                                            &blob_entry_key)) {
2678cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    NOTREACHED();
2679cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    return InternalInconsistencyStatus();
2680cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  }
2681cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  std::string encoded_key = blob_entry_key.Encode();
26821320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  bool found;
26831320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  std::string encoded_value;
26841320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  leveldb::Status s = transaction()->Get(encoded_key, &encoded_value, &found);
2685cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (!s.ok())
2686cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    return s;
26871320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (found) {
26881320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    if (!DecodeBlobData(encoded_value, &value->blob_info)) {
2689cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      INTERNAL_READ_ERROR(GET_BLOB_INFO_FOR_RECORD);
2690cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      return InternalInconsistencyStatus();
2691cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    }
2692cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    std::vector<IndexedDBBlobInfo>::iterator iter;
2693cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    for (iter = value->blob_info.begin(); iter != value->blob_info.end();
2694cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)         ++iter) {
2695cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      iter->set_file_path(
2696cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)          backing_store_->GetBlobFileName(database_id, iter->key()));
2697cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      iter->set_mark_used_callback(
2698cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)          backing_store_->active_blob_registry()->GetAddBlobRefCallback(
2699cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)              database_id, iter->key()));
2700cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      iter->set_release_callback(
2701cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)          backing_store_->active_blob_registry()->GetFinalReleaseCallback(
2702cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)              database_id, iter->key()));
2703cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      if (iter->is_file()) {
2704cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        base::File::Info info;
2705cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        if (base::GetFileInfo(iter->file_path(), &info)) {
2706cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)          // This should always work, but it isn't fatal if it doesn't; it just
2707cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)          // means a potential slow synchronous call from the renderer later.
2708cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)          iter->set_last_modified(info.last_modified);
2709cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)          iter->set_size(info.size);
2710cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        }
2711cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      }
2712cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    }
2713cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  }
2714cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  return leveldb::Status::OK();
2715cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
2716cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
2717010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)void IndexedDBBackingStore::CleanPrimaryJournalIgnoreReturn() {
2718010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  CleanUpBlobJournal(BlobJournalKey::Encode());
2719010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)}
2720010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
2721a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)WARN_UNUSED_RESULT static leveldb::Status SetMaxIndexId(
2722a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    LevelDBTransaction* transaction,
2723a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    int64 database_id,
2724a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    int64 object_store_id,
2725a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    int64 index_id) {
2726868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  int64 max_index_id = -1;
27277dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  const std::string max_index_id_key = ObjectStoreMetaDataKey::Encode(
2728868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      database_id, object_store_id, ObjectStoreMetaDataKey::MAX_INDEX_ID);
2729868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  bool found = false;
2730a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  leveldb::Status s =
2731a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      GetInt(transaction, max_index_id_key, &max_index_id, &found);
2732a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  if (!s.ok()) {
2733e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    INTERNAL_READ_ERROR_UNTESTED(SET_MAX_INDEX_ID);
2734a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    return s;
2735868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
2736868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (!found)
2737868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    max_index_id = kMinimumIndexId;
2738868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
2739868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (index_id <= max_index_id) {
2740e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    INTERNAL_CONSISTENCY_ERROR_UNTESTED(SET_MAX_INDEX_ID);
2741a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    return InternalInconsistencyStatus();
2742868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
2743868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
27447dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  PutInt(transaction, max_index_id_key, index_id);
2745a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  return s;
2746868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
2747868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
2748a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)leveldb::Status IndexedDBBackingStore::CreateIndex(
2749868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    IndexedDBBackingStore::Transaction* transaction,
2750868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    int64 database_id,
2751868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    int64 object_store_id,
2752868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    int64 index_id,
2753a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    const base::string16& name,
2754868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    const IndexedDBKeyPath& key_path,
2755868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    bool is_unique,
2756868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    bool is_multi_entry) {
2757eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  IDB_TRACE("IndexedDBBackingStore::CreateIndex");
2758868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (!KeyPrefix::ValidIds(database_id, object_store_id, index_id))
2759a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    return InvalidDBKeyStatus();
27604e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  LevelDBTransaction* leveldb_transaction = transaction->transaction();
2761a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  leveldb::Status s = SetMaxIndexId(
2762a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      leveldb_transaction, database_id, object_store_id, index_id);
2763a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
2764a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  if (!s.ok())
2765a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    return s;
2766868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
27677dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  const std::string name_key = IndexMetaDataKey::Encode(
2768868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      database_id, object_store_id, index_id, IndexMetaDataKey::NAME);
27697dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  const std::string unique_key = IndexMetaDataKey::Encode(
2770868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      database_id, object_store_id, index_id, IndexMetaDataKey::UNIQUE);
27717dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  const std::string key_path_key = IndexMetaDataKey::Encode(
2772868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      database_id, object_store_id, index_id, IndexMetaDataKey::KEY_PATH);
27737dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  const std::string multi_entry_key = IndexMetaDataKey::Encode(
2774868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      database_id, object_store_id, index_id, IndexMetaDataKey::MULTI_ENTRY);
2775868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
27767dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  PutString(leveldb_transaction, name_key, name);
27777dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  PutBool(leveldb_transaction, unique_key, is_unique);
27787dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  PutIDBKeyPath(leveldb_transaction, key_path_key, key_path);
27797dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  PutBool(leveldb_transaction, multi_entry_key, is_multi_entry);
2780a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  return s;
2781868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
2782868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
2783a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)leveldb::Status IndexedDBBackingStore::DeleteIndex(
2784868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    IndexedDBBackingStore::Transaction* transaction,
2785868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    int64 database_id,
2786868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    int64 object_store_id,
2787868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    int64 index_id) {
2788eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  IDB_TRACE("IndexedDBBackingStore::DeleteIndex");
2789868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (!KeyPrefix::ValidIds(database_id, object_store_id, index_id))
2790a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    return InvalidDBKeyStatus();
27914e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  LevelDBTransaction* leveldb_transaction = transaction->transaction();
2792868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
27937dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  const std::string index_meta_data_start =
2794868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      IndexMetaDataKey::Encode(database_id, object_store_id, index_id, 0);
27957dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  const std::string index_meta_data_end =
2796868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      IndexMetaDataKey::EncodeMaxKey(database_id, object_store_id, index_id);
279746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  leveldb::Status s = DeleteRangeBasic(
279846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      leveldb_transaction, index_meta_data_start, index_meta_data_end, true);
2799868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
28000529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  if (s.ok()) {
28010529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    const std::string index_data_start =
28020529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch        IndexDataKey::EncodeMinKey(database_id, object_store_id, index_id);
28030529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    const std::string index_data_end =
28040529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch        IndexDataKey::EncodeMaxKey(database_id, object_store_id, index_id);
280546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    s = DeleteRangeBasic(
280646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)        leveldb_transaction, index_data_start, index_data_end, true);
28070529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  }
28080529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch
28090529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  if (!s.ok())
28100529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    INTERNAL_WRITE_ERROR_UNTESTED(DELETE_INDEX);
28110529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch
28120529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  return s;
2813868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
2814868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
2815a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)leveldb::Status IndexedDBBackingStore::PutIndexDataForRecord(
2816868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    IndexedDBBackingStore::Transaction* transaction,
2817868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    int64 database_id,
2818868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    int64 object_store_id,
2819868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    int64 index_id,
2820868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    const IndexedDBKey& key,
2821868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    const RecordIdentifier& record_identifier) {
2822eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  IDB_TRACE("IndexedDBBackingStore::PutIndexDataForRecord");
2823868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DCHECK(key.IsValid());
2824868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (!KeyPrefix::ValidIds(database_id, object_store_id, index_id))
2825a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    return InvalidDBKeyStatus();
2826868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
28277dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  std::string encoded_key;
2828868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  EncodeIDBKey(key, &encoded_key);
2829868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
28307dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  const std::string index_data_key =
2831868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      IndexDataKey::Encode(database_id,
2832868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                           object_store_id,
2833868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                           index_id,
2834868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                           encoded_key,
2835eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                           record_identifier.primary_key(),
2836eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                           0);
2837868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
28387dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  std::string data;
2839868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  EncodeVarInt(record_identifier.version(), &data);
28407dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  data.append(record_identifier.primary_key());
2841868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
28424e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  transaction->transaction()->Put(index_data_key, &data);
2843a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  return leveldb::Status::OK();
2844868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
2845868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
2846868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)static bool FindGreatestKeyLessThanOrEqual(LevelDBTransaction* transaction,
28477dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch                                           const std::string& target,
28480529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch                                           std::string* found_key,
28495f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                           leveldb::Status* s) {
2850868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  scoped_ptr<LevelDBIterator> it = transaction->CreateIterator();
28515f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  *s = it->Seek(target);
28525f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  if (!s->ok())
28530529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    return false;
2854868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
2855868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (!it->IsValid()) {
28565f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    *s = it->SeekToLast();
28575f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    if (!s->ok() || !it->IsValid())
2858868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      return false;
2859868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
2860868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
28617dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  while (CompareIndexKeys(it->Key(), target) > 0) {
28625f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    *s = it->Prev();
28635f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    if (!s->ok() || !it->IsValid())
2864868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      return false;
2865868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
2866868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
2867868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  do {
28687dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    *found_key = it->Key().as_string();
2869868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
2870868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    // There can be several index keys that compare equal. We want the last one.
28715f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    *s = it->Next();
28725f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  } while (s->ok() && it->IsValid() && !CompareIndexKeys(it->Key(), target));
2873868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
2874868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  return true;
2875868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
2876868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
2877a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)static leveldb::Status VersionExists(LevelDBTransaction* transaction,
2878a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                                     int64 database_id,
2879a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                                     int64 object_store_id,
2880a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                                     int64 version,
2881a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                                     const std::string& encoded_primary_key,
2882a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                                     bool* exists) {
28837dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  const std::string key =
2884868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      ExistsEntryKey::Encode(database_id, object_store_id, encoded_primary_key);
2885868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  std::string data;
2886868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
2887a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  leveldb::Status s = transaction->Get(key, &data, exists);
2888a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  if (!s.ok()) {
2889e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    INTERNAL_READ_ERROR_UNTESTED(VERSION_EXISTS);
2890a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    return s;
2891868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
2892868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (!*exists)
2893a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    return s;
2894868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
2895868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  StringPiece slice(data);
2896868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  int64 decoded;
2897868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (!DecodeInt(&slice, &decoded) || !slice.empty())
2898a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    return InternalInconsistencyStatus();
2899868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  *exists = (decoded == version);
2900a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  return s;
2901868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
2902868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
2903a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)leveldb::Status IndexedDBBackingStore::FindKeyInIndex(
2904868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    IndexedDBBackingStore::Transaction* transaction,
2905868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    int64 database_id,
2906868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    int64 object_store_id,
2907868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    int64 index_id,
2908868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    const IndexedDBKey& key,
29097dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    std::string* found_encoded_primary_key,
2910868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    bool* found) {
2911eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  IDB_TRACE("IndexedDBBackingStore::FindKeyInIndex");
2912868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DCHECK(KeyPrefix::ValidIds(database_id, object_store_id, index_id));
2913868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
2914868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DCHECK(found_encoded_primary_key->empty());
2915868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  *found = false;
2916868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
29174e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  LevelDBTransaction* leveldb_transaction = transaction->transaction();
29187dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  const std::string leveldb_key =
2919868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      IndexDataKey::Encode(database_id, object_store_id, index_id, key);
2920868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  scoped_ptr<LevelDBIterator> it = leveldb_transaction->CreateIterator();
29210529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  leveldb::Status s = it->Seek(leveldb_key);
29220529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  if (!s.ok()) {
29230529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    INTERNAL_READ_ERROR_UNTESTED(FIND_KEY_IN_INDEX);
29240529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    return s;
29250529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  }
2926868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
2927868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  for (;;) {
2928868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    if (!it->IsValid())
2929a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      return leveldb::Status::OK();
29307dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    if (CompareIndexKeys(it->Key(), leveldb_key) > 0)
2931a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      return leveldb::Status::OK();
2932868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
29337dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    StringPiece slice(it->Value());
2934868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
2935868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    int64 version;
2936868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    if (!DecodeVarInt(&slice, &version)) {
2937e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch      INTERNAL_READ_ERROR_UNTESTED(FIND_KEY_IN_INDEX);
2938a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      return InternalInconsistencyStatus();
2939868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    }
29407dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    *found_encoded_primary_key = slice.as_string();
2941868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
2942868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    bool exists = false;
29430529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    s = VersionExists(leveldb_transaction,
29440529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch                      database_id,
29450529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch                      object_store_id,
29460529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch                      version,
29470529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch                      *found_encoded_primary_key,
29480529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch                      &exists);
2949a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    if (!s.ok())
2950a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      return s;
2951868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    if (!exists) {
2952868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      // Delete stale index data entry and continue.
2953868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      leveldb_transaction->Remove(it->Key());
29540529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch      s = it->Next();
2955868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      continue;
2956868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    }
2957868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    *found = true;
2958a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    return s;
2959868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
2960868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
2961868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
2962a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)leveldb::Status IndexedDBBackingStore::GetPrimaryKeyViaIndex(
2963868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    IndexedDBBackingStore::Transaction* transaction,
2964868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    int64 database_id,
2965868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    int64 object_store_id,
2966868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    int64 index_id,
2967868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    const IndexedDBKey& key,
2968868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    scoped_ptr<IndexedDBKey>* primary_key) {
2969eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  IDB_TRACE("IndexedDBBackingStore::GetPrimaryKeyViaIndex");
2970868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (!KeyPrefix::ValidIds(database_id, object_store_id, index_id))
2971a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    return InvalidDBKeyStatus();
2972868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
2973868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  bool found = false;
29747dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  std::string found_encoded_primary_key;
2975a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  leveldb::Status s = FindKeyInIndex(transaction,
2976a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                                     database_id,
2977a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                                     object_store_id,
2978a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                                     index_id,
2979a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                                     key,
2980a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                                     &found_encoded_primary_key,
2981a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                                     &found);
2982a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  if (!s.ok()) {
2983e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    INTERNAL_READ_ERROR_UNTESTED(GET_PRIMARY_KEY_VIA_INDEX);
2984a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    return s;
2985868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
2986868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (!found)
2987a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    return s;
2988868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (!found_encoded_primary_key.size()) {
2989e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    INTERNAL_READ_ERROR_UNTESTED(GET_PRIMARY_KEY_VIA_INDEX);
2990a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    return InvalidDBKeyStatus();
2991868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
2992868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
29937dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  StringPiece slice(found_encoded_primary_key);
2994a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  if (DecodeIDBKey(&slice, primary_key) && slice.empty())
2995a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    return s;
2996a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  else
2997a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    return InvalidDBKeyStatus();
2998868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
2999868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
3000a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)leveldb::Status IndexedDBBackingStore::KeyExistsInIndex(
3001868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    IndexedDBBackingStore::Transaction* transaction,
3002868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    int64 database_id,
3003868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    int64 object_store_id,
3004868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    int64 index_id,
3005868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    const IndexedDBKey& index_key,
3006868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    scoped_ptr<IndexedDBKey>* found_primary_key,
3007868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    bool* exists) {
3008eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  IDB_TRACE("IndexedDBBackingStore::KeyExistsInIndex");
3009868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (!KeyPrefix::ValidIds(database_id, object_store_id, index_id))
3010a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    return InvalidDBKeyStatus();
3011868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
3012868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  *exists = false;
30137dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  std::string found_encoded_primary_key;
3014a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  leveldb::Status s = FindKeyInIndex(transaction,
3015a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                                     database_id,
3016a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                                     object_store_id,
3017a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                                     index_id,
3018a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                                     index_key,
3019a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                                     &found_encoded_primary_key,
3020a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                                     exists);
3021a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  if (!s.ok()) {
3022e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    INTERNAL_READ_ERROR_UNTESTED(KEY_EXISTS_IN_INDEX);
3023a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    return s;
3024868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
3025868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (!*exists)
3026a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    return leveldb::Status::OK();
3027868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (found_encoded_primary_key.empty()) {
3028e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    INTERNAL_READ_ERROR_UNTESTED(KEY_EXISTS_IN_INDEX);
3029a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    return InvalidDBKeyStatus();
3030868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
3031868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
30327dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  StringPiece slice(found_encoded_primary_key);
3033a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  if (DecodeIDBKey(&slice, found_primary_key) && slice.empty())
3034a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    return s;
3035a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  else
3036a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    return InvalidDBKeyStatus();
3037868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
3038868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
3039868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)IndexedDBBackingStore::Cursor::Cursor(
3040868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    const IndexedDBBackingStore::Cursor* other)
3041cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    : backing_store_(other->backing_store_),
3042cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      transaction_(other->transaction_),
3043cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      database_id_(other->database_id_),
3044868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      cursor_options_(other->cursor_options_),
3045868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      current_key_(new IndexedDBKey(*other->current_key_)) {
3046868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (other->iterator_) {
3047cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    iterator_ = transaction_->transaction()->CreateIterator();
3048868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
3049868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    if (other->iterator_->IsValid()) {
30500529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch      leveldb::Status s = iterator_->Seek(other->iterator_->Key());
30510529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch      // TODO(cmumford): Handle this error (crbug.com/363397)
3052868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      DCHECK(iterator_->IsValid());
3053868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    }
3054868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
3055868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
3056868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
3057cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)IndexedDBBackingStore::Cursor::Cursor(
3058cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    scoped_refptr<IndexedDBBackingStore> backing_store,
3059cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    IndexedDBBackingStore::Transaction* transaction,
3060cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    int64 database_id,
3061cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    const CursorOptions& cursor_options)
30621320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    : backing_store_(backing_store.get()),
3063cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      transaction_(transaction),
3064cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      database_id_(database_id),
3065cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      cursor_options_(cursor_options) {
3066cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
3067868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)IndexedDBBackingStore::Cursor::~Cursor() {}
3068868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
30690529e5d033099cbfc42635f6f6183833b09dff6eBen Murdochbool IndexedDBBackingStore::Cursor::FirstSeek(leveldb::Status* s) {
3070cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  iterator_ = transaction_->transaction()->CreateIterator();
3071868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (cursor_options_.forward)
30720529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    *s = iterator_->Seek(cursor_options_.low_key);
3073868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  else
30740529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    *s = iterator_->Seek(cursor_options_.high_key);
30750529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  if (!s->ok())
30760529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    return false;
3077868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
30780529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  return Continue(0, READY, s);
3079868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
3080868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
30810529e5d033099cbfc42635f6f6183833b09dff6eBen Murdochbool IndexedDBBackingStore::Cursor::Advance(uint32 count, leveldb::Status* s) {
30820529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  *s = leveldb::Status::OK();
3083868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  while (count--) {
30840529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    if (!Continue(s))
3085868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      return false;
3086868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
3087868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  return true;
3088868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
3089868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
30907dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochbool IndexedDBBackingStore::Cursor::Continue(const IndexedDBKey* key,
3091f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                                             const IndexedDBKey* primary_key,
30920529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch                                             IteratorState next_state,
30930529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch                                             leveldb::Status* s) {
3094f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  DCHECK(!key || key->IsValid());
3095f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  DCHECK(!primary_key || primary_key->IsValid());
30960529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  *s = leveldb::Status::OK();
3097f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
3098868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // TODO(alecflett): avoid a copy here?
3099868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  IndexedDBKey previous_key = current_key_ ? *current_key_ : IndexedDBKey();
3100868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
3101868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // When iterating with PrevNoDuplicate, spec requires that the
3102868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // value we yield for each key is the first duplicate in forwards
3103868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // order.
3104868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  IndexedDBKey last_duplicate_key;
3105868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
3106868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  bool forward = cursor_options_.forward;
3107116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  bool first_iteration_forward = forward;
3108116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  bool flipped = false;
3109868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
3110868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  for (;;) {
3111868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    if (next_state == SEEK) {
3112868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      // TODO(jsbell): Optimize seeking for reverse cursors as well.
3113116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      if (first_iteration_forward && key) {
3114116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch        first_iteration_forward = false;
3115f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        std::string leveldb_key;
3116f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        if (primary_key) {
3117f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)          leveldb_key = EncodeKey(*key, *primary_key);
3118f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        } else {
3119f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)          leveldb_key = EncodeKey(*key);
3120f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        }
31210529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch        *s = iterator_->Seek(leveldb_key);
3122868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      } else if (forward) {
31230529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch        *s = iterator_->Next();
3124868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      } else {
31250529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch        *s = iterator_->Prev();
3126868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      }
31270529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch      if (!s->ok())
31280529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch        return false;
3129868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    } else {
3130868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      next_state = SEEK;  // for subsequent iterations
3131868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    }
3132868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
3133868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    if (!iterator_->IsValid()) {
3134868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      if (!forward && last_duplicate_key.IsValid()) {
3135868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        // We need to walk forward because we hit the end of
3136868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        // the data.
3137868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        forward = true;
3138116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch        flipped = true;
3139868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        continue;
3140868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      }
3141868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
3142868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      return false;
3143868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    }
3144868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
3145868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    if (IsPastBounds()) {
3146868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      if (!forward && last_duplicate_key.IsValid()) {
3147868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        // We need to walk forward because now we're beyond the
3148868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        // bounds defined by the cursor.
3149868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        forward = true;
3150116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch        flipped = true;
3151868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        continue;
3152868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      }
3153868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
3154868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      return false;
3155868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    }
3156868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
3157868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    if (!HaveEnteredRange())
3158868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      continue;
3159868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
3160868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    // The row may not load because there's a stale entry in the
3161868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    // index. This is not fatal.
3162868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    if (!LoadCurrentRow())
3163868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      continue;
3164868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
3165f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    if (key) {
3166868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      if (forward) {
316723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)        if (primary_key && current_key_->Equals(*key) &&
3168f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)            this->primary_key().IsLessThan(*primary_key))
3169f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)          continue;
3170116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch        if (!flipped && current_key_->IsLessThan(*key))
3171868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)          continue;
3172868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      } else {
317323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)        if (primary_key && key->Equals(*current_key_) &&
3174f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)            primary_key->IsLessThan(this->primary_key()))
3175f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)          continue;
3176868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        if (key->IsLessThan(*current_key_))
3177868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)          continue;
3178868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      }
3179868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    }
3180868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
3181868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    if (cursor_options_.unique) {
318223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)      if (previous_key.IsValid() && current_key_->Equals(previous_key)) {
3183868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        // We should never be able to walk forward all the way
3184868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        // to the previous key.
3185868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        DCHECK(!last_duplicate_key.IsValid());
3186868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        continue;
3187868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      }
3188868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
3189868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      if (!forward) {
3190868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        if (!last_duplicate_key.IsValid()) {
3191868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)          last_duplicate_key = *current_key_;
3192868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)          continue;
3193868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        }
3194868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
3195868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        // We need to walk forward because we hit the boundary
3196868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        // between key ranges.
319723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)        if (!last_duplicate_key.Equals(*current_key_)) {
3198868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)          forward = true;
3199116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch          flipped = true;
3200868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)          continue;
3201868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        }
3202868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
3203868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        continue;
3204868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      }
3205868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    }
3206868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    break;
3207868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
3208868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
3209868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DCHECK(!last_duplicate_key.IsValid() ||
321023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)         (forward && last_duplicate_key.Equals(*current_key_)));
3211868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  return true;
3212868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
3213868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
3214868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)bool IndexedDBBackingStore::Cursor::HaveEnteredRange() const {
3215868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (cursor_options_.forward) {
32167dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    int compare = CompareIndexKeys(iterator_->Key(), cursor_options_.low_key);
3217868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    if (cursor_options_.low_open) {
3218868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      return compare > 0;
3219868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    }
3220868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return compare >= 0;
3221868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
32227dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  int compare = CompareIndexKeys(iterator_->Key(), cursor_options_.high_key);
3223868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (cursor_options_.high_open) {
3224868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return compare < 0;
3225868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
3226868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  return compare <= 0;
3227868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
3228868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
3229868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)bool IndexedDBBackingStore::Cursor::IsPastBounds() const {
3230868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (cursor_options_.forward) {
32317dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    int compare = CompareIndexKeys(iterator_->Key(), cursor_options_.high_key);
3232868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    if (cursor_options_.high_open) {
3233868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      return compare >= 0;
3234868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    }
3235868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return compare > 0;
3236868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
32377dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  int compare = CompareIndexKeys(iterator_->Key(), cursor_options_.low_key);
3238868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (cursor_options_.low_open) {
3239868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return compare <= 0;
3240868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
3241868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  return compare < 0;
3242868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
3243868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
3244868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)const IndexedDBKey& IndexedDBBackingStore::Cursor::primary_key() const {
3245868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  return *current_key_;
3246868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
3247868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
3248868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)const IndexedDBBackingStore::RecordIdentifier&
3249868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)IndexedDBBackingStore::Cursor::record_identifier() const {
3250868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  return record_identifier_;
3251868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
3252868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
3253868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)class ObjectStoreKeyCursorImpl : public IndexedDBBackingStore::Cursor {
3254868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) public:
3255868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  ObjectStoreKeyCursorImpl(
3256cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      scoped_refptr<IndexedDBBackingStore> backing_store,
3257cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      IndexedDBBackingStore::Transaction* transaction,
3258cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      int64 database_id,
3259868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      const IndexedDBBackingStore::Cursor::CursorOptions& cursor_options)
3260cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      : IndexedDBBackingStore::Cursor(backing_store,
3261cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                                      transaction,
3262cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                                      database_id,
3263cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                                      cursor_options) {}
3264868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
3265868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  virtual Cursor* Clone() OVERRIDE {
3266868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return new ObjectStoreKeyCursorImpl(this);
3267868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
3268868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
3269868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // IndexedDBBackingStore::Cursor
327023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  virtual IndexedDBValue* value() OVERRIDE {
3271868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    NOTREACHED();
3272868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return NULL;
3273868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
3274868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  virtual bool LoadCurrentRow() OVERRIDE;
3275868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
3276868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) protected:
32777dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  virtual std::string EncodeKey(const IndexedDBKey& key) OVERRIDE {
3278868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return ObjectStoreDataKey::Encode(
3279868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        cursor_options_.database_id, cursor_options_.object_store_id, key);
3280868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
3281f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  virtual std::string EncodeKey(const IndexedDBKey& key,
3282f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                                const IndexedDBKey& primary_key) OVERRIDE {
3283f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    NOTREACHED();
3284f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    return std::string();
3285f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  }
3286868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
3287868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) private:
3288868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  explicit ObjectStoreKeyCursorImpl(const ObjectStoreKeyCursorImpl* other)
3289868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      : IndexedDBBackingStore::Cursor(other) {}
3290f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
3291f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(ObjectStoreKeyCursorImpl);
3292868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)};
3293868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
3294868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)bool ObjectStoreKeyCursorImpl::LoadCurrentRow() {
3295ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  StringPiece slice(iterator_->Key());
3296868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  ObjectStoreDataKey object_store_data_key;
3297ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  if (!ObjectStoreDataKey::Decode(&slice, &object_store_data_key)) {
3298e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    INTERNAL_READ_ERROR_UNTESTED(LOAD_CURRENT_ROW);
3299868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return false;
3300868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
3301868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
3302868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  current_key_ = object_store_data_key.user_key();
3303868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
3304868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  int64 version;
3305ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  slice = StringPiece(iterator_->Value());
3306868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (!DecodeVarInt(&slice, &version)) {
3307e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    INTERNAL_READ_ERROR_UNTESTED(LOAD_CURRENT_ROW);
3308868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return false;
3309868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
3310868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
3311868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // TODO(jsbell): This re-encodes what was just decoded; try and optimize.
33127dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  std::string encoded_key;
3313868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  EncodeIDBKey(*current_key_, &encoded_key);
3314868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  record_identifier_.Reset(encoded_key, version);
3315868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
3316868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  return true;
3317868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
3318868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
3319868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)class ObjectStoreCursorImpl : public IndexedDBBackingStore::Cursor {
3320868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) public:
3321868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  ObjectStoreCursorImpl(
3322cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      scoped_refptr<IndexedDBBackingStore> backing_store,
3323cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      IndexedDBBackingStore::Transaction* transaction,
3324cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      int64 database_id,
3325868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      const IndexedDBBackingStore::Cursor::CursorOptions& cursor_options)
3326cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      : IndexedDBBackingStore::Cursor(backing_store,
3327cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                                      transaction,
3328cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                                      database_id,
3329cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                                      cursor_options) {}
3330868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
3331868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  virtual Cursor* Clone() OVERRIDE { return new ObjectStoreCursorImpl(this); }
3332868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
3333868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // IndexedDBBackingStore::Cursor
333423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  virtual IndexedDBValue* value() OVERRIDE { return &current_value_; }
3335868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  virtual bool LoadCurrentRow() OVERRIDE;
3336868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
3337868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) protected:
33387dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  virtual std::string EncodeKey(const IndexedDBKey& key) OVERRIDE {
3339868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return ObjectStoreDataKey::Encode(
3340868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        cursor_options_.database_id, cursor_options_.object_store_id, key);
3341868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
3342f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  virtual std::string EncodeKey(const IndexedDBKey& key,
3343f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                                const IndexedDBKey& primary_key) OVERRIDE {
3344f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    NOTREACHED();
3345f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    return std::string();
3346f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  }
3347868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
3348868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) private:
3349868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  explicit ObjectStoreCursorImpl(const ObjectStoreCursorImpl* other)
3350868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      : IndexedDBBackingStore::Cursor(other),
3351868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        current_value_(other->current_value_) {}
3352868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
335323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  IndexedDBValue current_value_;
3354f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
3355f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(ObjectStoreCursorImpl);
3356868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)};
3357868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
3358868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)bool ObjectStoreCursorImpl::LoadCurrentRow() {
335923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  StringPiece key_slice(iterator_->Key());
3360868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  ObjectStoreDataKey object_store_data_key;
336123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  if (!ObjectStoreDataKey::Decode(&key_slice, &object_store_data_key)) {
3362e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    INTERNAL_READ_ERROR_UNTESTED(LOAD_CURRENT_ROW);
3363868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return false;
3364868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
3365868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
3366868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  current_key_ = object_store_data_key.user_key();
3367868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
3368868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  int64 version;
336923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  StringPiece value_slice = StringPiece(iterator_->Value());
337023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  if (!DecodeVarInt(&value_slice, &version)) {
3371e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    INTERNAL_READ_ERROR_UNTESTED(LOAD_CURRENT_ROW);
3372868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return false;
3373868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
3374868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
3375868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // TODO(jsbell): This re-encodes what was just decoded; try and optimize.
33767dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  std::string encoded_key;
3377868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  EncodeIDBKey(*current_key_, &encoded_key);
3378868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  record_identifier_.Reset(encoded_key, version);
3379868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
3380cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (!transaction_->GetBlobInfoForRecord(database_id_,
3381cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                                          iterator_->Key().as_string(),
3382cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                                          &current_value_).ok()) {
3383cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    return false;
3384cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  }
338523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  current_value_.bits = value_slice.as_string();
3386868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  return true;
3387868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
3388868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
3389868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)class IndexKeyCursorImpl : public IndexedDBBackingStore::Cursor {
3390868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) public:
3391868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  IndexKeyCursorImpl(
3392cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      scoped_refptr<IndexedDBBackingStore> backing_store,
3393cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      IndexedDBBackingStore::Transaction* transaction,
3394cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      int64 database_id,
3395868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      const IndexedDBBackingStore::Cursor::CursorOptions& cursor_options)
3396cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      : IndexedDBBackingStore::Cursor(backing_store,
3397cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                                      transaction,
3398cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                                      database_id,
3399cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                                      cursor_options) {}
3400868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
3401868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  virtual Cursor* Clone() OVERRIDE { return new IndexKeyCursorImpl(this); }
3402868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
3403868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // IndexedDBBackingStore::Cursor
340423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  virtual IndexedDBValue* value() OVERRIDE {
3405868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    NOTREACHED();
3406868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return NULL;
3407868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
3408868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  virtual const IndexedDBKey& primary_key() const OVERRIDE {
3409868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return *primary_key_;
3410868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
3411a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  virtual const IndexedDBBackingStore::RecordIdentifier& record_identifier()
3412a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      const OVERRIDE {
3413868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    NOTREACHED();
3414868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return record_identifier_;
3415868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
3416868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  virtual bool LoadCurrentRow() OVERRIDE;
3417868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
3418868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) protected:
34197dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  virtual std::string EncodeKey(const IndexedDBKey& key) OVERRIDE {
3420868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return IndexDataKey::Encode(cursor_options_.database_id,
3421868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                cursor_options_.object_store_id,
3422868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                cursor_options_.index_id,
3423868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                key);
3424868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
3425f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  virtual std::string EncodeKey(const IndexedDBKey& key,
3426f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                                const IndexedDBKey& primary_key) OVERRIDE {
3427f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    return IndexDataKey::Encode(cursor_options_.database_id,
3428f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                                cursor_options_.object_store_id,
3429f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                                cursor_options_.index_id,
3430f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                                key,
3431f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                                primary_key);
3432f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  }
3433868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
3434868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) private:
3435868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  explicit IndexKeyCursorImpl(const IndexKeyCursorImpl* other)
3436868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      : IndexedDBBackingStore::Cursor(other),
3437868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        primary_key_(new IndexedDBKey(*other->primary_key_)) {}
3438868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
3439868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  scoped_ptr<IndexedDBKey> primary_key_;
3440f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
3441f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(IndexKeyCursorImpl);
3442868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)};
3443868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
3444868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)bool IndexKeyCursorImpl::LoadCurrentRow() {
3445ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  StringPiece slice(iterator_->Key());
3446868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  IndexDataKey index_data_key;
3447ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  if (!IndexDataKey::Decode(&slice, &index_data_key)) {
3448e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    INTERNAL_READ_ERROR_UNTESTED(LOAD_CURRENT_ROW);
3449ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    return false;
3450ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  }
3451868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
3452868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  current_key_ = index_data_key.user_key();
3453868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DCHECK(current_key_);
3454868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
3455ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  slice = StringPiece(iterator_->Value());
3456868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  int64 index_data_version;
3457868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (!DecodeVarInt(&slice, &index_data_version)) {
3458e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    INTERNAL_READ_ERROR_UNTESTED(LOAD_CURRENT_ROW);
3459868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return false;
3460868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
3461868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
3462868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (!DecodeIDBKey(&slice, &primary_key_) || !slice.empty()) {
3463e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    INTERNAL_READ_ERROR_UNTESTED(LOAD_CURRENT_ROW);
3464868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return false;
3465868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
3466868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
34677dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  std::string primary_leveldb_key =
3468868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      ObjectStoreDataKey::Encode(index_data_key.DatabaseId(),
3469868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                 index_data_key.ObjectStoreId(),
3470868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                 *primary_key_);
3471868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
3472868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  std::string result;
3473868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  bool found = false;
3474cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  leveldb::Status s =
3475cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      transaction_->transaction()->Get(primary_leveldb_key, &result, &found);
3476a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  if (!s.ok()) {
3477e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    INTERNAL_READ_ERROR_UNTESTED(LOAD_CURRENT_ROW);
3478868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return false;
3479868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
3480868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (!found) {
3481cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    transaction_->transaction()->Remove(iterator_->Key());
3482868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return false;
3483868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
3484868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (!result.size()) {
3485e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    INTERNAL_READ_ERROR_UNTESTED(LOAD_CURRENT_ROW);
3486868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return false;
3487868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
3488868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
3489868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  int64 object_store_data_version;
3490868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  slice = StringPiece(result);
3491868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (!DecodeVarInt(&slice, &object_store_data_version)) {
3492e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    INTERNAL_READ_ERROR_UNTESTED(LOAD_CURRENT_ROW);
3493868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return false;
3494868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
3495868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
3496868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (object_store_data_version != index_data_version) {
3497cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    transaction_->transaction()->Remove(iterator_->Key());
3498868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return false;
3499868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
3500868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
3501868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  return true;
3502868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
3503868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
3504868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)class IndexCursorImpl : public IndexedDBBackingStore::Cursor {
3505868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) public:
3506868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  IndexCursorImpl(
3507cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      scoped_refptr<IndexedDBBackingStore> backing_store,
3508cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      IndexedDBBackingStore::Transaction* transaction,
3509cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      int64 database_id,
3510868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      const IndexedDBBackingStore::Cursor::CursorOptions& cursor_options)
3511cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      : IndexedDBBackingStore::Cursor(backing_store,
3512cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                                      transaction,
3513cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                                      database_id,
3514cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                                      cursor_options) {}
3515868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
3516868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  virtual Cursor* Clone() OVERRIDE { return new IndexCursorImpl(this); }
3517868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
3518868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // IndexedDBBackingStore::Cursor
351923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  virtual IndexedDBValue* value() OVERRIDE { return &current_value_; }
3520868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  virtual const IndexedDBKey& primary_key() const OVERRIDE {
3521868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return *primary_key_;
3522868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
3523a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  virtual const IndexedDBBackingStore::RecordIdentifier& record_identifier()
3524a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      const OVERRIDE {
3525868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    NOTREACHED();
3526868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return record_identifier_;
3527868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
3528868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  virtual bool LoadCurrentRow() OVERRIDE;
3529868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
3530868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) protected:
35317dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  virtual std::string EncodeKey(const IndexedDBKey& key) OVERRIDE {
3532868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return IndexDataKey::Encode(cursor_options_.database_id,
3533868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                cursor_options_.object_store_id,
3534868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                cursor_options_.index_id,
3535868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                key);
3536868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
3537f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  virtual std::string EncodeKey(const IndexedDBKey& key,
3538f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                                const IndexedDBKey& primary_key) OVERRIDE {
3539f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    return IndexDataKey::Encode(cursor_options_.database_id,
3540f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                                cursor_options_.object_store_id,
3541f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                                cursor_options_.index_id,
3542f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                                key,
3543f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                                primary_key);
3544f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  }
3545868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
3546868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) private:
3547868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  explicit IndexCursorImpl(const IndexCursorImpl* other)
3548868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      : IndexedDBBackingStore::Cursor(other),
3549868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        primary_key_(new IndexedDBKey(*other->primary_key_)),
3550868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        current_value_(other->current_value_),
3551868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        primary_leveldb_key_(other->primary_leveldb_key_) {}
3552868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
3553868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  scoped_ptr<IndexedDBKey> primary_key_;
355423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  IndexedDBValue current_value_;
35557dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  std::string primary_leveldb_key_;
3556f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
3557f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(IndexCursorImpl);
3558868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)};
3559868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
3560868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)bool IndexCursorImpl::LoadCurrentRow() {
3561ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  StringPiece slice(iterator_->Key());
3562868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  IndexDataKey index_data_key;
3563ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  if (!IndexDataKey::Decode(&slice, &index_data_key)) {
3564e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    INTERNAL_READ_ERROR_UNTESTED(LOAD_CURRENT_ROW);
3565ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    return false;
3566ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  }
3567868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
3568868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  current_key_ = index_data_key.user_key();
3569868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DCHECK(current_key_);
3570868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
3571ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  slice = StringPiece(iterator_->Value());
3572868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  int64 index_data_version;
3573868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (!DecodeVarInt(&slice, &index_data_version)) {
3574e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    INTERNAL_READ_ERROR_UNTESTED(LOAD_CURRENT_ROW);
3575868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return false;
3576868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
3577868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (!DecodeIDBKey(&slice, &primary_key_)) {
3578e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    INTERNAL_READ_ERROR_UNTESTED(LOAD_CURRENT_ROW);
3579868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return false;
3580868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
3581868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
3582cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  DCHECK_EQ(index_data_key.DatabaseId(), database_id_);
3583868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  primary_leveldb_key_ =
3584868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      ObjectStoreDataKey::Encode(index_data_key.DatabaseId(),
3585868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                 index_data_key.ObjectStoreId(),
3586868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                 *primary_key_);
3587868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
3588868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  std::string result;
3589868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  bool found = false;
3590cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  leveldb::Status s =
3591cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      transaction_->transaction()->Get(primary_leveldb_key_, &result, &found);
3592a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  if (!s.ok()) {
3593e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    INTERNAL_READ_ERROR_UNTESTED(LOAD_CURRENT_ROW);
3594868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return false;
3595868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
3596868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (!found) {
3597cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    transaction_->transaction()->Remove(iterator_->Key());
3598868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return false;
3599868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
3600868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (!result.size()) {
3601e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    INTERNAL_READ_ERROR_UNTESTED(LOAD_CURRENT_ROW);
3602868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return false;
3603868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
3604868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
3605868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  int64 object_store_data_version;
3606868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  slice = StringPiece(result);
3607868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (!DecodeVarInt(&slice, &object_store_data_version)) {
3608e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    INTERNAL_READ_ERROR_UNTESTED(LOAD_CURRENT_ROW);
3609868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return false;
3610868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
3611868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
3612868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (object_store_data_version != index_data_version) {
3613cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    transaction_->transaction()->Remove(iterator_->Key());
3614868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return false;
3615868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
3616868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
361723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  current_value_.bits = slice.as_string();
3618cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  return transaction_->GetBlobInfoForRecord(database_id_,
3619cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                                            primary_leveldb_key_,
3620cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                                            &current_value_).ok();
3621868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
3622868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
3623868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)bool ObjectStoreCursorOptions(
3624868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    LevelDBTransaction* transaction,
3625868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    int64 database_id,
3626868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    int64 object_store_id,
3627868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    const IndexedDBKeyRange& range,
3628116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    blink::WebIDBCursorDirection direction,
3629868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    IndexedDBBackingStore::Cursor::CursorOptions* cursor_options) {
3630868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  cursor_options->database_id = database_id;
3631868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  cursor_options->object_store_id = object_store_id;
3632868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
3633868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  bool lower_bound = range.lower().IsValid();
3634868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  bool upper_bound = range.upper().IsValid();
3635868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  cursor_options->forward =
3636116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      (direction == blink::WebIDBCursorDirectionNextNoDuplicate ||
3637116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch       direction == blink::WebIDBCursorDirectionNext);
3638116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  cursor_options->unique =
3639116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      (direction == blink::WebIDBCursorDirectionNextNoDuplicate ||
3640116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch       direction == blink::WebIDBCursorDirectionPrevNoDuplicate);
3641868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
3642868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (!lower_bound) {
3643868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    cursor_options->low_key =
3644868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        ObjectStoreDataKey::Encode(database_id, object_store_id, MinIDBKey());
3645868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    cursor_options->low_open = true;  // Not included.
3646868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  } else {
3647868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    cursor_options->low_key =
3648868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        ObjectStoreDataKey::Encode(database_id, object_store_id, range.lower());
3649868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    cursor_options->low_open = range.lowerOpen();
3650868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
3651868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
36520529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  leveldb::Status s;
36530529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch
3654868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (!upper_bound) {
3655868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    cursor_options->high_key =
3656868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        ObjectStoreDataKey::Encode(database_id, object_store_id, MaxIDBKey());
3657868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
3658868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    if (cursor_options->forward) {
3659868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      cursor_options->high_open = true;  // Not included.
3660868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    } else {
3661868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      // We need a key that exists.
36620529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch      // TODO(cmumford): Handle this error (crbug.com/363397)
3663424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      if (!FindGreatestKeyLessThanOrEqual(transaction,
3664424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)                                          cursor_options->high_key,
36650529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch                                          &cursor_options->high_key,
36665f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                          &s))
3667868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        return false;
3668868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      cursor_options->high_open = false;
3669868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    }
3670868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  } else {
3671868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    cursor_options->high_key =
3672868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        ObjectStoreDataKey::Encode(database_id, object_store_id, range.upper());
3673868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    cursor_options->high_open = range.upperOpen();
3674868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
3675868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    if (!cursor_options->forward) {
3676868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      // For reverse cursors, we need a key that exists.
36777dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      std::string found_high_key;
36780529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch      // TODO(cmumford): Handle this error (crbug.com/363397)
3679868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      if (!FindGreatestKeyLessThanOrEqual(
36805f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)              transaction, cursor_options->high_key, &found_high_key, &s))
3681868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        return false;
3682868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
3683868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      // If the target key should not be included, but we end up with a smaller
3684868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      // key, we should include that.
3685868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      if (cursor_options->high_open &&
36867dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch          CompareIndexKeys(found_high_key, cursor_options->high_key) < 0)
3687868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        cursor_options->high_open = false;
3688868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
3689868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      cursor_options->high_key = found_high_key;
3690868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    }
3691868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
3692868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
3693868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  return true;
3694868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
3695868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
3696868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)bool IndexCursorOptions(
3697868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    LevelDBTransaction* transaction,
3698868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    int64 database_id,
3699868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    int64 object_store_id,
3700868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    int64 index_id,
3701868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    const IndexedDBKeyRange& range,
3702116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    blink::WebIDBCursorDirection direction,
3703868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    IndexedDBBackingStore::Cursor::CursorOptions* cursor_options) {
3704868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DCHECK(transaction);
3705868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (!KeyPrefix::ValidIds(database_id, object_store_id, index_id))
3706868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return false;
3707868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
3708868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  cursor_options->database_id = database_id;
3709868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  cursor_options->object_store_id = object_store_id;
3710868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  cursor_options->index_id = index_id;
3711868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
3712868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  bool lower_bound = range.lower().IsValid();
3713868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  bool upper_bound = range.upper().IsValid();
3714868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  cursor_options->forward =
3715116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      (direction == blink::WebIDBCursorDirectionNextNoDuplicate ||
3716116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch       direction == blink::WebIDBCursorDirectionNext);
3717116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  cursor_options->unique =
3718116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      (direction == blink::WebIDBCursorDirectionNextNoDuplicate ||
3719116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch       direction == blink::WebIDBCursorDirectionPrevNoDuplicate);
3720868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
3721868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (!lower_bound) {
3722868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    cursor_options->low_key =
3723868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        IndexDataKey::EncodeMinKey(database_id, object_store_id, index_id);
3724868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    cursor_options->low_open = false;  // Included.
3725868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  } else {
3726868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    cursor_options->low_key = IndexDataKey::Encode(
3727868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        database_id, object_store_id, index_id, range.lower());
3728868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    cursor_options->low_open = range.lowerOpen();
3729868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
3730868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
37310529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  leveldb::Status s;
37320529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch
3733868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (!upper_bound) {
3734868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    cursor_options->high_key =
3735868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        IndexDataKey::EncodeMaxKey(database_id, object_store_id, index_id);
3736868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    cursor_options->high_open = false;  // Included.
3737868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
3738868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    if (!cursor_options->forward) {  // We need a key that exists.
3739424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      if (!FindGreatestKeyLessThanOrEqual(transaction,
3740424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)                                          cursor_options->high_key,
37410529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch                                          &cursor_options->high_key,
37425f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                          &s))
3743868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        return false;
3744868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      cursor_options->high_open = false;
3745868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    }
3746868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  } else {
3747868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    cursor_options->high_key = IndexDataKey::Encode(
3748868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        database_id, object_store_id, index_id, range.upper());
3749868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    cursor_options->high_open = range.upperOpen();
3750868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
37517dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    std::string found_high_key;
3752eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    // Seek to the *last* key in the set of non-unique keys
37530529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    // TODO(cmumford): Handle this error (crbug.com/363397)
3754868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    if (!FindGreatestKeyLessThanOrEqual(
37555f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            transaction, cursor_options->high_key, &found_high_key, &s))
3756868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      return false;
3757868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
3758868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    // If the target key should not be included, but we end up with a smaller
3759868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    // key, we should include that.
3760868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    if (cursor_options->high_open &&
37617dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch        CompareIndexKeys(found_high_key, cursor_options->high_key) < 0)
3762868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      cursor_options->high_open = false;
3763868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
3764868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    cursor_options->high_key = found_high_key;
3765868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
3766868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
3767868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  return true;
3768868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
3769868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
3770868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)scoped_ptr<IndexedDBBackingStore::Cursor>
3771868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)IndexedDBBackingStore::OpenObjectStoreCursor(
3772868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    IndexedDBBackingStore::Transaction* transaction,
3773868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    int64 database_id,
3774868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    int64 object_store_id,
3775868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    const IndexedDBKeyRange& range,
3776116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    blink::WebIDBCursorDirection direction,
37770529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    leveldb::Status* s) {
3778eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  IDB_TRACE("IndexedDBBackingStore::OpenObjectStoreCursor");
37790529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  *s = leveldb::Status::OK();
37804e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  LevelDBTransaction* leveldb_transaction = transaction->transaction();
3781868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  IndexedDBBackingStore::Cursor::CursorOptions cursor_options;
3782868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (!ObjectStoreCursorOptions(leveldb_transaction,
3783868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                database_id,
3784868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                object_store_id,
3785868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                range,
3786868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                direction,
3787868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                &cursor_options))
3788868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return scoped_ptr<IndexedDBBackingStore::Cursor>();
3789cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  scoped_ptr<ObjectStoreCursorImpl> cursor(new ObjectStoreCursorImpl(
3790cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      this, transaction, database_id, cursor_options));
37910529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  if (!cursor->FirstSeek(s))
3792868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return scoped_ptr<IndexedDBBackingStore::Cursor>();
3793868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
3794868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  return cursor.PassAs<IndexedDBBackingStore::Cursor>();
3795868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
3796868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
3797868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)scoped_ptr<IndexedDBBackingStore::Cursor>
3798868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)IndexedDBBackingStore::OpenObjectStoreKeyCursor(
3799868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    IndexedDBBackingStore::Transaction* transaction,
3800868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    int64 database_id,
3801868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    int64 object_store_id,
3802868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    const IndexedDBKeyRange& range,
3803116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    blink::WebIDBCursorDirection direction,
38040529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    leveldb::Status* s) {
3805eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  IDB_TRACE("IndexedDBBackingStore::OpenObjectStoreKeyCursor");
38060529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  *s = leveldb::Status::OK();
38074e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  LevelDBTransaction* leveldb_transaction = transaction->transaction();
3808868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  IndexedDBBackingStore::Cursor::CursorOptions cursor_options;
3809868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (!ObjectStoreCursorOptions(leveldb_transaction,
3810868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                database_id,
3811868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                object_store_id,
3812868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                range,
3813868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                direction,
3814868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                &cursor_options))
3815868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return scoped_ptr<IndexedDBBackingStore::Cursor>();
3816cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  scoped_ptr<ObjectStoreKeyCursorImpl> cursor(new ObjectStoreKeyCursorImpl(
3817cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      this, transaction, database_id, cursor_options));
38180529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  if (!cursor->FirstSeek(s))
3819868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return scoped_ptr<IndexedDBBackingStore::Cursor>();
3820868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
3821868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  return cursor.PassAs<IndexedDBBackingStore::Cursor>();
3822868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
3823868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
3824868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)scoped_ptr<IndexedDBBackingStore::Cursor>
3825868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)IndexedDBBackingStore::OpenIndexKeyCursor(
3826868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    IndexedDBBackingStore::Transaction* transaction,
3827868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    int64 database_id,
3828868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    int64 object_store_id,
3829868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    int64 index_id,
3830868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    const IndexedDBKeyRange& range,
3831116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    blink::WebIDBCursorDirection direction,
38320529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    leveldb::Status* s) {
3833eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  IDB_TRACE("IndexedDBBackingStore::OpenIndexKeyCursor");
38340529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  *s = leveldb::Status::OK();
38354e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  LevelDBTransaction* leveldb_transaction = transaction->transaction();
3836868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  IndexedDBBackingStore::Cursor::CursorOptions cursor_options;
3837868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (!IndexCursorOptions(leveldb_transaction,
3838868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                          database_id,
3839868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                          object_store_id,
3840868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                          index_id,
3841868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                          range,
3842868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                          direction,
3843868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                          &cursor_options))
3844868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return scoped_ptr<IndexedDBBackingStore::Cursor>();
3845868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  scoped_ptr<IndexKeyCursorImpl> cursor(
3846cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      new IndexKeyCursorImpl(this, transaction, database_id, cursor_options));
38470529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  if (!cursor->FirstSeek(s))
3848868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return scoped_ptr<IndexedDBBackingStore::Cursor>();
3849868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
3850868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  return cursor.PassAs<IndexedDBBackingStore::Cursor>();
3851868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
3852868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
3853868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)scoped_ptr<IndexedDBBackingStore::Cursor>
3854868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)IndexedDBBackingStore::OpenIndexCursor(
3855868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    IndexedDBBackingStore::Transaction* transaction,
3856868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    int64 database_id,
3857868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    int64 object_store_id,
3858868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    int64 index_id,
3859868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    const IndexedDBKeyRange& range,
3860116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    blink::WebIDBCursorDirection direction,
38610529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    leveldb::Status* s) {
3862eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  IDB_TRACE("IndexedDBBackingStore::OpenIndexCursor");
38634e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  LevelDBTransaction* leveldb_transaction = transaction->transaction();
3864868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  IndexedDBBackingStore::Cursor::CursorOptions cursor_options;
3865868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (!IndexCursorOptions(leveldb_transaction,
3866868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                          database_id,
3867868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                          object_store_id,
3868868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                          index_id,
3869868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                          range,
3870868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                          direction,
3871868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                          &cursor_options))
3872868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return scoped_ptr<IndexedDBBackingStore::Cursor>();
3873868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  scoped_ptr<IndexCursorImpl> cursor(
3874cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      new IndexCursorImpl(this, transaction, database_id, cursor_options));
38750529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  if (!cursor->FirstSeek(s))
3876868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return scoped_ptr<IndexedDBBackingStore::Cursor>();
3877868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
3878868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  return cursor.PassAs<IndexedDBBackingStore::Cursor>();
3879868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
3880868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
3881868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)IndexedDBBackingStore::Transaction::Transaction(
3882868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    IndexedDBBackingStore* backing_store)
3883cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    : backing_store_(backing_store), database_id_(-1) {
3884cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
3885868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
38860529e5d033099cbfc42635f6f6183833b09dff6eBen MurdochIndexedDBBackingStore::Transaction::~Transaction() {
38870529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  STLDeleteContainerPairSecondPointers(
38880529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch      blob_change_map_.begin(), blob_change_map_.end());
3889cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  STLDeleteContainerPairSecondPointers(incognito_blob_map_.begin(),
3890cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                                       incognito_blob_map_.end());
38910529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch}
3892868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
3893eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochvoid IndexedDBBackingStore::Transaction::Begin() {
3894eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  IDB_TRACE("IndexedDBBackingStore::Transaction::Begin");
38957d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  DCHECK(!transaction_.get());
3896f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  transaction_ = IndexedDBClassFactory::Get()->CreateLevelDBTransaction(
3897f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      backing_store_->db_.get());
3898cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
3899cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // If incognito, this snapshots blobs just as the above transaction_
3900cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // constructor snapshots the leveldb.
3901cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  BlobChangeMap::const_iterator iter;
3902cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  for (iter = backing_store_->incognito_blob_map_.begin();
3903cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)       iter != backing_store_->incognito_blob_map_.end();
3904cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)       ++iter)
3905cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    incognito_blob_map_[iter->first] = iter->second->Clone().release();
3906868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
3907868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
390846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)static GURL getURLFromUUID(const string& uuid) {
390946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  return GURL("blob:uuid/" + uuid);
391046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)}
391146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
391246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)leveldb::Status IndexedDBBackingStore::Transaction::HandleBlobPreTransaction(
391346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    BlobEntryKeyValuePairVec* new_blob_entries,
391446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    WriteDescriptorVec* new_files_to_write) {
391546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  if (backing_store_->is_incognito())
391646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    return leveldb::Status::OK();
391746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
391846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  BlobChangeMap::iterator iter = blob_change_map_.begin();
391946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  new_blob_entries->clear();
392046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  new_files_to_write->clear();
392146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  if (iter != blob_change_map_.end()) {
392246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    // Create LevelDBTransaction for the name generator seed and add-journal.
392346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    scoped_refptr<LevelDBTransaction> pre_transaction =
3924f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)        IndexedDBClassFactory::Get()->CreateLevelDBTransaction(
3925f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)            backing_store_->db_.get());
392646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    BlobJournalType journal;
392746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    for (; iter != blob_change_map_.end(); ++iter) {
392846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      std::vector<IndexedDBBlobInfo>::iterator info_iter;
392946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      std::vector<IndexedDBBlobInfo*> new_blob_keys;
393046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      for (info_iter = iter->second->mutable_blob_info().begin();
393146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)           info_iter != iter->second->mutable_blob_info().end();
393246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)           ++info_iter) {
393346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)        int64 next_blob_key = -1;
393446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)        bool result = GetBlobKeyGeneratorCurrentNumber(
393546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)            pre_transaction.get(), database_id_, &next_blob_key);
393646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)        if (!result || next_blob_key < 0)
393746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)          return InternalInconsistencyStatus();
393846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)        BlobJournalEntryType journal_entry =
393946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)            std::make_pair(database_id_, next_blob_key);
394046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)        journal.push_back(journal_entry);
394146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)        if (info_iter->is_file()) {
394246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)          new_files_to_write->push_back(
39436d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)              WriteDescriptor(info_iter->file_path(),
39446d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)                              next_blob_key,
39456d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)                              info_iter->size(),
39466d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)                              info_iter->last_modified()));
394746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)        } else {
39486d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)          new_files_to_write->push_back(
39496d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)              WriteDescriptor(getURLFromUUID(info_iter->uuid()),
39506d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)                              next_blob_key,
39516d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)                              info_iter->size()));
395246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)        }
395346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)        info_iter->set_key(next_blob_key);
395446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)        new_blob_keys.push_back(&*info_iter);
395546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)        result = UpdateBlobKeyGeneratorCurrentNumber(
395646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)            pre_transaction.get(), database_id_, next_blob_key + 1);
395746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)        if (!result)
395846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)          return InternalInconsistencyStatus();
395946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      }
396046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      BlobEntryKey blob_entry_key;
396146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      StringPiece key_piece(iter->second->key());
396246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      if (!BlobEntryKey::FromObjectStoreDataKey(&key_piece, &blob_entry_key)) {
396346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)        NOTREACHED();
396446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)        return InternalInconsistencyStatus();
396546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      }
396646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      new_blob_entries->push_back(
396746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)          std::make_pair(blob_entry_key, EncodeBlobData(new_blob_keys)));
396846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    }
396946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    UpdatePrimaryJournalWithBlobList(pre_transaction.get(), journal);
397046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    leveldb::Status s = pre_transaction->Commit();
397146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    if (!s.ok())
397246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      return InternalInconsistencyStatus();
397346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  }
397446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  return leveldb::Status::OK();
397546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)}
397646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
397746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)bool IndexedDBBackingStore::Transaction::CollectBlobFilesToRemove() {
397846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  if (backing_store_->is_incognito())
397946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    return true;
398046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
398146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  BlobChangeMap::const_iterator iter = blob_change_map_.begin();
398246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  // Look up all old files to remove as part of the transaction, store their
398346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  // names in blobs_to_remove_, and remove their old blob data entries.
398446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  if (iter != blob_change_map_.end()) {
398546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    for (; iter != blob_change_map_.end(); ++iter) {
398646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      BlobEntryKey blob_entry_key;
398746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      StringPiece key_piece(iter->second->key());
398846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      if (!BlobEntryKey::FromObjectStoreDataKey(&key_piece, &blob_entry_key)) {
398946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)        NOTREACHED();
399046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)        INTERNAL_WRITE_ERROR_UNTESTED(TRANSACTION_COMMIT_METHOD);
399146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)        transaction_ = NULL;
399246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)        return false;
399346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      }
399446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      if (database_id_ < 0)
399546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)        database_id_ = blob_entry_key.database_id();
399646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      else
399746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)        DCHECK_EQ(database_id_, blob_entry_key.database_id());
399846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      std::string blob_entry_key_bytes = blob_entry_key.Encode();
39991320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      bool found;
40001320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      std::string blob_entry_value_bytes;
40011320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      leveldb::Status s = transaction_->Get(
40021320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci          blob_entry_key_bytes, &blob_entry_value_bytes, &found);
40031320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      if (s.ok() && found) {
400446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)        std::vector<IndexedDBBlobInfo> blob_info;
40051320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        if (!DecodeBlobData(blob_entry_value_bytes, &blob_info)) {
400646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)          INTERNAL_READ_ERROR_UNTESTED(TRANSACTION_COMMIT_METHOD);
400746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)          transaction_ = NULL;
400846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)          return false;
400946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)        }
401046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)        std::vector<IndexedDBBlobInfo>::iterator blob_info_iter;
401146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)        for (blob_info_iter = blob_info.begin();
401246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)             blob_info_iter != blob_info.end();
401346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)             ++blob_info_iter)
401446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)          blobs_to_remove_.push_back(
401546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)              std::make_pair(database_id_, blob_info_iter->key()));
401646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)        transaction_->Remove(blob_entry_key_bytes);
401746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      }
401846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    }
401946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  }
402046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  return true;
402146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)}
402246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
402346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)leveldb::Status IndexedDBBackingStore::Transaction::SortBlobsToRemove() {
402446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  IndexedDBActiveBlobRegistry* registry =
402546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      backing_store_->active_blob_registry();
402646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  BlobJournalType::iterator iter;
402746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  BlobJournalType primary_journal, live_blob_journal;
402846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  for (iter = blobs_to_remove_.begin(); iter != blobs_to_remove_.end();
402946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)       ++iter) {
403046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    if (registry->MarkDeletedCheckIfUsed(iter->first, iter->second))
403146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      live_blob_journal.push_back(*iter);
403246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    else
403346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      primary_journal.push_back(*iter);
403446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  }
403546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  UpdatePrimaryJournalWithBlobList(transaction_.get(), primary_journal);
403646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  leveldb::Status s =
403746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      MergeBlobsIntoLiveBlobJournal(transaction_.get(), live_blob_journal);
403846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  if (!s.ok())
403946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    return s;
404046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  // To signal how many blobs need attention right now.
404146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  blobs_to_remove_.swap(primary_journal);
404246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  return leveldb::Status::OK();
404346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)}
404446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
404546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)leveldb::Status IndexedDBBackingStore::Transaction::CommitPhaseOne(
404646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    scoped_refptr<BlobWriteCallback> callback) {
404746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  IDB_TRACE("IndexedDBBackingStore::Transaction::CommitPhaseOne");
40481320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  DCHECK(transaction_.get());
404946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  DCHECK(backing_store_->task_runner()->RunsTasksOnCurrentThread());
405046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
405146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  leveldb::Status s;
405246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
405346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  s = backing_store_->CleanUpBlobJournal(BlobJournalKey::Encode());
405446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  if (!s.ok()) {
4055116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    INTERNAL_WRITE_ERROR(TRANSACTION_COMMIT_METHOD);
405646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    transaction_ = NULL;
405746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    return s;
405846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  }
405946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
406046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  BlobEntryKeyValuePairVec new_blob_entries;
406146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  WriteDescriptorVec new_files_to_write;
406246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  s = HandleBlobPreTransaction(&new_blob_entries, &new_files_to_write);
406346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  if (!s.ok()) {
406446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    INTERNAL_WRITE_ERROR_UNTESTED(TRANSACTION_COMMIT_METHOD);
406546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    transaction_ = NULL;
406646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    return s;
406746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  }
406846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
406946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  DCHECK(!new_files_to_write.size() ||
407046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)         KeyPrefix::IsValidDatabaseId(database_id_));
407146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  if (!CollectBlobFilesToRemove()) {
407246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    INTERNAL_WRITE_ERROR_UNTESTED(TRANSACTION_COMMIT_METHOD);
407346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    transaction_ = NULL;
407446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    return InternalInconsistencyStatus();
407546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  }
407646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
407746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  if (new_files_to_write.size()) {
407846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    // This kicks off the writes of the new blobs, if any.
407946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    // This call will zero out new_blob_entries and new_files_to_write.
40805f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    WriteNewBlobs(&new_blob_entries, &new_files_to_write, callback);
408146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    // Remove the add journal, if any; once the blobs are written, and we
408246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    // commit, this will do the cleanup.
408346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    ClearBlobJournal(transaction_.get(), BlobJournalKey::Encode());
408446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  } else {
408546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    callback->Run(true);
408646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  }
408746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
408846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  return leveldb::Status::OK();
408946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)}
409046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
409146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)leveldb::Status IndexedDBBackingStore::Transaction::CommitPhaseTwo() {
409246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  IDB_TRACE("IndexedDBBackingStore::Transaction::CommitPhaseTwo");
409346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  leveldb::Status s;
409446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  if (blobs_to_remove_.size()) {
409546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    s = SortBlobsToRemove();
409646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    if (!s.ok()) {
409746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      INTERNAL_READ_ERROR_UNTESTED(TRANSACTION_COMMIT_METHOD);
409846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      transaction_ = NULL;
409946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      return s;
410046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    }
410146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  }
410246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
410346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  s = transaction_->Commit();
4104868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  transaction_ = NULL;
4105cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
4106cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (s.ok() && backing_store_->is_incognito() && !blob_change_map_.empty()) {
4107cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    BlobChangeMap& target_map = backing_store_->incognito_blob_map_;
4108cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    BlobChangeMap::iterator iter;
4109cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    for (iter = blob_change_map_.begin(); iter != blob_change_map_.end();
4110cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)         ++iter) {
4111cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      BlobChangeMap::iterator target_record = target_map.find(iter->first);
4112cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      if (target_record != target_map.end()) {
4113cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        delete target_record->second;
4114cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        target_map.erase(target_record);
4115cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      }
4116cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      if (iter->second) {
4117cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        target_map[iter->first] = iter->second;
4118cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        iter->second = NULL;
4119cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      }
4120cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    }
4121cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  }
4122a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  if (!s.ok())
4123116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    INTERNAL_WRITE_ERROR(TRANSACTION_COMMIT_METHOD);
412446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  else if (blobs_to_remove_.size())
412546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    s = backing_store_->CleanUpBlobJournal(BlobJournalKey::Encode());
412646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
4127a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  return s;
4128868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
4129868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
41305c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
41315c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liuclass IndexedDBBackingStore::Transaction::BlobWriteCallbackWrapper
41325c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    : public IndexedDBBackingStore::BlobWriteCallback {
41335c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu public:
41345c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  BlobWriteCallbackWrapper(IndexedDBBackingStore::Transaction* transaction,
41355c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu                           scoped_refptr<BlobWriteCallback> callback)
41365c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      : transaction_(transaction), callback_(callback) {}
41375c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  virtual void Run(bool succeeded) OVERRIDE {
41385c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    callback_->Run(succeeded);
41396d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)    if (succeeded)  // Else it's already been deleted during rollback.
41406d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)      transaction_->chained_blob_writer_ = NULL;
41415c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  }
41425c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
41435c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu private:
41445c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  virtual ~BlobWriteCallbackWrapper() {}
41455c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  friend class base::RefCounted<IndexedDBBackingStore::BlobWriteCallback>;
41465c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
41475c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  IndexedDBBackingStore::Transaction* transaction_;
41485c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  scoped_refptr<BlobWriteCallback> callback_;
4149f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
4150f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(BlobWriteCallbackWrapper);
41515c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu};
41525c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
41535c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liuvoid IndexedDBBackingStore::Transaction::WriteNewBlobs(
41545f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    BlobEntryKeyValuePairVec* new_blob_entries,
41555f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    WriteDescriptorVec* new_files_to_write,
41565c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    scoped_refptr<BlobWriteCallback> callback) {
41575f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  DCHECK_GT(new_files_to_write->size(), 0UL);
41585c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  DCHECK_GT(database_id_, 0);
41595c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  BlobEntryKeyValuePairVec::iterator blob_entry_iter;
41605f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  for (blob_entry_iter = new_blob_entries->begin();
41615f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)       blob_entry_iter != new_blob_entries->end();
41625c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu       ++blob_entry_iter) {
41635c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    // Add the new blob-table entry for each blob to the main transaction, or
41645c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    // remove any entry that may exist if there's no new one.
41655c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    if (!blob_entry_iter->second.size())
41665c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      transaction_->Remove(blob_entry_iter->first.Encode());
41675c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    else
41685c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      transaction_->Put(blob_entry_iter->first.Encode(),
41695c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu                        &blob_entry_iter->second);
41705c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  }
41715c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  // Creating the writer will start it going asynchronously.
41725c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  chained_blob_writer_ =
41735c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      new ChainedBlobWriterImpl(database_id_,
41745c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu                                backing_store_,
41755c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu                                new_files_to_write,
41765c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu                                new BlobWriteCallbackWrapper(this, callback));
41775c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu}
41785c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
4179868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void IndexedDBBackingStore::Transaction::Rollback() {
4180eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  IDB_TRACE("IndexedDBBackingStore::Transaction::Rollback");
41811320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (chained_blob_writer_.get()) {
41825c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    chained_blob_writer_->Abort();
41835c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    chained_blob_writer_ = NULL;
41845c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  }
4185116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  if (transaction_.get() == NULL)
4186116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    return;
4187868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  transaction_->Rollback();
4188868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  transaction_ = NULL;
4189868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
4190868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
4191cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)IndexedDBBackingStore::BlobChangeRecord::BlobChangeRecord(
4192cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    const std::string& key,
4193cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    int64 object_store_id)
41940529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    : key_(key), object_store_id_(object_store_id) {
41950529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch}
41960529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch
4197cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)IndexedDBBackingStore::BlobChangeRecord::~BlobChangeRecord() {
41980529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch}
41990529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch
4200cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void IndexedDBBackingStore::BlobChangeRecord::SetBlobInfo(
42010529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    std::vector<IndexedDBBlobInfo>* blob_info) {
42020529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  blob_info_.clear();
42030529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  if (blob_info)
42040529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    blob_info_.swap(*blob_info);
42050529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch}
42060529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch
4207cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void IndexedDBBackingStore::BlobChangeRecord::SetHandles(
420803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    ScopedVector<storage::BlobDataHandle>* handles) {
42090529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  handles_.clear();
42100529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  if (handles)
42110529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    handles_.swap(*handles);
42120529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch}
42130529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch
4214cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)scoped_ptr<IndexedDBBackingStore::BlobChangeRecord>
4215cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)IndexedDBBackingStore::BlobChangeRecord::Clone() const {
4216cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  scoped_ptr<IndexedDBBackingStore::BlobChangeRecord> record(
4217cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      new BlobChangeRecord(key_, object_store_id_));
4218cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  record->blob_info_ = blob_info_;
4219cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
422003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  ScopedVector<storage::BlobDataHandle>::const_iterator iter;
4221cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  for (iter = handles_.begin(); iter != handles_.end(); ++iter)
422203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    record->handles_.push_back(new storage::BlobDataHandle(**iter));
4223cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  return record.Pass();
4224cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
4225cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
4226f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)leveldb::Status IndexedDBBackingStore::Transaction::PutBlobInfoIfNeeded(
4227f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    int64 database_id,
4228f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    int64 object_store_id,
4229f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    const std::string& object_store_data_key,
4230f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    std::vector<IndexedDBBlobInfo>* blob_info,
423103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    ScopedVector<storage::BlobDataHandle>* handles) {
4232f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  if (!blob_info || blob_info->empty()) {
4233f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    blob_change_map_.erase(object_store_data_key);
4234f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    incognito_blob_map_.erase(object_store_data_key);
4235f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
4236f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    BlobEntryKey blob_entry_key;
4237f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    StringPiece leveldb_key_piece(object_store_data_key);
4238f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    if (!BlobEntryKey::FromObjectStoreDataKey(&leveldb_key_piece,
4239f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                                              &blob_entry_key)) {
4240f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      NOTREACHED();
4241f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      return InternalInconsistencyStatus();
4242f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    }
4243f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    std::string value;
4244f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    bool found = false;
4245f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    leveldb::Status s =
4246f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)        transaction()->Get(blob_entry_key.Encode(), &value, &found);
4247f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    if (!s.ok())
4248f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      return s;
4249f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    if (!found)
4250f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      return leveldb::Status::OK();
4251f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  }
4252f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  PutBlobInfo(
4253f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      database_id, object_store_id, object_store_data_key, blob_info, handles);
4254f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  return leveldb::Status::OK();
4255f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)}
4256f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
42570529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch// This is storing an info, even if empty, even if the previous key had no blob
42580529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch// info that we know of.  It duplicates a bunch of information stored in the
42590529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch// leveldb transaction, but only w.r.t. the user keys altered--we don't keep the
42600529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch// changes to exists or index keys here.
42610529e5d033099cbfc42635f6f6183833b09dff6eBen Murdochvoid IndexedDBBackingStore::Transaction::PutBlobInfo(
42620529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    int64 database_id,
42630529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    int64 object_store_id,
4264cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    const std::string& object_store_data_key,
42650529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    std::vector<IndexedDBBlobInfo>* blob_info,
426603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    ScopedVector<storage::BlobDataHandle>* handles) {
4267cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  DCHECK_GT(object_store_data_key.size(), 0UL);
42680529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  if (database_id_ < 0)
42690529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    database_id_ = database_id;
42700529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  DCHECK_EQ(database_id_, database_id);
42710529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch
4272cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  BlobChangeMap::iterator it = blob_change_map_.find(object_store_data_key);
42730529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  BlobChangeRecord* record = NULL;
42740529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  if (it == blob_change_map_.end()) {
4275cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    record = new BlobChangeRecord(object_store_data_key, object_store_id);
4276cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    blob_change_map_[object_store_data_key] = record;
42770529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  } else {
42780529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    record = it->second;
42790529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  }
42800529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  DCHECK_EQ(record->object_store_id(), object_store_id);
42810529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  record->SetBlobInfo(blob_info);
42820529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  record->SetHandles(handles);
42830529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  DCHECK(!handles || !handles->size());
42840529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch}
42850529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch
42865c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo LiuIndexedDBBackingStore::Transaction::WriteDescriptor::WriteDescriptor(
42875c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    const GURL& url,
42886d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)    int64_t key,
42896d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)    int64_t size)
42906d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)    : is_file_(false), url_(url), key_(key), size_(size) {
42916d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)}
42925c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
42935c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo LiuIndexedDBBackingStore::Transaction::WriteDescriptor::WriteDescriptor(
42945c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    const FilePath& file_path,
42956d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)    int64_t key,
42966d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)    int64_t size,
42976d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)    base::Time last_modified)
42986d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)    : is_file_(true),
42996d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)      file_path_(file_path),
43006d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)      key_(key),
43016d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)      size_(size),
43026d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)      last_modified_(last_modified) {
43036d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)}
43045c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
4305868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}  // namespace content
4306