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 7169d21cbbc6433555578cbe8d4cf00f675a0e59..2eed735d38de71329069b7576eafc5679483987c 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> |
@@ -13,7 +14,11 @@ |
#include "base/memory/ref_counted.h" |
#include "base/memory/scoped_ptr.h" |
#include "base/memory/weak_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" |
@@ -24,10 +29,21 @@ |
#include "third_party/WebKit/public/platform/WebIDBCallbacks.h" |
#include "third_party/leveldatabase/src/include/leveldb/status.h" |
+class GURL; |
+ |
+namespace base { |
+class TaskRunner; |
+} |
+ |
+namespace net { |
+class URLRequestContext; |
+} |
+ |
namespace content { |
class LevelDBComparator; |
class LevelDBDatabase; |
+struct IndexedDBValue; |
class LevelDBFactory { |
public: |
@@ -49,14 +65,20 @@ class CONTENT_EXPORT IndexedDBBackingStore |
const std::string& origin_identifier, |
const base::FilePath& path_base, |
const std::string& file_identifier, |
- WebKit::WebIDBCallbacks::DataLoss* data_loss); |
+ net::URLRequestContext* request_context, |
+ WebKit::WebIDBCallbacks::DataLoss* data_loss, |
+ base::TaskRunner* task_runner, |
+ bool clean_journal); |
static scoped_refptr<IndexedDBBackingStore> Open( |
const std::string& origin_identifier, |
const base::FilePath& path_base, |
const std::string& file_identifier, |
+ net::URLRequestContext* request_context, |
WebKit::WebIDBCallbacks::DataLoss* data_loss, |
- LevelDBFactory* factory); |
+ LevelDBFactory* factory, |
+ base::TaskRunner* task_runner, |
+ bool clean_journal); |
static scoped_refptr<IndexedDBBackingStore> OpenInMemory( |
const std::string& file_identifier); |
static scoped_refptr<IndexedDBBackingStore> OpenInMemory( |
@@ -66,6 +88,8 @@ class CONTENT_EXPORT IndexedDBBackingStore |
return weak_factory_.GetWeakPtr(); |
} |
+ void GrantChildProcessPermissions(int child_process_id); |
+ |
virtual std::vector<string16> GetDatabaseNames(); |
virtual bool GetIDBDatabaseMetaData(const string16& name, |
IndexedDBDatabaseMetadata* metadata, |
@@ -120,16 +144,23 @@ 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, |
RecordIdentifier* record) WARN_UNUSED_RESULT; |
virtual bool ClearObjectStore(IndexedDBBackingStore::Transaction* transaction, |
int64 database_id, |
@@ -138,6 +169,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, |
@@ -191,6 +226,11 @@ class CONTENT_EXPORT IndexedDBBackingStore |
scoped_ptr<IndexedDBKey>* found_primary_key, |
bool* exists) WARN_UNUSED_RESULT; |
+ // Public for IndexedDBBlobRegistryCallback. |
+ void ReportBlobUnused(int64 database_id, int64 blob_key); |
+ |
+ base::FilePath GetIDBBlobFileName(int64 database_id, int64 key); |
+ |
class Cursor { |
public: |
virtual ~Cursor(); |
@@ -222,12 +262,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); |
@@ -236,7 +278,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_; |
@@ -275,35 +319,146 @@ 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>*); |
static LevelDBTransaction* LevelDBTransactionFrom( |
Transaction* transaction) { |
return transaction->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; |
+ |
+ typedef std::vector<WriteDescriptor> WriteDescriptorVec; |
+ |
private: |
+ struct AVLTreeNode { |
+ AVLTreeNode() {} |
+ ~AVLTreeNode() {} |
+ std::string key; |
+ int64 object_store_id; |
+ std::vector<IndexedDBBlobInfo> blob_info; |
+ |
+ AVLTreeNode* less; |
+ AVLTreeNode* greater; |
+ int balance_factor; |
+ DISALLOW_COPY_AND_ASSIGN(AVLTreeNode); |
+ }; |
+ struct AVLTreeAbstractor { |
+ typedef AVLTreeNode* handle; |
+ typedef size_t size; |
+ typedef std::string key; // TODO(ericu): base::StringPiece? |
+ |
+ handle GetLess(handle h) { return h->less; } |
+ void SetLess(handle h, handle less) { h->less = less; } |
+ handle GetGreater(handle h) { return h->greater; } |
+ void SetGreater(handle h, handle greater) { h->greater = greater; } |
+ |
+ int GetBalanceFactor(handle h) { return h->balance_factor; } |
+ void SetBalanceFactor(handle h, int bf) { h->balance_factor = bf; } |
+ |
+ int CompareKeyKey(const key& ka, const key& kb) { |
+ return comparator_->Compare(ka, kb); |
+ } |
+ int CompareKeyNode(const key& k, handle h) { |
+ return CompareKeyKey(k, key(h->key)); |
+ } |
+ int CompareNodeNode(handle ha, handle hb) { |
+ return CompareKeyKey(key(ha->key), key(hb->key)); |
+ } |
+ |
+ static handle Null() { return 0; } |
+ |
+ const LevelDBComparator* comparator_; |
+ }; |
+ typedef AVLTree<AVLTreeAbstractor> TreeType; |
+ |
+ // 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_; |
+ TreeType blob_info_tree_; |
+ 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 std::string& identifier, |
+ 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 WriteBlobFile(int64 database_id, |
+ const Transaction::WriteDescriptor& descriptor, |
+ Transaction::ChainedBlobWriter* chained_blob_writer); |
+ |
private: |
static scoped_refptr<IndexedDBBackingStore> Create( |
const std::string& identifier, |
+ 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, |
@@ -316,11 +471,23 @@ class CONTENT_EXPORT IndexedDBBackingStore |
int64 object_store_id, |
IndexedDBObjectStoreMetadata::IndexMap* map) |
WARN_UNUSED_RESULT; |
+ bool RemoveBlobFile(int64 database_id, int64 key); |
+ bool RemoveBlobDirectory(int64 database_id); |
+ bool CleanUpBlobJournal(const std::string& level_db_key); |
+ void CleanPrimaryJournalIgnoreReturn(); |
std::string 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::WeakPtrFactory<IndexedDBBackingStore> weak_factory_; |
}; |