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_
14 #include "base/basictypes.h"
15 #include "base/files/file_path.h"
16 #include "base/memory/ref_counted.h"
17 #include "base/memory/scoped_ptr.h"
18 #include "base/strings/string_piece.h"
19 #include "base/time/time.h"
20 #include "base/timer/timer.h"
21 #include "content/browser/indexed_db/indexed_db.h"
22 #include "content/browser/indexed_db/indexed_db_active_blob_registry.h"
23 #include "content/browser/indexed_db/indexed_db_blob_info.h"
24 #include "content/browser/indexed_db/indexed_db_leveldb_coding.h"
25 #include "content/browser/indexed_db/indexed_db_metadata.h"
26 #include "content/browser/indexed_db/leveldb/leveldb_iterator.h"
27 #include "content/browser/indexed_db/leveldb/leveldb_transaction.h"
28 #include "content/common/content_export.h"
29 #include "content/common/indexed_db/indexed_db_key.h"
30 #include "content/common/indexed_db/indexed_db_key_path.h"
31 #include "content/common/indexed_db/indexed_db_key_range.h"
32 #include "third_party/leveldatabase/src/include/leveldb/status.h"
34 #include "webkit/browser/blob/blob_data_handle.h"
37 class SequencedTaskRunner
;
41 class FileWriterDelegate
;
45 class URLRequestContext
;
50 class IndexedDBFactory
;
51 class LevelDBComparator
;
52 class LevelDBDatabase
;
54 struct IndexedDBValue
;
56 class CONTENT_EXPORT IndexedDBBackingStore
57 : public base::RefCounted
<IndexedDBBackingStore
> {
59 class CONTENT_EXPORT Comparator
: public LevelDBComparator
{
61 virtual int Compare(const base::StringPiece
& a
,
62 const base::StringPiece
& b
) const OVERRIDE
;
63 virtual const char* Name() const OVERRIDE
;
66 class CONTENT_EXPORT RecordIdentifier
{
68 RecordIdentifier(const std::string
& primary_key
, int64 version
);
72 const std::string
& primary_key() const { return primary_key_
; }
73 int64
version() const { return version_
; }
74 void Reset(const std::string
& primary_key
, int64 version
) {
75 primary_key_
= primary_key
;
80 // TODO(jsbell): Make it more clear that this is the *encoded* version of
82 std::string primary_key_
;
84 DISALLOW_COPY_AND_ASSIGN(RecordIdentifier
);
87 class BlobWriteCallback
: public base::RefCounted
<BlobWriteCallback
> {
89 virtual void Run(bool succeeded
) = 0;
92 friend class base::RefCounted
<BlobWriteCallback
>;
93 virtual ~BlobWriteCallback() {}
96 class BlobChangeRecord
{
98 BlobChangeRecord(const std::string
& key
, int64 object_store_id
);
101 const std::string
& key() const { return key_
; }
102 int64
object_store_id() const { return object_store_id_
; }
103 void SetBlobInfo(std::vector
<IndexedDBBlobInfo
>* blob_info
);
104 std::vector
<IndexedDBBlobInfo
>& mutable_blob_info() { return blob_info_
; }
105 const std::vector
<IndexedDBBlobInfo
>& blob_info() const {
108 void SetHandles(ScopedVector
<storage::BlobDataHandle
>* handles
);
109 scoped_ptr
<BlobChangeRecord
> Clone() const;
113 int64 object_store_id_
;
114 std::vector
<IndexedDBBlobInfo
> blob_info_
;
115 ScopedVector
<storage::BlobDataHandle
> handles_
;
116 DISALLOW_COPY_AND_ASSIGN(BlobChangeRecord
);
118 typedef std::map
<std::string
, BlobChangeRecord
*> BlobChangeMap
;
120 class CONTENT_EXPORT Transaction
{
122 explicit Transaction(IndexedDBBackingStore
* backing_store
);
123 virtual ~Transaction();
125 virtual void Begin();
126 // The callback will be called eventually on success or failure, or
127 // immediately if phase one is complete due to lack of any blobs to write.
128 virtual leveldb::Status
CommitPhaseOne(scoped_refptr
<BlobWriteCallback
>);
129 virtual leveldb::Status
CommitPhaseTwo();
130 virtual void Rollback();
132 backing_store_
= NULL
;
135 leveldb::Status
PutBlobInfoIfNeeded(
137 int64 object_store_id
,
138 const std::string
& object_store_data_key
,
139 std::vector
<IndexedDBBlobInfo
>*,
140 ScopedVector
<storage::BlobDataHandle
>* handles
);
141 void PutBlobInfo(int64 database_id
,
142 int64 object_store_id
,
143 const std::string
& object_store_data_key
,
144 std::vector
<IndexedDBBlobInfo
>*,
145 ScopedVector
<storage::BlobDataHandle
>* handles
);
147 LevelDBTransaction
* transaction() { return transaction_
.get(); }
149 leveldb::Status
GetBlobInfoForRecord(
151 const std::string
& object_store_data_key
,
152 IndexedDBValue
* value
);
154 // This holds a BlobEntryKey and the encoded IndexedDBBlobInfo vector stored
156 typedef std::vector
<std::pair
<BlobEntryKey
, std::string
> >
157 BlobEntryKeyValuePairVec
;
159 class WriteDescriptor
{
161 WriteDescriptor(const GURL
& url
, int64_t key
, int64_t size
);
162 WriteDescriptor(const base::FilePath
& path
,
165 base::Time last_modified
);
167 bool is_file() const { return is_file_
; }
168 const GURL
& url() const {
172 const base::FilePath
& file_path() const {
176 int64_t key() const { return key_
; }
177 int64_t size() const { return size_
; }
178 base::Time
last_modified() const { return last_modified_
; }
183 base::FilePath file_path_
;
186 base::Time last_modified_
;
189 class ChainedBlobWriter
190 : public base::RefCountedThreadSafe
<ChainedBlobWriter
> {
192 virtual void set_delegate(
193 scoped_ptr
<storage::FileWriterDelegate
> delegate
) = 0;
195 // TODO(ericu): Add a reason in the event of failure.
196 virtual void ReportWriteCompletion(bool succeeded
,
197 int64 bytes_written
) = 0;
199 virtual void Abort() = 0;
202 friend class base::RefCountedThreadSafe
<ChainedBlobWriter
>;
203 virtual ~ChainedBlobWriter() {}
206 class ChainedBlobWriterImpl
;
208 typedef std::vector
<WriteDescriptor
> WriteDescriptorVec
;
211 class BlobWriteCallbackWrapper
;
213 leveldb::Status
HandleBlobPreTransaction(
214 BlobEntryKeyValuePairVec
* new_blob_entries
,
215 WriteDescriptorVec
* new_files_to_write
);
216 // Returns true on success, false on failure.
217 bool CollectBlobFilesToRemove();
218 // The callback will be called eventually on success or failure.
219 void WriteNewBlobs(BlobEntryKeyValuePairVec
* new_blob_entries
,
220 WriteDescriptorVec
* new_files_to_write
,
221 scoped_refptr
<BlobWriteCallback
> callback
);
222 leveldb::Status
SortBlobsToRemove();
224 IndexedDBBackingStore
* backing_store_
;
225 scoped_refptr
<LevelDBTransaction
> transaction_
;
226 BlobChangeMap blob_change_map_
;
227 BlobChangeMap incognito_blob_map_
;
229 BlobJournalType blobs_to_remove_
;
230 scoped_refptr
<ChainedBlobWriter
> chained_blob_writer_
;
235 enum IteratorState
{ READY
= 0, SEEK
};
239 struct CursorOptions
{
243 int64 object_store_id
;
247 std::string high_key
;
253 const IndexedDBKey
& key() const { return *current_key_
; }
254 bool Continue(leveldb::Status
* s
) { return Continue(NULL
, NULL
, SEEK
, s
); }
255 bool Continue(const IndexedDBKey
* key
,
257 leveldb::Status
* s
) {
258 return Continue(key
, NULL
, state
, s
);
260 bool Continue(const IndexedDBKey
* key
,
261 const IndexedDBKey
* primary_key
,
264 bool Advance(uint32 count
, leveldb::Status
*);
265 bool FirstSeek(leveldb::Status
*);
267 virtual Cursor
* Clone() = 0;
268 virtual const IndexedDBKey
& primary_key() const;
269 virtual IndexedDBValue
* value() = 0;
270 virtual const RecordIdentifier
& record_identifier() const;
271 virtual bool LoadCurrentRow() = 0;
274 Cursor(scoped_refptr
<IndexedDBBackingStore
> backing_store
,
275 Transaction
* transaction
,
277 const CursorOptions
& cursor_options
);
278 explicit Cursor(const IndexedDBBackingStore::Cursor
* other
);
280 virtual std::string
EncodeKey(const IndexedDBKey
& key
) = 0;
281 virtual std::string
EncodeKey(const IndexedDBKey
& key
,
282 const IndexedDBKey
& primary_key
) = 0;
284 bool IsPastBounds() const;
285 bool HaveEnteredRange() const;
287 IndexedDBBackingStore
* backing_store_
;
288 Transaction
* transaction_
;
290 const CursorOptions cursor_options_
;
291 scoped_ptr
<LevelDBIterator
> iterator_
;
292 scoped_ptr
<IndexedDBKey
> current_key_
;
293 IndexedDBBackingStore::RecordIdentifier record_identifier_
;
296 DISALLOW_COPY_AND_ASSIGN(Cursor
);
299 const GURL
& origin_url() const { return origin_url_
; }
300 IndexedDBFactory
* factory() const { return indexed_db_factory_
; }
301 base::SequencedTaskRunner
* task_runner() const { return task_runner_
.get(); }
302 base::OneShotTimer
<IndexedDBBackingStore
>* close_timer() {
303 return &close_timer_
;
305 IndexedDBActiveBlobRegistry
* active_blob_registry() {
306 return &active_blob_registry_
;
309 static scoped_refptr
<IndexedDBBackingStore
> Open(
310 IndexedDBFactory
* indexed_db_factory
,
311 const GURL
& origin_url
,
312 const base::FilePath
& path_base
,
313 net::URLRequestContext
* request_context
,
314 blink::WebIDBDataLoss
* data_loss
,
315 std::string
* data_loss_message
,
317 base::SequencedTaskRunner
* task_runner
,
319 leveldb::Status
* status
);
320 static scoped_refptr
<IndexedDBBackingStore
> Open(
321 IndexedDBFactory
* indexed_db_factory
,
322 const GURL
& origin_url
,
323 const base::FilePath
& path_base
,
324 net::URLRequestContext
* request_context
,
325 blink::WebIDBDataLoss
* data_loss
,
326 std::string
* data_loss_message
,
328 LevelDBFactory
* leveldb_factory
,
329 base::SequencedTaskRunner
* task_runner
,
331 leveldb::Status
* status
);
332 static scoped_refptr
<IndexedDBBackingStore
> OpenInMemory(
333 const GURL
& origin_url
,
334 base::SequencedTaskRunner
* task_runner
,
335 leveldb::Status
* status
);
336 static scoped_refptr
<IndexedDBBackingStore
> OpenInMemory(
337 const GURL
& origin_url
,
338 LevelDBFactory
* leveldb_factory
,
339 base::SequencedTaskRunner
* task_runner
,
340 leveldb::Status
* status
);
342 void GrantChildProcessPermissions(int child_process_id
);
344 // Compact is public for testing.
345 virtual void Compact();
346 virtual std::vector
<base::string16
> GetDatabaseNames(leveldb::Status
*);
347 virtual leveldb::Status
GetIDBDatabaseMetaData(
348 const base::string16
& name
,
349 IndexedDBDatabaseMetadata
* metadata
,
350 bool* success
) WARN_UNUSED_RESULT
;
351 virtual leveldb::Status
CreateIDBDatabaseMetaData(
352 const base::string16
& name
,
353 const base::string16
& version
,
356 virtual bool UpdateIDBDatabaseIntVersion(
357 IndexedDBBackingStore::Transaction
* transaction
,
360 virtual leveldb::Status
DeleteDatabase(const base::string16
& name
);
362 // Assumes caller has already closed the backing store.
363 static leveldb::Status
DestroyBackingStore(const base::FilePath
& path_base
,
364 const GURL
& origin_url
);
365 static bool RecordCorruptionInfo(const base::FilePath
& path_base
,
366 const GURL
& origin_url
,
367 const std::string
& message
);
368 leveldb::Status
GetObjectStores(
370 IndexedDBDatabaseMetadata::ObjectStoreMap
* map
) WARN_UNUSED_RESULT
;
371 virtual leveldb::Status
CreateObjectStore(
372 IndexedDBBackingStore::Transaction
* transaction
,
374 int64 object_store_id
,
375 const base::string16
& name
,
376 const IndexedDBKeyPath
& key_path
,
377 bool auto_increment
);
378 virtual leveldb::Status
DeleteObjectStore(
379 IndexedDBBackingStore::Transaction
* transaction
,
381 int64 object_store_id
) WARN_UNUSED_RESULT
;
383 virtual leveldb::Status
GetRecord(
384 IndexedDBBackingStore::Transaction
* transaction
,
386 int64 object_store_id
,
387 const IndexedDBKey
& key
,
388 IndexedDBValue
* record
) WARN_UNUSED_RESULT
;
389 virtual leveldb::Status
PutRecord(
390 IndexedDBBackingStore::Transaction
* transaction
,
392 int64 object_store_id
,
393 const IndexedDBKey
& key
,
394 IndexedDBValue
* value
,
395 ScopedVector
<storage::BlobDataHandle
>* handles
,
396 RecordIdentifier
* record
) WARN_UNUSED_RESULT
;
397 virtual leveldb::Status
ClearObjectStore(
398 IndexedDBBackingStore::Transaction
* transaction
,
400 int64 object_store_id
) WARN_UNUSED_RESULT
;
401 virtual leveldb::Status
DeleteRecord(
402 IndexedDBBackingStore::Transaction
* transaction
,
404 int64 object_store_id
,
405 const RecordIdentifier
& record
) WARN_UNUSED_RESULT
;
406 virtual leveldb::Status
DeleteRange(
407 IndexedDBBackingStore::Transaction
* transaction
,
409 int64 object_store_id
,
410 const IndexedDBKeyRange
&) WARN_UNUSED_RESULT
;
411 virtual leveldb::Status
GetKeyGeneratorCurrentNumber(
412 IndexedDBBackingStore::Transaction
* transaction
,
414 int64 object_store_id
,
415 int64
* current_number
) WARN_UNUSED_RESULT
;
416 virtual leveldb::Status
MaybeUpdateKeyGeneratorCurrentNumber(
417 IndexedDBBackingStore::Transaction
* transaction
,
419 int64 object_store_id
,
421 bool check_current
) WARN_UNUSED_RESULT
;
422 virtual leveldb::Status
KeyExistsInObjectStore(
423 IndexedDBBackingStore::Transaction
* transaction
,
425 int64 object_store_id
,
426 const IndexedDBKey
& key
,
427 RecordIdentifier
* found_record_identifier
,
428 bool* found
) WARN_UNUSED_RESULT
;
430 virtual leveldb::Status
CreateIndex(
431 IndexedDBBackingStore::Transaction
* transaction
,
433 int64 object_store_id
,
435 const base::string16
& name
,
436 const IndexedDBKeyPath
& key_path
,
438 bool is_multi_entry
) WARN_UNUSED_RESULT
;
439 virtual leveldb::Status
DeleteIndex(
440 IndexedDBBackingStore::Transaction
* transaction
,
442 int64 object_store_id
,
443 int64 index_id
) WARN_UNUSED_RESULT
;
444 virtual leveldb::Status
PutIndexDataForRecord(
445 IndexedDBBackingStore::Transaction
* transaction
,
447 int64 object_store_id
,
449 const IndexedDBKey
& key
,
450 const RecordIdentifier
& record
) WARN_UNUSED_RESULT
;
451 virtual leveldb::Status
GetPrimaryKeyViaIndex(
452 IndexedDBBackingStore::Transaction
* transaction
,
454 int64 object_store_id
,
456 const IndexedDBKey
& key
,
457 scoped_ptr
<IndexedDBKey
>* primary_key
) WARN_UNUSED_RESULT
;
458 virtual leveldb::Status
KeyExistsInIndex(
459 IndexedDBBackingStore::Transaction
* transaction
,
461 int64 object_store_id
,
463 const IndexedDBKey
& key
,
464 scoped_ptr
<IndexedDBKey
>* found_primary_key
,
465 bool* exists
) WARN_UNUSED_RESULT
;
467 // Public for IndexedDBActiveBlobRegistry::ReleaseBlobRef.
468 virtual void ReportBlobUnused(int64 database_id
, int64 blob_key
);
470 base::FilePath
GetBlobFileName(int64 database_id
, int64 key
);
472 virtual scoped_ptr
<Cursor
> OpenObjectStoreKeyCursor(
473 IndexedDBBackingStore::Transaction
* transaction
,
475 int64 object_store_id
,
476 const IndexedDBKeyRange
& key_range
,
477 blink::WebIDBCursorDirection
,
479 virtual scoped_ptr
<Cursor
> OpenObjectStoreCursor(
480 IndexedDBBackingStore::Transaction
* transaction
,
482 int64 object_store_id
,
483 const IndexedDBKeyRange
& key_range
,
484 blink::WebIDBCursorDirection
,
486 virtual scoped_ptr
<Cursor
> OpenIndexKeyCursor(
487 IndexedDBBackingStore::Transaction
* transaction
,
489 int64 object_store_id
,
491 const IndexedDBKeyRange
& key_range
,
492 blink::WebIDBCursorDirection
,
494 virtual scoped_ptr
<Cursor
> OpenIndexCursor(
495 IndexedDBBackingStore::Transaction
* transaction
,
497 int64 object_store_id
,
499 const IndexedDBKeyRange
& key_range
,
500 blink::WebIDBCursorDirection
,
504 friend class base::RefCounted
<IndexedDBBackingStore
>;
506 IndexedDBBackingStore(IndexedDBFactory
* indexed_db_factory
,
507 const GURL
& origin_url
,
508 const base::FilePath
& blob_path
,
509 net::URLRequestContext
* request_context
,
510 scoped_ptr
<LevelDBDatabase
> db
,
511 scoped_ptr
<LevelDBComparator
> comparator
,
512 base::SequencedTaskRunner
* task_runner
);
513 virtual ~IndexedDBBackingStore();
515 bool is_incognito() const { return !indexed_db_factory_
; }
517 leveldb::Status
SetUpMetadata();
519 virtual bool WriteBlobFile(
521 const Transaction::WriteDescriptor
& descriptor
,
522 Transaction::ChainedBlobWriter
* chained_blob_writer
);
523 virtual bool RemoveBlobFile(int64 database_id
, int64 key
);
524 virtual void StartJournalCleaningTimer();
525 void CleanPrimaryJournalIgnoreReturn();
528 static scoped_refptr
<IndexedDBBackingStore
> Create(
529 IndexedDBFactory
* indexed_db_factory
,
530 const GURL
& origin_url
,
531 const base::FilePath
& blob_path
,
532 net::URLRequestContext
* request_context
,
533 scoped_ptr
<LevelDBDatabase
> db
,
534 scoped_ptr
<LevelDBComparator
> comparator
,
535 base::SequencedTaskRunner
* task_runner
,
536 leveldb::Status
* status
);
538 static bool ReadCorruptionInfo(const base::FilePath
& path_base
,
539 const GURL
& origin_url
,
540 std::string
* message
);
542 leveldb::Status
FindKeyInIndex(
543 IndexedDBBackingStore::Transaction
* transaction
,
545 int64 object_store_id
,
547 const IndexedDBKey
& key
,
548 std::string
* found_encoded_primary_key
,
550 leveldb::Status
GetIndexes(int64 database_id
,
551 int64 object_store_id
,
552 IndexedDBObjectStoreMetadata::IndexMap
* map
)
554 bool RemoveBlobDirectory(int64 database_id
);
555 leveldb::Status
CleanUpBlobJournal(const std::string
& level_db_key
);
557 IndexedDBFactory
* indexed_db_factory_
;
558 const GURL origin_url_
;
559 base::FilePath blob_path_
;
561 // The origin identifier is a key prefix unique to the origin used in the
562 // leveldb backing store to partition data by origin. It is a normalized
563 // version of the origin URL with a versioning suffix appended, e.g.
564 // "http_localhost_81@1" Since only one origin is stored per backing store
565 // this is redundant but necessary for backwards compatibility; the suffix
566 // provides for future flexibility.
567 const std::string origin_identifier_
;
569 net::URLRequestContext
* request_context_
;
570 scoped_refptr
<base::SequencedTaskRunner
> task_runner_
;
571 std::set
<int> child_process_ids_granted_
;
572 BlobChangeMap incognito_blob_map_
;
573 base::OneShotTimer
<IndexedDBBackingStore
> journal_cleaning_timer_
;
575 scoped_ptr
<LevelDBDatabase
> db_
;
576 scoped_ptr
<LevelDBComparator
> comparator_
;
577 // Whenever blobs are registered in active_blob_registry_, indexed_db_factory_
578 // will hold a reference to this backing store.
579 IndexedDBActiveBlobRegistry active_blob_registry_
;
580 base::OneShotTimer
<IndexedDBBackingStore
> close_timer_
;
582 DISALLOW_COPY_AND_ASSIGN(IndexedDBBackingStore
);
585 } // namespace content
587 #endif // CONTENT_BROWSER_INDEXED_DB_INDEXED_DB_BACKING_STORE_H_