Revert 268405 "Make sure that ScratchBuffer::Allocate() always r..."
[chromium-blink-merge.git] / content / browser / indexed_db / indexed_db_backing_store.h
blob386e296c3aacfbf544f413186dec4933f8b199fd
1 // Copyright (c) 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #ifndef CONTENT_BROWSER_INDEXED_DB_INDEXED_DB_BACKING_STORE_H_
6 #define CONTENT_BROWSER_INDEXED_DB_INDEXED_DB_BACKING_STORE_H_
8 #include <set>
9 #include <string>
10 #include <vector>
12 #include "base/basictypes.h"
13 #include "base/files/file_path.h"
14 #include "base/memory/ref_counted.h"
15 #include "base/memory/scoped_ptr.h"
16 #include "base/strings/string_piece.h"
17 #include "base/timer/timer.h"
18 #include "content/browser/indexed_db/indexed_db.h"
19 #include "content/browser/indexed_db/indexed_db_active_blob_registry.h"
20 #include "content/browser/indexed_db/indexed_db_blob_info.h"
21 #include "content/browser/indexed_db/indexed_db_leveldb_coding.h"
22 #include "content/browser/indexed_db/indexed_db_metadata.h"
23 #include "content/browser/indexed_db/leveldb/leveldb_iterator.h"
24 #include "content/browser/indexed_db/leveldb/leveldb_transaction.h"
25 #include "content/common/content_export.h"
26 #include "content/common/indexed_db/indexed_db_key.h"
27 #include "content/common/indexed_db/indexed_db_key_path.h"
28 #include "content/common/indexed_db/indexed_db_key_range.h"
29 #include "third_party/leveldatabase/src/include/leveldb/status.h"
30 #include "url/gurl.h"
31 #include "webkit/browser/blob/blob_data_handle.h"
33 namespace base {
34 class TaskRunner;
37 namespace fileapi {
38 class FileWriterDelegate;
41 namespace net {
42 class URLRequestContext;
45 namespace content {
47 class IndexedDBFactory;
48 class LevelDBComparator;
49 class LevelDBDatabase;
50 struct IndexedDBValue;
52 class LevelDBFactory {
53 public:
54 virtual ~LevelDBFactory() {}
55 virtual leveldb::Status OpenLevelDB(const base::FilePath& file_name,
56 const LevelDBComparator* comparator,
57 scoped_ptr<LevelDBDatabase>* db,
58 bool* is_disk_full) = 0;
59 virtual leveldb::Status DestroyLevelDB(const base::FilePath& file_name) = 0;
62 class CONTENT_EXPORT IndexedDBBackingStore
63 : public base::RefCounted<IndexedDBBackingStore> {
64 public:
65 class CONTENT_EXPORT Transaction;
67 class Comparator : public LevelDBComparator {
68 public:
69 virtual int Compare(const base::StringPiece& a,
70 const base::StringPiece& b) const OVERRIDE;
71 virtual const char* Name() const OVERRIDE;
74 const GURL& origin_url() const { return origin_url_; }
75 IndexedDBFactory* factory() const { return indexed_db_factory_; }
76 base::TaskRunner* task_runner() const { return task_runner_; }
77 base::OneShotTimer<IndexedDBBackingStore>* close_timer() {
78 return &close_timer_;
80 IndexedDBActiveBlobRegistry* active_blob_registry() {
81 return &active_blob_registry_;
84 static scoped_refptr<IndexedDBBackingStore> Open(
85 IndexedDBFactory* indexed_db_factory,
86 const GURL& origin_url,
87 const base::FilePath& path_base,
88 net::URLRequestContext* request_context,
89 blink::WebIDBDataLoss* data_loss,
90 std::string* data_loss_message,
91 bool* disk_full,
92 base::TaskRunner* task_runner,
93 bool clean_journal);
94 static scoped_refptr<IndexedDBBackingStore> Open(
95 IndexedDBFactory* indexed_db_factory,
96 const GURL& origin_url,
97 const base::FilePath& path_base,
98 net::URLRequestContext* request_context,
99 blink::WebIDBDataLoss* data_loss,
100 std::string* data_loss_message,
101 bool* disk_full,
102 LevelDBFactory* leveldb_factory,
103 base::TaskRunner* task_runner,
104 bool clean_journal);
105 static scoped_refptr<IndexedDBBackingStore> OpenInMemory(
106 const GURL& origin_url,
107 base::TaskRunner* task_runner);
108 static scoped_refptr<IndexedDBBackingStore> OpenInMemory(
109 const GURL& origin_url,
110 LevelDBFactory* level_db_factory,
111 base::TaskRunner* task_runner);
113 void GrantChildProcessPermissions(int child_process_id);
115 // Compact is public for testing.
116 virtual void Compact();
117 virtual std::vector<base::string16> GetDatabaseNames(leveldb::Status*);
118 virtual leveldb::Status GetIDBDatabaseMetaData(
119 const base::string16& name,
120 IndexedDBDatabaseMetadata* metadata,
121 bool* success) WARN_UNUSED_RESULT;
122 virtual leveldb::Status CreateIDBDatabaseMetaData(
123 const base::string16& name,
124 const base::string16& version,
125 int64 int_version,
126 int64* row_id);
127 virtual bool UpdateIDBDatabaseIntVersion(
128 IndexedDBBackingStore::Transaction* transaction,
129 int64 row_id,
130 int64 int_version);
131 virtual leveldb::Status DeleteDatabase(const base::string16& name);
133 // Assumes caller has already closed the backing store.
134 static leveldb::Status DestroyBackingStore(const base::FilePath& path_base,
135 const GURL& origin_url);
136 static bool RecordCorruptionInfo(const base::FilePath& path_base,
137 const GURL& origin_url,
138 const std::string& message);
139 leveldb::Status GetObjectStores(
140 int64 database_id,
141 IndexedDBDatabaseMetadata::ObjectStoreMap* map) WARN_UNUSED_RESULT;
142 virtual leveldb::Status CreateObjectStore(
143 IndexedDBBackingStore::Transaction* transaction,
144 int64 database_id,
145 int64 object_store_id,
146 const base::string16& name,
147 const IndexedDBKeyPath& key_path,
148 bool auto_increment);
149 virtual leveldb::Status DeleteObjectStore(
150 IndexedDBBackingStore::Transaction* transaction,
151 int64 database_id,
152 int64 object_store_id) WARN_UNUSED_RESULT;
154 class CONTENT_EXPORT RecordIdentifier {
155 public:
156 RecordIdentifier(const std::string& primary_key, int64 version);
157 RecordIdentifier();
158 ~RecordIdentifier();
160 const std::string& primary_key() const { return primary_key_; }
161 int64 version() const { return version_; }
162 void Reset(const std::string& primary_key, int64 version) {
163 primary_key_ = primary_key;
164 version_ = version;
167 private:
168 // TODO(jsbell): Make it more clear that this is the *encoded* version of
169 // the key.
170 std::string primary_key_;
171 int64 version_;
172 DISALLOW_COPY_AND_ASSIGN(RecordIdentifier);
175 class BlobWriteCallback : public base::RefCounted<BlobWriteCallback> {
176 public:
177 virtual void Run(bool succeeded) = 0;
178 protected:
179 virtual ~BlobWriteCallback() {}
180 friend class base::RefCounted<BlobWriteCallback>;
183 virtual leveldb::Status GetRecord(
184 IndexedDBBackingStore::Transaction* transaction,
185 int64 database_id,
186 int64 object_store_id,
187 const IndexedDBKey& key,
188 IndexedDBValue* record) WARN_UNUSED_RESULT;
189 virtual leveldb::Status PutRecord(
190 IndexedDBBackingStore::Transaction* transaction,
191 int64 database_id,
192 int64 object_store_id,
193 const IndexedDBKey& key,
194 IndexedDBValue& value,
195 ScopedVector<webkit_blob::BlobDataHandle>* handles,
196 RecordIdentifier* record) WARN_UNUSED_RESULT;
197 virtual leveldb::Status ClearObjectStore(
198 IndexedDBBackingStore::Transaction* transaction,
199 int64 database_id,
200 int64 object_store_id) WARN_UNUSED_RESULT;
201 virtual leveldb::Status DeleteRecord(
202 IndexedDBBackingStore::Transaction* transaction,
203 int64 database_id,
204 int64 object_store_id,
205 const RecordIdentifier& record) WARN_UNUSED_RESULT;
206 virtual leveldb::Status GetKeyGeneratorCurrentNumber(
207 IndexedDBBackingStore::Transaction* transaction,
208 int64 database_id,
209 int64 object_store_id,
210 int64* current_number) WARN_UNUSED_RESULT;
211 virtual leveldb::Status MaybeUpdateKeyGeneratorCurrentNumber(
212 IndexedDBBackingStore::Transaction* transaction,
213 int64 database_id,
214 int64 object_store_id,
215 int64 new_state,
216 bool check_current) WARN_UNUSED_RESULT;
217 virtual leveldb::Status KeyExistsInObjectStore(
218 IndexedDBBackingStore::Transaction* transaction,
219 int64 database_id,
220 int64 object_store_id,
221 const IndexedDBKey& key,
222 RecordIdentifier* found_record_identifier,
223 bool* found) WARN_UNUSED_RESULT;
225 virtual leveldb::Status CreateIndex(
226 IndexedDBBackingStore::Transaction* transaction,
227 int64 database_id,
228 int64 object_store_id,
229 int64 index_id,
230 const base::string16& name,
231 const IndexedDBKeyPath& key_path,
232 bool is_unique,
233 bool is_multi_entry) WARN_UNUSED_RESULT;
234 virtual leveldb::Status DeleteIndex(
235 IndexedDBBackingStore::Transaction* transaction,
236 int64 database_id,
237 int64 object_store_id,
238 int64 index_id) WARN_UNUSED_RESULT;
239 virtual leveldb::Status PutIndexDataForRecord(
240 IndexedDBBackingStore::Transaction* transaction,
241 int64 database_id,
242 int64 object_store_id,
243 int64 index_id,
244 const IndexedDBKey& key,
245 const RecordIdentifier& record) WARN_UNUSED_RESULT;
246 virtual leveldb::Status GetPrimaryKeyViaIndex(
247 IndexedDBBackingStore::Transaction* transaction,
248 int64 database_id,
249 int64 object_store_id,
250 int64 index_id,
251 const IndexedDBKey& key,
252 scoped_ptr<IndexedDBKey>* primary_key) WARN_UNUSED_RESULT;
253 virtual leveldb::Status KeyExistsInIndex(
254 IndexedDBBackingStore::Transaction* transaction,
255 int64 database_id,
256 int64 object_store_id,
257 int64 index_id,
258 const IndexedDBKey& key,
259 scoped_ptr<IndexedDBKey>* found_primary_key,
260 bool* exists) WARN_UNUSED_RESULT;
262 // Public for IndexedDBActiveBlobRegistry::ReleaseBlobRef.
263 virtual void ReportBlobUnused(int64 database_id, int64 blob_key);
265 base::FilePath GetBlobFileName(int64 database_id, int64 key);
267 class Cursor {
268 public:
269 virtual ~Cursor();
271 enum IteratorState {
272 READY = 0,
273 SEEK
276 struct CursorOptions {
277 CursorOptions();
278 ~CursorOptions();
279 int64 database_id;
280 int64 object_store_id;
281 int64 index_id;
282 std::string low_key;
283 bool low_open;
284 std::string high_key;
285 bool high_open;
286 bool forward;
287 bool unique;
290 const IndexedDBKey& key() const { return *current_key_; }
291 bool Continue(leveldb::Status* s) { return Continue(NULL, NULL, SEEK, s); }
292 bool Continue(const IndexedDBKey* key,
293 IteratorState state,
294 leveldb::Status* s) {
295 return Continue(key, NULL, state, s);
297 bool Continue(const IndexedDBKey* key,
298 const IndexedDBKey* primary_key,
299 IteratorState state,
300 leveldb::Status*);
301 bool Advance(uint32 count, leveldb::Status*);
302 bool FirstSeek(leveldb::Status*);
304 virtual Cursor* Clone() = 0;
305 virtual const IndexedDBKey& primary_key() const;
306 virtual IndexedDBValue* value() = 0;
307 virtual const RecordIdentifier& record_identifier() const;
308 virtual bool LoadCurrentRow() = 0;
310 protected:
311 Cursor(LevelDBTransaction* transaction,
312 const CursorOptions& cursor_options);
313 explicit Cursor(const IndexedDBBackingStore::Cursor* other);
315 virtual std::string EncodeKey(const IndexedDBKey& key) = 0;
316 virtual std::string EncodeKey(const IndexedDBKey& key,
317 const IndexedDBKey& primary_key) = 0;
319 bool IsPastBounds() const;
320 bool HaveEnteredRange() const;
322 LevelDBTransaction* transaction_;
323 const CursorOptions cursor_options_;
324 scoped_ptr<LevelDBIterator> iterator_;
325 scoped_ptr<IndexedDBKey> current_key_;
326 IndexedDBBackingStore::RecordIdentifier record_identifier_;
329 virtual scoped_ptr<Cursor> OpenObjectStoreKeyCursor(
330 IndexedDBBackingStore::Transaction* transaction,
331 int64 database_id,
332 int64 object_store_id,
333 const IndexedDBKeyRange& key_range,
334 indexed_db::CursorDirection,
335 leveldb::Status*);
336 virtual scoped_ptr<Cursor> OpenObjectStoreCursor(
337 IndexedDBBackingStore::Transaction* transaction,
338 int64 database_id,
339 int64 object_store_id,
340 const IndexedDBKeyRange& key_range,
341 indexed_db::CursorDirection,
342 leveldb::Status*);
343 virtual scoped_ptr<Cursor> OpenIndexKeyCursor(
344 IndexedDBBackingStore::Transaction* transaction,
345 int64 database_id,
346 int64 object_store_id,
347 int64 index_id,
348 const IndexedDBKeyRange& key_range,
349 indexed_db::CursorDirection,
350 leveldb::Status*);
351 virtual scoped_ptr<Cursor> OpenIndexCursor(
352 IndexedDBBackingStore::Transaction* transaction,
353 int64 database_id,
354 int64 object_store_id,
355 int64 index_id,
356 const IndexedDBKeyRange& key_range,
357 indexed_db::CursorDirection,
358 leveldb::Status*);
360 class Transaction {
361 public:
362 explicit Transaction(IndexedDBBackingStore* backing_store);
363 virtual ~Transaction();
364 virtual void Begin();
365 virtual leveldb::Status Commit();
366 virtual void Rollback();
367 void Reset() {
368 backing_store_ = NULL;
369 transaction_ = NULL;
371 void PutBlobInfo(int64 database_id,
372 int64 object_store_id,
373 const std::string& object_store_data_key,
374 std::vector<IndexedDBBlobInfo>*,
375 ScopedVector<webkit_blob::BlobDataHandle>* handles);
377 LevelDBTransaction* transaction() { return transaction_; }
379 // This holds a BlobEntryKey and the encoded IndexedDBBlobInfo vector stored
380 // under that key.
381 typedef std::vector<std::pair<BlobEntryKey, std::string> >
382 BlobEntryKeyValuePairVec;
384 class WriteDescriptor {
385 public:
386 WriteDescriptor(const GURL& url, int64_t key);
387 WriteDescriptor(const base::FilePath& path, int64_t key);
389 bool is_file() const { return is_file_; }
390 const GURL& url() const {
391 DCHECK(!is_file_);
392 return url_;
394 const base::FilePath& file_path() const {
395 DCHECK(is_file_);
396 return file_path_;
398 int64_t key() const { return key_; }
400 private:
401 bool is_file_;
402 GURL url_;
403 base::FilePath file_path_;
404 int64_t key_;
407 class ChainedBlobWriter : public base::RefCounted<ChainedBlobWriter> {
408 public:
409 virtual void set_delegate(
410 scoped_ptr<fileapi::FileWriterDelegate> delegate) = 0;
412 // TODO(ericu): Add a reason in the event of failure.
413 virtual void ReportWriteCompletion(bool succeeded,
414 int64 bytes_written) = 0;
416 virtual void Abort() = 0;
418 protected:
419 virtual ~ChainedBlobWriter() {}
420 friend class base::RefCounted<ChainedBlobWriter>;
422 class ChainedBlobWriterImpl;
424 typedef std::vector<WriteDescriptor> WriteDescriptorVec;
426 private:
427 class BlobChangeRecord {
428 public:
429 BlobChangeRecord(const std::string& key, int64 object_store_id);
430 ~BlobChangeRecord();
431 const std::string& key() const { return key_; }
432 int64 object_store_id() const { return object_store_id_; }
433 void SetBlobInfo(std::vector<IndexedDBBlobInfo>* blob_info);
434 std::vector<IndexedDBBlobInfo>& mutable_blob_info() { return blob_info_; }
435 void SetHandles(ScopedVector<webkit_blob::BlobDataHandle>* handles);
437 private:
438 std::string key_;
439 int64 object_store_id_;
440 std::vector<IndexedDBBlobInfo> blob_info_;
441 ScopedVector<webkit_blob::BlobDataHandle> handles_;
443 class BlobWriteCallbackWrapper;
444 typedef std::map<std::string, BlobChangeRecord*> BlobChangeMap;
446 // The callback will be called eventually on success or failure.
447 void WriteNewBlobs(BlobEntryKeyValuePairVec& new_blob_entries,
448 WriteDescriptorVec& new_files_to_write,
449 scoped_refptr<BlobWriteCallback> callback);
451 IndexedDBBackingStore* backing_store_;
452 scoped_refptr<LevelDBTransaction> transaction_;
453 BlobChangeMap blob_change_map_;
454 int64 database_id_;
455 scoped_refptr<ChainedBlobWriter> chained_blob_writer_;
458 protected:
459 IndexedDBBackingStore(IndexedDBFactory* indexed_db_factory,
460 const GURL& origin_url,
461 const base::FilePath& blob_path,
462 net::URLRequestContext* request_context,
463 scoped_ptr<LevelDBDatabase> db,
464 scoped_ptr<LevelDBComparator> comparator,
465 base::TaskRunner* task_runner);
466 virtual ~IndexedDBBackingStore();
467 friend class base::RefCounted<IndexedDBBackingStore>;
469 virtual bool WriteBlobFile(
470 int64 database_id,
471 const Transaction::WriteDescriptor& descriptor,
472 Transaction::ChainedBlobWriter* chained_blob_writer);
473 virtual bool RemoveBlobFile(int64 database_id, int64 key);
474 virtual void StartJournalCleaningTimer();
475 void CleanPrimaryJournalIgnoreReturn();
477 private:
478 static scoped_refptr<IndexedDBBackingStore> Create(
479 IndexedDBFactory* indexed_db_factory,
480 const GURL& origin_url,
481 const base::FilePath& blob_path,
482 net::URLRequestContext* request_context,
483 scoped_ptr<LevelDBDatabase> db,
484 scoped_ptr<LevelDBComparator> comparator,
485 base::TaskRunner* task_runner);
487 static bool ReadCorruptionInfo(const base::FilePath& path_base,
488 const GURL& origin_url,
489 std::string& message);
491 leveldb::Status FindKeyInIndex(
492 IndexedDBBackingStore::Transaction* transaction,
493 int64 database_id,
494 int64 object_store_id,
495 int64 index_id,
496 const IndexedDBKey& key,
497 std::string* found_encoded_primary_key,
498 bool* found);
499 leveldb::Status GetIndexes(int64 database_id,
500 int64 object_store_id,
501 IndexedDBObjectStoreMetadata::IndexMap* map)
502 WARN_UNUSED_RESULT;
503 bool RemoveBlobDirectory(int64 database_id);
504 leveldb::Status CleanUpBlobJournal(const std::string& level_db_key);
506 IndexedDBFactory* indexed_db_factory_;
507 const GURL origin_url_;
508 base::FilePath blob_path_;
510 // The origin identifier is a key prefix unique to the origin used in the
511 // leveldb backing store to partition data by origin. It is a normalized
512 // version of the origin URL with a versioning suffix appended, e.g.
513 // "http_localhost_81@1" Since only one origin is stored per backing store
514 // this is redundant but necessary for backwards compatibility; the suffix
515 // provides for future flexibility.
516 const std::string origin_identifier_;
518 net::URLRequestContext* request_context_;
519 base::TaskRunner* task_runner_;
520 std::set<int> child_process_ids_granted_;
521 base::OneShotTimer<IndexedDBBackingStore> journal_cleaning_timer_;
523 scoped_ptr<LevelDBDatabase> db_;
524 scoped_ptr<LevelDBComparator> comparator_;
525 // Whenever blobs are registered in active_blob_registry_, indexed_db_factory_
526 // will hold a reference to this backing store.
527 IndexedDBActiveBlobRegistry active_blob_registry_;
528 base::OneShotTimer<IndexedDBBackingStore> close_timer_;
531 } // namespace content
533 #endif // CONTENT_BROWSER_INDEXED_DB_INDEXED_DB_BACKING_STORE_H_