Index: content/browser/indexed_db/indexed_db_backing_store.h |
diff --git a/content/browser/indexed_db/indexed_db_backing_store.h b/content/browser/indexed_db/indexed_db_backing_store.h |
index 9ea71f11ac65fd6b18c42b5734b9cf320bd9fcf2..3fce9805b9036adf0afc582f4cf07a13d412ab8e 100644 |
--- a/content/browser/indexed_db/indexed_db_backing_store.h |
+++ b/content/browser/indexed_db/indexed_db_backing_store.h |
@@ -5,6 +5,7 @@ |
#ifndef CONTENT_BROWSER_INDEXED_DB_INDEXED_DB_BACKING_STORE_H_ |
#define CONTENT_BROWSER_INDEXED_DB_INDEXED_DB_BACKING_STORE_H_ |
+#include <set> |
#include <string> |
#include <vector> |
@@ -14,6 +15,9 @@ |
#include "base/memory/scoped_ptr.h" |
#include "base/timer/timer.h" |
#include "content/browser/indexed_db/indexed_db.h" |
+#include "content/browser/indexed_db/indexed_db_active_blob_registry.h" |
+#include "content/browser/indexed_db/indexed_db_blob_info.h" |
+#include "content/browser/indexed_db/indexed_db_leveldb_coding.h" |
#include "content/browser/indexed_db/indexed_db_metadata.h" |
#include "content/browser/indexed_db/leveldb/leveldb_iterator.h" |
#include "content/browser/indexed_db/leveldb/leveldb_transaction.h" |
@@ -23,11 +27,28 @@ |
#include "content/common/indexed_db/indexed_db_key_range.h" |
#include "third_party/leveldatabase/src/include/leveldb/status.h" |
#include "url/gurl.h" |
+#include "webkit/browser/blob/blob_data_handle.h" |
+ |
+class GURL; |
+ |
+namespace base { |
+class TaskRunner; |
+} |
+ |
+namespace fileapi { |
+class FileWriterDelegate; |
+} |
+ |
+namespace net { |
+class URLRequestContext; |
+} |
namespace content { |
+class IndexedDBFactory; |
class LevelDBComparator; |
class LevelDBDatabase; |
+struct IndexedDBValue; |
class LevelDBFactory { |
public: |
@@ -48,26 +69,38 @@ class CONTENT_EXPORT IndexedDBBackingStore |
base::OneShotTimer<IndexedDBBackingStore>* close_timer() { |
return &close_timer_; |
} |
+ IndexedDBFactory* factory() const { return indexed_db_factory_; } |
static scoped_refptr<IndexedDBBackingStore> Open( |
+ IndexedDBFactory* indexed_db_factory, |
const GURL& origin_url, |
const base::FilePath& path_base, |
+ net::URLRequestContext* request_context, |
blink::WebIDBDataLoss* data_loss, |
std::string* data_loss_message, |
- bool* disk_full); |
+ bool* disk_full, |
+ base::TaskRunner* task_runner, |
+ bool clean_journal); |
static scoped_refptr<IndexedDBBackingStore> Open( |
+ IndexedDBFactory* indexed_db_factory, |
const GURL& origin_url, |
const base::FilePath& path_base, |
+ net::URLRequestContext* request_context, |
blink::WebIDBDataLoss* data_loss, |
std::string* data_loss_message, |
bool* disk_full, |
- LevelDBFactory* factory); |
+ LevelDBFactory* factory, |
+ base::TaskRunner* task_runner, |
+ bool clean_journal); |
static scoped_refptr<IndexedDBBackingStore> OpenInMemory( |
- const GURL& origin_url); |
+ const GURL& origin_url, base::TaskRunner* task_runner); |
static scoped_refptr<IndexedDBBackingStore> OpenInMemory( |
const GURL& origin_url, |
- LevelDBFactory* factory); |
+ LevelDBFactory* factory, |
+ base::TaskRunner* task_runner); |
+ |
+ void GrantChildProcessPermissions(int child_process_id); |
virtual std::vector<string16> GetDatabaseNames(); |
virtual bool GetIDBDatabaseMetaData(const string16& name, |
@@ -119,16 +152,24 @@ class CONTENT_EXPORT IndexedDBBackingStore |
DISALLOW_COPY_AND_ASSIGN(RecordIdentifier); |
}; |
+ class BlobWriteCallback : public RefCounted<BlobWriteCallback> { |
+ public: |
+ virtual ~BlobWriteCallback() { } |
+ virtual void didSucceed() = 0; |
+ virtual void didFail() = 0; |
+ }; |
+ |
virtual bool GetRecord(IndexedDBBackingStore::Transaction* transaction, |
int64 database_id, |
int64 object_store_id, |
const IndexedDBKey& key, |
- std::string* record) WARN_UNUSED_RESULT; |
+ IndexedDBValue* record) WARN_UNUSED_RESULT; |
virtual bool PutRecord(IndexedDBBackingStore::Transaction* transaction, |
int64 database_id, |
int64 object_store_id, |
const IndexedDBKey& key, |
- const std::string& value, |
+ IndexedDBValue& value, |
+ ScopedVector<webkit_blob::BlobDataHandle>* handles, |
RecordIdentifier* record) WARN_UNUSED_RESULT; |
virtual bool ClearObjectStore(IndexedDBBackingStore::Transaction* transaction, |
int64 database_id, |
@@ -137,6 +178,10 @@ class CONTENT_EXPORT IndexedDBBackingStore |
int64 database_id, |
int64 object_store_id, |
const RecordIdentifier& record) WARN_UNUSED_RESULT; |
+ virtual bool DeleteRange(IndexedDBBackingStore::Transaction* transaction, |
+ int64 database_id, |
+ int64 object_store_id, |
+ const IndexedDBKeyRange&) WARN_UNUSED_RESULT; |
virtual bool GetKeyGeneratorCurrentNumber( |
IndexedDBBackingStore::Transaction* transaction, |
int64 database_id, |
@@ -190,6 +235,11 @@ class CONTENT_EXPORT IndexedDBBackingStore |
scoped_ptr<IndexedDBKey>* found_primary_key, |
bool* exists) WARN_UNUSED_RESULT; |
+ // Public for IndexedDBActiveBlobRegistry::ReleaseBlobRef. |
+ void ReportBlobUnused(int64 database_id, int64 blob_key); |
+ |
+ base::FilePath GetIDBBlobFileName(int64 database_id, int64 key); |
+ |
class Cursor { |
public: |
virtual ~Cursor(); |
@@ -226,12 +276,14 @@ class CONTENT_EXPORT IndexedDBBackingStore |
virtual Cursor* Clone() = 0; |
virtual const IndexedDBKey& primary_key() const; |
- virtual std::string* Value() = 0; |
+ virtual IndexedDBValue* Value() = 0; |
virtual const RecordIdentifier& record_identifier() const; |
virtual bool LoadCurrentRow() = 0; |
protected: |
- Cursor(LevelDBTransaction* transaction, |
+ Cursor(scoped_refptr<IndexedDBBackingStore> backing_store, |
+ LevelDBTransaction* transaction, |
+ int64 database_id, |
const CursorOptions& cursor_options); |
explicit Cursor(const IndexedDBBackingStore::Cursor* other); |
@@ -242,7 +294,9 @@ class CONTENT_EXPORT IndexedDBBackingStore |
bool IsPastBounds() const; |
bool HaveEnteredRange() const; |
+ scoped_refptr<IndexedDBBackingStore> backing_store_; |
LevelDBTransaction* transaction_; |
+ int64 database_id_; |
const CursorOptions cursor_options_; |
scoped_ptr<LevelDBIterator> iterator_; |
scoped_ptr<IndexedDBKey> current_key_; |
@@ -281,32 +335,155 @@ class CONTENT_EXPORT IndexedDBBackingStore |
explicit Transaction(IndexedDBBackingStore* backing_store); |
~Transaction(); |
void Begin(); |
- bool Commit(); |
+ // The callback will be called eventually on success or failure, or |
+ // immediately if phase one is complete due to lack of any blobs to write. |
+ bool CommitPhaseOne(scoped_refptr<BlobWriteCallback>); |
+ bool CommitPhaseTwo(); |
void Rollback(); |
void Reset() { |
backing_store_ = NULL; |
transaction_ = NULL; |
} |
+ void PutBlobInfo(int64 database_id, int64 object_store_id, |
+ const std::string& key, std::vector<IndexedDBBlobInfo>*, |
+ ScopedVector<webkit_blob::BlobDataHandle>* handles); |
LevelDBTransaction* transaction() { return transaction_; } |
+ // DatabaseId, BlobKey |
+ typedef std::pair<int64_t, int64_t> BlobJournalEntryType; |
+ typedef std::vector<BlobJournalEntryType> BlobJournalType; |
+ // This holds a BlobEntryKey and the encoded IndexedDBBlobInfo vector stored |
+ // under that key. |
+ typedef std::vector< std::pair<BlobEntryKey, std::string> > |
+ BlobEntryKeyValuePairVec; |
+ |
+ class WriteDescriptor { |
+ public: |
+ WriteDescriptor(const GURL& url, int64_t key); |
+ WriteDescriptor(const base::FilePath& path, int64_t key); |
+ |
+ bool is_file() const { return is_file_; } |
+ const GURL& url() const { |
+ DCHECK(!is_file_); |
+ return url_; |
+ } |
+ const base::FilePath& file_path() const { |
+ DCHECK(is_file_); |
+ return file_path_; |
+ } |
+ int64_t key() const { return key_; } |
+ private: |
+ bool is_file_; |
+ GURL url_; |
+ base::FilePath file_path_; |
+ int64_t key_; |
+ }; |
+ |
+ class ChainedBlobWriter : public base::RefCounted<ChainedBlobWriter> { |
+ public: |
+ |
+ virtual void set_delegate( |
+ scoped_ptr<fileapi::FileWriterDelegate> delegate) = 0; |
+ |
+ virtual void ReportWriteCompletion( |
+ bool succeeded, int64 bytes_written) = 0; |
+ |
+ virtual void Abort() = 0; |
+ |
+ protected: |
+ virtual ~ChainedBlobWriter() {} |
+ friend class base::RefCounted<ChainedBlobWriter>; |
+ }; |
+ class ChainedBlobWriterImpl; |
+ |
+ typedef std::vector<WriteDescriptor> WriteDescriptorVec; |
+ |
private: |
+ class BlobChangeRecord { |
+ public: |
+ BlobChangeRecord() {} |
+ void set_key(const std::string& key) { |
+ key_ = key; |
+ } |
+ const std::string& key() const { |
+ return key_; |
+ } |
+ void set_object_store_id(int64 object_store_id) { |
+ object_store_id_ = object_store_id; |
+ } |
+ int64 object_store_id() const { |
+ return object_store_id_; |
+ } |
+ void SetBlobInfo(std::vector<IndexedDBBlobInfo>* blob_info); |
+ std::vector<IndexedDBBlobInfo>& mutable_blob_info() { |
+ return blob_info_; |
+ } |
+ void SetHandles(ScopedVector<webkit_blob::BlobDataHandle>* handles); |
+ |
+ private: |
+ std::string key_; |
+ int64 object_store_id_; |
+ std::vector<IndexedDBBlobInfo> blob_info_; |
+ ScopedVector<webkit_blob::BlobDataHandle> handles_; |
+ }; |
+ class BlobWriteCallbackWrapper; |
+ typedef std::map<std::string, BlobChangeRecord*> BlobChangeMap; |
+ |
+ // These return true on success, false on failure. |
+ bool HandleBlobPreTransaction(BlobEntryKeyValuePairVec* new_blob_entries, |
+ WriteDescriptorVec* new_files_to_write); |
+ bool CollectBlobFilesToRemove(); |
+ // The callback will be called eventually on success or failure. |
+ void WriteNewBlobs(BlobEntryKeyValuePairVec& new_blob_entries, |
+ WriteDescriptorVec& new_files_to_write, |
+ scoped_refptr<BlobWriteCallback> callback); |
+ bool SortBlobsToRemove(); |
+ |
IndexedDBBackingStore* backing_store_; |
scoped_refptr<LevelDBTransaction> transaction_; |
+ BlobChangeMap blob_change_map_; |
+ int64 database_id_; |
+ BlobJournalType blobs_to_remove_; |
+ scoped_refptr<ChainedBlobWriter> chained_blob_writer_; |
}; |
+ LevelDBComparator* comparator() { return comparator_.get(); } |
+ IndexedDBActiveBlobRegistry* active_blob_registry() { |
+ return &active_blob_registry_; |
+ } |
+ |
+ base::TaskRunner* task_runner() { return task_runner_; } |
+ |
protected: |
- IndexedDBBackingStore(const GURL& origin_url, |
+ IndexedDBBackingStore(IndexedDBFactory* indexed_db_factory, |
+ const GURL& origin_url, |
+ const base::FilePath& blob_path, |
+ net::URLRequestContext* request_context, |
scoped_ptr<LevelDBDatabase> db, |
- scoped_ptr<LevelDBComparator> comparator); |
+ scoped_ptr<LevelDBComparator> comparator, |
+ base::TaskRunner* task_runner); |
virtual ~IndexedDBBackingStore(); |
friend class base::RefCounted<IndexedDBBackingStore>; |
+ bool SetUpMetadata(); |
+ |
+ virtual bool WriteBlobFile( |
+ int64 database_id, const Transaction::WriteDescriptor& descriptor, |
+ Transaction::ChainedBlobWriter* chained_blob_writer); |
+ virtual bool RemoveBlobFile(int64 database_id, int64 key); |
+ virtual void StartJournalCleaningTimer(); |
+ void CleanPrimaryJournalIgnoreReturn(); |
+ |
private: |
static scoped_refptr<IndexedDBBackingStore> Create( |
+ IndexedDBFactory* indexed_db_factory, |
const GURL& origin_url, |
+ const base::FilePath& blob_path, |
+ net::URLRequestContext* request_context, |
scoped_ptr<LevelDBDatabase> db, |
- scoped_ptr<LevelDBComparator> comparator); |
+ scoped_ptr<LevelDBComparator> comparator, |
+ base::TaskRunner* task_runner); |
bool FindKeyInIndex(IndexedDBBackingStore::Transaction* transaction, |
int64 database_id, |
@@ -319,7 +496,10 @@ class CONTENT_EXPORT IndexedDBBackingStore |
int64 object_store_id, |
IndexedDBObjectStoreMetadata::IndexMap* map) |
WARN_UNUSED_RESULT; |
+ bool RemoveBlobDirectory(int64 database_id); |
+ bool CleanUpBlobJournal(const std::string& level_db_key); |
+ IndexedDBFactory* indexed_db_factory_; |
const GURL origin_url_; |
// The origin identifier is a key prefix unique to the origin used in the |
@@ -330,8 +510,17 @@ class CONTENT_EXPORT IndexedDBBackingStore |
// provides for future flexibility. |
const std::string origin_identifier_; |
+ base::FilePath blob_path_; |
+ net::URLRequestContext* request_context_; |
+ base::TaskRunner* task_runner_; |
+ std::set<int> child_process_ids_granted_; |
+ base::OneShotTimer<IndexedDBBackingStore> journal_cleaning_timer_; |
+ |
scoped_ptr<LevelDBDatabase> db_; |
scoped_ptr<LevelDBComparator> comparator_; |
+ // The active_blob_registry_ will hold a refcount to this backing store |
+ // whenever any live blobs are registered with it. |
+ IndexedDBActiveBlobRegistry active_blob_registry_; |
base::OneShotTimer<IndexedDBBackingStore> close_timer_; |
}; |