Index: content/browser/indexed_db/indexed_db_database_impl.cc |
diff --git a/content/browser/indexed_db/indexed_db_database_impl.cc b/content/browser/indexed_db/indexed_db_database_impl.cc |
deleted file mode 100644 |
index fb2dcc4dcfa3afbee7871391be418e7f803671c9..0000000000000000000000000000000000000000 |
--- a/content/browser/indexed_db/indexed_db_database_impl.cc |
+++ /dev/null |
@@ -1,1802 +0,0 @@ |
-// Copyright (c) 2013 The Chromium Authors. All rights reserved. |
-// Use of this source code is governed by a BSD-style license that can be |
-// found in the LICENSE file. |
- |
-#include "content/browser/indexed_db/indexed_db_database_impl.h" |
- |
-#include <math.h> |
-#include <vector> |
- |
-#include "base/auto_reset.h" |
-#include "base/logging.h" |
-#include "base/memory/scoped_ptr.h" |
-#include "base/strings/string_number_conversions.h" |
-#include "base/strings/utf_string_conversions.h" |
-#include "content/browser/indexed_db/indexed_db_backing_store.h" |
-#include "content/browser/indexed_db/indexed_db_cursor_impl.h" |
-#include "content/browser/indexed_db/indexed_db_factory_impl.h" |
-#include "content/browser/indexed_db/indexed_db_index_writer.h" |
-#include "content/browser/indexed_db/indexed_db_tracing.h" |
-#include "content/browser/indexed_db/indexed_db_transaction.h" |
-#include "content/common/indexed_db/indexed_db_key_path.h" |
-#include "content/common/indexed_db/indexed_db_key_range.h" |
-#include "third_party/WebKit/public/platform/WebIDBDatabaseException.h" |
- |
-using base::Int64ToString16; |
-using WebKit::WebIDBKey; |
- |
-namespace content { |
- |
-class CreateObjectStoreOperation : public IndexedDBTransaction::Operation { |
- public: |
- CreateObjectStoreOperation( |
- scoped_refptr<IndexedDBBackingStore> backing_store, |
- const IndexedDBObjectStoreMetadata& object_store_metadata) |
- : backing_store_(backing_store), |
- object_store_metadata_(object_store_metadata) {} |
- virtual void Perform(IndexedDBTransaction* transaction) OVERRIDE; |
- |
- private: |
- const scoped_refptr<IndexedDBBackingStore> backing_store_; |
- const IndexedDBObjectStoreMetadata object_store_metadata_; |
-}; |
- |
-class DeleteObjectStoreOperation : public IndexedDBTransaction::Operation { |
- public: |
- DeleteObjectStoreOperation( |
- scoped_refptr<IndexedDBBackingStore> backing_store, |
- const IndexedDBObjectStoreMetadata& object_store_metadata) |
- : backing_store_(backing_store), |
- object_store_metadata_(object_store_metadata) {} |
- virtual void Perform(IndexedDBTransaction* transaction) OVERRIDE; |
- |
- private: |
- const scoped_refptr<IndexedDBBackingStore> backing_store_; |
- const IndexedDBObjectStoreMetadata object_store_metadata_; |
-}; |
- |
-class IndexedDBDatabaseImpl::VersionChangeOperation |
- : public IndexedDBTransaction::Operation { |
- public: |
- VersionChangeOperation( |
- scoped_refptr<IndexedDBDatabaseImpl> database, |
- int64 transaction_id, |
- int64 version, |
- scoped_refptr<IndexedDBCallbacksWrapper> callbacks, |
- scoped_refptr<IndexedDBDatabaseCallbacksWrapper> database_callbacks) |
- : database_(database), |
- transaction_id_(transaction_id), |
- version_(version), |
- callbacks_(callbacks), |
- database_callbacks_(database_callbacks) {} |
- virtual void Perform(IndexedDBTransaction* transaction) OVERRIDE; |
- |
- private: |
- scoped_refptr<IndexedDBDatabaseImpl> database_; |
- int64 transaction_id_; |
- int64 version_; |
- scoped_refptr<IndexedDBCallbacksWrapper> callbacks_; |
- scoped_refptr<IndexedDBDatabaseCallbacksWrapper> database_callbacks_; |
-}; |
- |
-class CreateObjectStoreAbortOperation : public IndexedDBTransaction::Operation { |
- public: |
- CreateObjectStoreAbortOperation(scoped_refptr<IndexedDBDatabaseImpl> database, |
- int64 object_store_id) |
- : database_(database), object_store_id_(object_store_id) {} |
- virtual void Perform(IndexedDBTransaction* transaction) OVERRIDE; |
- |
- private: |
- const scoped_refptr<IndexedDBDatabaseImpl> database_; |
- const int64 object_store_id_; |
-}; |
- |
-class DeleteObjectStoreAbortOperation : public IndexedDBTransaction::Operation { |
- public: |
- DeleteObjectStoreAbortOperation( |
- scoped_refptr<IndexedDBDatabaseImpl> database, |
- const IndexedDBObjectStoreMetadata& object_store_metadata) |
- : database_(database), object_store_metadata_(object_store_metadata) {} |
- virtual void Perform(IndexedDBTransaction* transaction) OVERRIDE; |
- |
- private: |
- scoped_refptr<IndexedDBDatabaseImpl> database_; |
- IndexedDBObjectStoreMetadata object_store_metadata_; |
-}; |
- |
-class IndexedDBDatabaseImpl::VersionChangeAbortOperation |
- : public IndexedDBTransaction::Operation { |
- public: |
- VersionChangeAbortOperation(scoped_refptr<IndexedDBDatabaseImpl> database, |
- const string16& previous_version, |
- int64 previous_int_version) |
- : database_(database), |
- previous_version_(previous_version), |
- previous_int_version_(previous_int_version) {} |
- virtual void Perform(IndexedDBTransaction* transaction) OVERRIDE; |
- |
- private: |
- scoped_refptr<IndexedDBDatabaseImpl> database_; |
- string16 previous_version_; |
- int64 previous_int_version_; |
-}; |
- |
-class CreateIndexOperation : public IndexedDBTransaction::Operation { |
- public: |
- CreateIndexOperation(scoped_refptr<IndexedDBBackingStore> backing_store, |
- int64 object_store_id, |
- const IndexedDBIndexMetadata& index_metadata) |
- : backing_store_(backing_store), |
- object_store_id_(object_store_id), |
- index_metadata_(index_metadata) {} |
- virtual void Perform(IndexedDBTransaction* transaction) OVERRIDE; |
- |
- private: |
- const scoped_refptr<IndexedDBBackingStore> backing_store_; |
- const int64 object_store_id_; |
- const IndexedDBIndexMetadata index_metadata_; |
-}; |
- |
-class DeleteIndexOperation : public IndexedDBTransaction::Operation { |
- public: |
- DeleteIndexOperation(scoped_refptr<IndexedDBBackingStore> backing_store, |
- int64 object_store_id, |
- const IndexedDBIndexMetadata& index_metadata) |
- : backing_store_(backing_store), |
- object_store_id_(object_store_id), |
- index_metadata_(index_metadata) {} |
- virtual void Perform(IndexedDBTransaction* transaction) OVERRIDE; |
- |
- private: |
- const scoped_refptr<IndexedDBBackingStore> backing_store_; |
- const int64 object_store_id_; |
- const IndexedDBIndexMetadata index_metadata_; |
-}; |
- |
-class CreateIndexAbortOperation : public IndexedDBTransaction::Operation { |
- public: |
- CreateIndexAbortOperation(scoped_refptr<IndexedDBDatabaseImpl> database, |
- int64 object_store_id, |
- int64 index_id) |
- : database_(database), |
- object_store_id_(object_store_id), |
- index_id_(index_id) {} |
- virtual void Perform(IndexedDBTransaction* transaction) OVERRIDE; |
- |
- private: |
- const scoped_refptr<IndexedDBDatabaseImpl> database_; |
- const int64 object_store_id_; |
- const int64 index_id_; |
-}; |
- |
-class DeleteIndexAbortOperation : public IndexedDBTransaction::Operation { |
- public: |
- DeleteIndexAbortOperation(scoped_refptr<IndexedDBDatabaseImpl> database, |
- int64 object_store_id, |
- const IndexedDBIndexMetadata& index_metadata) |
- : database_(database), |
- object_store_id_(object_store_id), |
- index_metadata_(index_metadata) {} |
- virtual void Perform(IndexedDBTransaction* transaction) OVERRIDE; |
- |
- private: |
- const scoped_refptr<IndexedDBDatabaseImpl> database_; |
- const int64 object_store_id_; |
- const IndexedDBIndexMetadata index_metadata_; |
-}; |
- |
-class GetOperation : public IndexedDBTransaction::Operation { |
- public: |
- GetOperation(scoped_refptr<IndexedDBBackingStore> backing_store, |
- const IndexedDBDatabaseMetadata& metadata, |
- int64 object_store_id, |
- int64 index_id, |
- scoped_ptr<IndexedDBKeyRange> key_range, |
- indexed_db::CursorType cursor_type, |
- scoped_refptr<IndexedDBCallbacksWrapper> callbacks) |
- : backing_store_(backing_store), |
- database_id_(metadata.id), |
- object_store_id_(object_store_id), |
- index_id_(index_id), |
- key_path_(metadata.object_stores.find(object_store_id) |
- ->second.key_path), |
- auto_increment_(metadata.object_stores.find(object_store_id) |
- ->second.auto_increment), |
- key_range_(key_range.Pass()), |
- cursor_type_(cursor_type), |
- callbacks_(callbacks) { |
- DCHECK(metadata.object_stores.find(object_store_id) != |
- metadata.object_stores.end()); |
- DCHECK(metadata.object_stores.find(object_store_id)->second.id == |
- object_store_id); |
- } |
- virtual void Perform(IndexedDBTransaction* transaction) OVERRIDE; |
- |
- private: |
- const scoped_refptr<IndexedDBBackingStore> backing_store_; |
- const int64 database_id_; |
- const int64 object_store_id_; |
- const int64 index_id_; |
- const IndexedDBKeyPath key_path_; |
- const bool auto_increment_; |
- const scoped_ptr<IndexedDBKeyRange> key_range_; |
- const indexed_db::CursorType cursor_type_; |
- const scoped_refptr<IndexedDBCallbacksWrapper> callbacks_; |
-}; |
- |
-class PutOperation : public IndexedDBTransaction::Operation { |
- public: |
- PutOperation(scoped_refptr<IndexedDBBackingStore> backing_store, |
- int64 database_id, |
- const IndexedDBObjectStoreMetadata& object_store, |
- std::vector<char>* value, |
- scoped_ptr<IndexedDBKey> key, |
- IndexedDBDatabase::PutMode put_mode, |
- scoped_refptr<IndexedDBCallbacksWrapper> callbacks, |
- const std::vector<int64>& index_ids, |
- const std::vector<IndexedDBDatabase::IndexKeys>& index_keys) |
- : backing_store_(backing_store), |
- database_id_(database_id), |
- object_store_(object_store), |
- key_(key.Pass()), |
- put_mode_(put_mode), |
- callbacks_(callbacks), |
- index_ids_(index_ids), |
- index_keys_(index_keys) { |
- value_.swap(*value); |
- } |
- virtual void Perform(IndexedDBTransaction* transaction) OVERRIDE; |
- |
- private: |
- const scoped_refptr<IndexedDBBackingStore> backing_store_; |
- const int64 database_id_; |
- const IndexedDBObjectStoreMetadata object_store_; |
- std::vector<char> value_; |
- scoped_ptr<IndexedDBKey> key_; |
- const IndexedDBDatabase::PutMode put_mode_; |
- const scoped_refptr<IndexedDBCallbacksWrapper> callbacks_; |
- const std::vector<int64> index_ids_; |
- const std::vector<IndexedDBDatabase::IndexKeys> index_keys_; |
-}; |
- |
-class SetIndexesReadyOperation : public IndexedDBTransaction::Operation { |
- public: |
- explicit SetIndexesReadyOperation(size_t index_count) |
- : index_count_(index_count) {} |
- virtual void Perform(IndexedDBTransaction* transaction) OVERRIDE; |
- |
- private: |
- const size_t index_count_; |
-}; |
- |
-class OpenCursorOperation : public IndexedDBTransaction::Operation { |
- public: |
- OpenCursorOperation(scoped_refptr<IndexedDBBackingStore> backing_store, |
- int64 database_id, |
- int64 object_store_id, |
- int64 index_id, |
- scoped_ptr<IndexedDBKeyRange> key_range, |
- indexed_db::CursorDirection direction, |
- indexed_db::CursorType cursor_type, |
- IndexedDBDatabase::TaskType task_type, |
- scoped_refptr<IndexedDBCallbacksWrapper> callbacks) |
- : backing_store_(backing_store), |
- database_id_(database_id), |
- object_store_id_(object_store_id), |
- index_id_(index_id), |
- key_range_(key_range.Pass()), |
- direction_(direction), |
- cursor_type_(cursor_type), |
- task_type_(task_type), |
- callbacks_(callbacks) {} |
- virtual void Perform(IndexedDBTransaction* transaction) OVERRIDE; |
- |
- private: |
- const scoped_refptr<IndexedDBBackingStore> backing_store_; |
- const int64 database_id_; |
- const int64 object_store_id_; |
- const int64 index_id_; |
- const scoped_ptr<IndexedDBKeyRange> key_range_; |
- const indexed_db::CursorDirection direction_; |
- const indexed_db::CursorType cursor_type_; |
- const IndexedDBDatabase::TaskType task_type_; |
- const scoped_refptr<IndexedDBCallbacksWrapper> callbacks_; |
-}; |
- |
-class CountOperation : public IndexedDBTransaction::Operation { |
- public: |
- CountOperation(scoped_refptr<IndexedDBBackingStore> backing_store, |
- int64 database_id, |
- int64 object_store_id, |
- int64 index_id, |
- scoped_ptr<IndexedDBKeyRange> key_range, |
- scoped_refptr<IndexedDBCallbacksWrapper> callbacks) |
- : backing_store_(backing_store), |
- database_id_(database_id), |
- object_store_id_(object_store_id), |
- index_id_(index_id), |
- key_range_(key_range.Pass()), |
- callbacks_(callbacks) {} |
- virtual void Perform(IndexedDBTransaction* transaction) OVERRIDE; |
- |
- private: |
- const scoped_refptr<IndexedDBBackingStore> backing_store_; |
- const int64 database_id_; |
- const int64 object_store_id_; |
- const int64 index_id_; |
- const scoped_ptr<IndexedDBKeyRange> key_range_; |
- const scoped_refptr<IndexedDBCallbacksWrapper> callbacks_; |
-}; |
- |
-class DeleteRangeOperation : public IndexedDBTransaction::Operation { |
- public: |
- DeleteRangeOperation(scoped_refptr<IndexedDBBackingStore> backing_store, |
- int64 database_id, |
- int64 object_store_id, |
- scoped_ptr<IndexedDBKeyRange> key_range, |
- scoped_refptr<IndexedDBCallbacksWrapper> callbacks) |
- : backing_store_(backing_store), |
- database_id_(database_id), |
- object_store_id_(object_store_id), |
- key_range_(key_range.Pass()), |
- callbacks_(callbacks) {} |
- virtual void Perform(IndexedDBTransaction* transaction) OVERRIDE; |
- |
- private: |
- const scoped_refptr<IndexedDBBackingStore> backing_store_; |
- const int64 database_id_; |
- const int64 object_store_id_; |
- const scoped_ptr<IndexedDBKeyRange> key_range_; |
- const scoped_refptr<IndexedDBCallbacksWrapper> callbacks_; |
-}; |
- |
-class ClearOperation : public IndexedDBTransaction::Operation { |
- public: |
- ClearOperation(scoped_refptr<IndexedDBBackingStore> backing_store, |
- int64 database_id, |
- int64 object_store_id, |
- scoped_refptr<IndexedDBCallbacksWrapper> callbacks) |
- : backing_store_(backing_store), |
- database_id_(database_id), |
- object_store_id_(object_store_id), |
- callbacks_(callbacks) {} |
- virtual void Perform(IndexedDBTransaction* transaction) OVERRIDE; |
- |
- private: |
- const scoped_refptr<IndexedDBBackingStore> backing_store_; |
- const int64 database_id_; |
- const int64 object_store_id_; |
- const scoped_refptr<IndexedDBCallbacksWrapper> callbacks_; |
-}; |
- |
-class IndexedDBDatabaseImpl::PendingOpenCall { |
- public: |
- PendingOpenCall( |
- scoped_refptr<IndexedDBCallbacksWrapper> callbacks, |
- scoped_refptr<IndexedDBDatabaseCallbacksWrapper> database_callbacks, |
- int64 transaction_id, |
- int64 version) |
- : callbacks_(callbacks), |
- database_callbacks_(database_callbacks), |
- version_(version), |
- transaction_id_(transaction_id) {} |
- scoped_refptr<IndexedDBCallbacksWrapper> Callbacks() { return callbacks_; } |
- scoped_refptr<IndexedDBDatabaseCallbacksWrapper> DatabaseCallbacks() { |
- return database_callbacks_; |
- } |
- int64 Version() { return version_; } |
- int64 TransactionId() const { return transaction_id_; } |
- |
- private: |
- scoped_refptr<IndexedDBCallbacksWrapper> callbacks_; |
- scoped_refptr<IndexedDBDatabaseCallbacksWrapper> database_callbacks_; |
- int64 version_; |
- const int64 transaction_id_; |
-}; |
- |
-class IndexedDBDatabaseImpl::PendingDeleteCall { |
- public: |
- explicit PendingDeleteCall(scoped_refptr<IndexedDBCallbacksWrapper> callbacks) |
- : callbacks_(callbacks) {} |
- scoped_refptr<IndexedDBCallbacksWrapper> Callbacks() { return callbacks_; } |
- |
- private: |
- scoped_refptr<IndexedDBCallbacksWrapper> callbacks_; |
-}; |
- |
-scoped_refptr<IndexedDBDatabaseImpl> IndexedDBDatabaseImpl::Create( |
- const string16& name, |
- IndexedDBBackingStore* database, |
- IndexedDBFactoryImpl* factory, |
- const string16& unique_identifier) { |
- scoped_refptr<IndexedDBDatabaseImpl> backend = |
- new IndexedDBDatabaseImpl(name, database, factory, unique_identifier); |
- if (!backend->OpenInternal()) |
- return 0; |
- return backend; |
-} |
- |
-namespace { |
-const base::string16::value_type kNoStringVersion[] = {0}; |
-} |
- |
-IndexedDBDatabaseImpl::IndexedDBDatabaseImpl( |
- const string16& name, |
- IndexedDBBackingStore* backing_store, |
- IndexedDBFactoryImpl* factory, |
- const string16& unique_identifier) |
- : backing_store_(backing_store), |
- metadata_(name, |
- kInvalidId, |
- kNoStringVersion, |
- IndexedDBDatabaseMetadata::NO_INT_VERSION, |
- kInvalidId), |
- identifier_(unique_identifier), |
- factory_(factory), |
- running_version_change_transaction_(NULL), |
- closing_connection_(false) { |
- DCHECK(!metadata_.name.empty()); |
-} |
- |
-void IndexedDBDatabaseImpl::AddObjectStore( |
- const IndexedDBObjectStoreMetadata& object_store, |
- int64 new_max_object_store_id) { |
- DCHECK(metadata_.object_stores.find(object_store.id) == |
- metadata_.object_stores.end()); |
- if (new_max_object_store_id != IndexedDBObjectStoreMetadata::kInvalidId) { |
- DCHECK_LT(metadata_.max_object_store_id, new_max_object_store_id); |
- metadata_.max_object_store_id = new_max_object_store_id; |
- } |
- metadata_.object_stores[object_store.id] = object_store; |
-} |
- |
-void IndexedDBDatabaseImpl::RemoveObjectStore(int64 object_store_id) { |
- DCHECK(metadata_.object_stores.find(object_store_id) != |
- metadata_.object_stores.end()); |
- metadata_.object_stores.erase(object_store_id); |
-} |
- |
-void IndexedDBDatabaseImpl::AddIndex(int64 object_store_id, |
- const IndexedDBIndexMetadata& index, |
- int64 new_max_index_id) { |
- DCHECK(metadata_.object_stores.find(object_store_id) != |
- metadata_.object_stores.end()); |
- IndexedDBObjectStoreMetadata object_store = |
- metadata_.object_stores[object_store_id]; |
- |
- DCHECK(object_store.indexes.find(index.id) == object_store.indexes.end()); |
- object_store.indexes[index.id] = index; |
- if (new_max_index_id != IndexedDBIndexMetadata::kInvalidId) { |
- DCHECK_LT(object_store.max_index_id, new_max_index_id); |
- object_store.max_index_id = new_max_index_id; |
- } |
- metadata_.object_stores[object_store_id] = object_store; |
-} |
- |
-void IndexedDBDatabaseImpl::RemoveIndex(int64 object_store_id, int64 index_id) { |
- DCHECK(metadata_.object_stores.find(object_store_id) != |
- metadata_.object_stores.end()); |
- IndexedDBObjectStoreMetadata object_store = |
- metadata_.object_stores[object_store_id]; |
- |
- DCHECK(object_store.indexes.find(index_id) != object_store.indexes.end()); |
- object_store.indexes.erase(index_id); |
- metadata_.object_stores[object_store_id] = object_store; |
-} |
- |
-bool IndexedDBDatabaseImpl::OpenInternal() { |
- bool success = false; |
- bool ok = backing_store_->GetIDBDatabaseMetaData( |
- metadata_.name, &metadata_, &success); |
- DCHECK(success == (metadata_.id != kInvalidId)) << "success = " << success |
- << " id_ = " << metadata_.id; |
- if (!ok) |
- return false; |
- if (success) |
- return backing_store_->GetObjectStores(metadata_.id, |
- &metadata_.object_stores); |
- |
- return backing_store_->CreateIDBDatabaseMetaData( |
- metadata_.name, metadata_.version, metadata_.int_version, &metadata_.id); |
-} |
- |
-IndexedDBDatabaseImpl::~IndexedDBDatabaseImpl() { |
- DCHECK(transactions_.empty()); |
- DCHECK(pending_open_calls_.empty()); |
- DCHECK(pending_delete_calls_.empty()); |
-} |
- |
-scoped_refptr<IndexedDBBackingStore> IndexedDBDatabaseImpl::BackingStore() |
- const { |
- return backing_store_; |
-} |
- |
-void IndexedDBDatabaseImpl::CreateObjectStore(int64 transaction_id, |
- int64 object_store_id, |
- const string16& name, |
- const IndexedDBKeyPath& key_path, |
- bool auto_increment) { |
- IDB_TRACE("IndexedDBDatabaseImpl::create_object_store"); |
- TransactionMap::const_iterator trans_iterator = |
- transactions_.find(transaction_id); |
- if (trans_iterator == transactions_.end()) |
- return; |
- IndexedDBTransaction* transaction = trans_iterator->second; |
- DCHECK_EQ(transaction->mode(), indexed_db::TRANSACTION_VERSION_CHANGE); |
- |
- DCHECK(metadata_.object_stores.find(object_store_id) == |
- metadata_.object_stores.end()); |
- IndexedDBObjectStoreMetadata object_store_metadata( |
- name, |
- object_store_id, |
- key_path, |
- auto_increment, |
- IndexedDBDatabase::kMinimumIndexId); |
- |
- transaction->ScheduleTask( |
- new CreateObjectStoreOperation(backing_store_, object_store_metadata), |
- new CreateObjectStoreAbortOperation(this, object_store_id)); |
- |
- AddObjectStore(object_store_metadata, object_store_id); |
-} |
- |
-void CreateObjectStoreOperation::Perform(IndexedDBTransaction* transaction) { |
- IDB_TRACE("CreateObjectStoreOperation"); |
- if (!backing_store_->CreateObjectStore( |
- transaction->BackingStoreTransaction(), |
- transaction->database()->id(), |
- object_store_metadata_.id, |
- object_store_metadata_.name, |
- object_store_metadata_.key_path, |
- object_store_metadata_.auto_increment)) { |
- transaction->Abort(IndexedDBDatabaseError( |
- WebKit::WebIDBDatabaseExceptionUnknownError, |
- ASCIIToUTF16("Internal error creating object store '") + |
- object_store_metadata_.name + ASCIIToUTF16("'."))); |
- return; |
- } |
-} |
- |
-void IndexedDBDatabaseImpl::DeleteObjectStore(int64 transaction_id, |
- int64 object_store_id) { |
- IDB_TRACE("IndexedDBDatabaseImpl::delete_object_store"); |
- TransactionMap::const_iterator trans_iterator = |
- transactions_.find(transaction_id); |
- if (trans_iterator == transactions_.end()) |
- return; |
- IndexedDBTransaction* transaction = trans_iterator->second; |
- DCHECK_EQ(transaction->mode(), indexed_db::TRANSACTION_VERSION_CHANGE); |
- |
- DCHECK(metadata_.object_stores.find(object_store_id) != |
- metadata_.object_stores.end()); |
- const IndexedDBObjectStoreMetadata& object_store_metadata = |
- metadata_.object_stores[object_store_id]; |
- |
- transaction->ScheduleTask( |
- new DeleteObjectStoreOperation(backing_store_, object_store_metadata), |
- new DeleteObjectStoreAbortOperation(this, object_store_metadata)); |
- RemoveObjectStore(object_store_id); |
-} |
- |
-void IndexedDBDatabaseImpl::CreateIndex(int64 transaction_id, |
- int64 object_store_id, |
- int64 index_id, |
- const string16& name, |
- const IndexedDBKeyPath& key_path, |
- bool unique, |
- bool multi_entry) { |
- IDB_TRACE("IndexedDBDatabaseImpl::create_index"); |
- TransactionMap::const_iterator trans_iterator = |
- transactions_.find(transaction_id); |
- if (trans_iterator == transactions_.end()) |
- return; |
- IndexedDBTransaction* transaction = trans_iterator->second; |
- DCHECK_EQ(transaction->mode(), indexed_db::TRANSACTION_VERSION_CHANGE); |
- |
- DCHECK(metadata_.object_stores.find(object_store_id) != |
- metadata_.object_stores.end()); |
- const IndexedDBObjectStoreMetadata object_store = |
- metadata_.object_stores[object_store_id]; |
- |
- DCHECK(object_store.indexes.find(index_id) == object_store.indexes.end()); |
- const IndexedDBIndexMetadata index_metadata( |
- name, index_id, key_path, unique, multi_entry); |
- |
- transaction->ScheduleTask( |
- new CreateIndexOperation(backing_store_, object_store_id, index_metadata), |
- new CreateIndexAbortOperation(this, object_store_id, index_id)); |
- |
- AddIndex(object_store_id, index_metadata, index_id); |
-} |
- |
-void CreateIndexOperation::Perform(IndexedDBTransaction* transaction) { |
- IDB_TRACE("CreateIndexOperation"); |
- if (!backing_store_->CreateIndex(transaction->BackingStoreTransaction(), |
- transaction->database()->id(), |
- object_store_id_, |
- index_metadata_.id, |
- index_metadata_.name, |
- index_metadata_.key_path, |
- index_metadata_.unique, |
- index_metadata_.multi_entry)) { |
- string16 error_string = ASCIIToUTF16("Internal error creating index '") + |
- index_metadata_.name + ASCIIToUTF16("'."); |
- transaction->Abort(IndexedDBDatabaseError( |
- WebKit::WebIDBDatabaseExceptionUnknownError, error_string)); |
- return; |
- } |
-} |
- |
-void CreateIndexAbortOperation::Perform(IndexedDBTransaction* transaction) { |
- IDB_TRACE("CreateIndexAbortOperation"); |
- DCHECK(!transaction); |
- database_->RemoveIndex(object_store_id_, index_id_); |
-} |
- |
-void IndexedDBDatabaseImpl::DeleteIndex(int64 transaction_id, |
- int64 object_store_id, |
- int64 index_id) { |
- IDB_TRACE("IndexedDBDatabaseImpl::delete_index"); |
- TransactionMap::const_iterator trans_iterator = |
- transactions_.find(transaction_id); |
- if (trans_iterator == transactions_.end()) |
- return; |
- IndexedDBTransaction* transaction = trans_iterator->second; |
- DCHECK_EQ(transaction->mode(), indexed_db::TRANSACTION_VERSION_CHANGE); |
- |
- DCHECK(metadata_.object_stores.find(object_store_id) != |
- metadata_.object_stores.end()); |
- IndexedDBObjectStoreMetadata object_store = |
- metadata_.object_stores[object_store_id]; |
- |
- DCHECK(object_store.indexes.find(index_id) != object_store.indexes.end()); |
- const IndexedDBIndexMetadata& index_metadata = object_store.indexes[index_id]; |
- |
- transaction->ScheduleTask( |
- new DeleteIndexOperation(backing_store_, object_store_id, index_metadata), |
- new DeleteIndexAbortOperation(this, object_store_id, index_metadata)); |
- |
- RemoveIndex(object_store_id, index_id); |
-} |
- |
-void DeleteIndexOperation::Perform(IndexedDBTransaction* transaction) { |
- IDB_TRACE("DeleteIndexOperation"); |
- bool ok = backing_store_->DeleteIndex(transaction->BackingStoreTransaction(), |
- transaction->database()->id(), |
- object_store_id_, |
- index_metadata_.id); |
- if (!ok) { |
- string16 error_string = ASCIIToUTF16("Internal error deleting index '") + |
- index_metadata_.name + ASCIIToUTF16("'."); |
- transaction->Abort(IndexedDBDatabaseError( |
- WebKit::WebIDBDatabaseExceptionUnknownError, error_string)); |
- } |
-} |
- |
-void DeleteIndexAbortOperation::Perform(IndexedDBTransaction* transaction) { |
- IDB_TRACE("DeleteIndexAbortOperation"); |
- DCHECK(!transaction); |
- database_->AddIndex( |
- object_store_id_, index_metadata_, IndexedDBIndexMetadata::kInvalidId); |
-} |
- |
-void IndexedDBDatabaseImpl::Commit(int64 transaction_id) { |
- // The frontend suggests that we commit, but we may have previously initiated |
- // an abort, and so have disposed of the transaction. on_abort has already |
- // been dispatched to the frontend, so it will find out about that |
- // asynchronously. |
- if (transactions_.find(transaction_id) != transactions_.end()) |
- transactions_[transaction_id]->Commit(); |
-} |
- |
-void IndexedDBDatabaseImpl::Abort(int64 transaction_id) { |
- // If the transaction is unknown, then it has already been aborted by the |
- // backend before this call so it is safe to ignore it. |
- if (transactions_.find(transaction_id) != transactions_.end()) |
- transactions_[transaction_id]->Abort(); |
-} |
- |
-void IndexedDBDatabaseImpl::Abort(int64 transaction_id, |
- const IndexedDBDatabaseError& error) { |
- // If the transaction is unknown, then it has already been aborted by the |
- // backend before this call so it is safe to ignore it. |
- if (transactions_.find(transaction_id) != transactions_.end()) |
- transactions_[transaction_id]->Abort(error); |
-} |
- |
-void IndexedDBDatabaseImpl::Get( |
- int64 transaction_id, |
- int64 object_store_id, |
- int64 index_id, |
- scoped_ptr<IndexedDBKeyRange> key_range, |
- bool key_only, |
- scoped_refptr<IndexedDBCallbacksWrapper> callbacks) { |
- IDB_TRACE("IndexedDBDatabaseImpl::get"); |
- TransactionMap::const_iterator trans_iterator = |
- transactions_.find(transaction_id); |
- if (trans_iterator == transactions_.end()) |
- return; |
- IndexedDBTransaction* transaction = trans_iterator->second; |
- |
- transaction->ScheduleTask(new GetOperation( |
- backing_store_, |
- metadata_, |
- object_store_id, |
- index_id, |
- key_range.Pass(), |
- key_only ? indexed_db::CURSOR_KEY_ONLY : indexed_db::CURSOR_KEY_AND_VALUE, |
- callbacks)); |
-} |
- |
-void GetOperation::Perform(IndexedDBTransaction* transaction) { |
- IDB_TRACE("GetOperation"); |
- |
- const IndexedDBKey* key; |
- |
- scoped_ptr<IndexedDBBackingStore::Cursor> backing_store_cursor; |
- if (key_range_->IsOnlyKey()) { |
- key = &key_range_->lower(); |
- } else { |
- if (index_id_ == IndexedDBIndexMetadata::kInvalidId) { |
- DCHECK_NE(cursor_type_, indexed_db::CURSOR_KEY_ONLY); |
- // ObjectStore Retrieval Operation |
- backing_store_cursor = backing_store_->OpenObjectStoreCursor( |
- transaction->BackingStoreTransaction(), |
- database_id_, |
- object_store_id_, |
- *key_range_, |
- indexed_db::CURSOR_NEXT); |
- } else if (cursor_type_ == indexed_db::CURSOR_KEY_ONLY) { |
- // Index Value Retrieval Operation |
- backing_store_cursor = backing_store_->OpenIndexKeyCursor( |
- transaction->BackingStoreTransaction(), |
- database_id_, |
- object_store_id_, |
- index_id_, |
- *key_range_, |
- indexed_db::CURSOR_NEXT); |
- } else { |
- // Index Referenced Value Retrieval Operation |
- backing_store_cursor = backing_store_->OpenIndexCursor( |
- transaction->BackingStoreTransaction(), |
- database_id_, |
- object_store_id_, |
- index_id_, |
- *key_range_, |
- indexed_db::CURSOR_NEXT); |
- } |
- |
- if (!backing_store_cursor) { |
- callbacks_->OnSuccess(); |
- return; |
- } |
- |
- key = &backing_store_cursor->key(); |
- } |
- |
- scoped_ptr<IndexedDBKey> primary_key; |
- bool ok; |
- if (index_id_ == IndexedDBIndexMetadata::kInvalidId) { |
- // Object Store Retrieval Operation |
- std::vector<char> value; |
- ok = backing_store_->GetRecord(transaction->BackingStoreTransaction(), |
- database_id_, |
- object_store_id_, |
- *key, |
- &value); |
- if (!ok) { |
- callbacks_->OnError(IndexedDBDatabaseError( |
- WebKit::WebIDBDatabaseExceptionUnknownError, |
- "Internal error in get_record.")); |
- return; |
- } |
- |
- if (value.empty()) { |
- callbacks_->OnSuccess(); |
- return; |
- } |
- |
- if (auto_increment_ && !key_path_.IsNull()) { |
- callbacks_->OnSuccess(&value, *key, key_path_); |
- return; |
- } |
- |
- callbacks_->OnSuccess(&value); |
- return; |
- } |
- |
- // From here we are dealing only with indexes. |
- ok = backing_store_->GetPrimaryKeyViaIndex( |
- transaction->BackingStoreTransaction(), |
- database_id_, |
- object_store_id_, |
- index_id_, |
- *key, |
- &primary_key); |
- if (!ok) { |
- callbacks_->OnError(IndexedDBDatabaseError( |
- WebKit::WebIDBDatabaseExceptionUnknownError, |
- "Internal error in get_primary_key_via_index.")); |
- return; |
- } |
- if (!primary_key) { |
- callbacks_->OnSuccess(); |
- return; |
- } |
- if (cursor_type_ == indexed_db::CURSOR_KEY_ONLY) { |
- // Index Value Retrieval Operation |
- callbacks_->OnSuccess(*primary_key); |
- return; |
- } |
- |
- // Index Referenced Value Retrieval Operation |
- std::vector<char> value; |
- ok = backing_store_->GetRecord(transaction->BackingStoreTransaction(), |
- database_id_, |
- object_store_id_, |
- *primary_key, |
- &value); |
- if (!ok) { |
- callbacks_->OnError( |
- IndexedDBDatabaseError(WebKit::WebIDBDatabaseExceptionUnknownError, |
- "Internal error in get_record.")); |
- return; |
- } |
- |
- if (value.empty()) { |
- callbacks_->OnSuccess(); |
- return; |
- } |
- if (auto_increment_ && !key_path_.IsNull()) { |
- callbacks_->OnSuccess(&value, *primary_key, key_path_); |
- return; |
- } |
- callbacks_->OnSuccess(&value); |
-} |
- |
-static scoped_ptr<IndexedDBKey> GenerateKey( |
- scoped_refptr<IndexedDBBackingStore> backing_store, |
- scoped_refptr<IndexedDBTransaction> transaction, |
- int64 database_id, |
- int64 object_store_id) { |
- const int64 max_generator_value = |
- 9007199254740992LL; // Maximum integer storable as ECMAScript number. |
- int64 current_number; |
- bool ok = backing_store->GetKeyGeneratorCurrentNumber( |
- transaction->BackingStoreTransaction(), |
- database_id, |
- object_store_id, |
- ¤t_number); |
- if (!ok) { |
- LOG(ERROR) << "Failed to get_key_generator_current_number"; |
- return make_scoped_ptr(new IndexedDBKey()); |
- } |
- if (current_number < 0 || current_number > max_generator_value) |
- return make_scoped_ptr(new IndexedDBKey()); |
- |
- return make_scoped_ptr( |
- new IndexedDBKey(current_number, WebIDBKey::NumberType)); |
-} |
- |
-static bool UpdateKeyGenerator( |
- scoped_refptr<IndexedDBBackingStore> backing_store, |
- scoped_refptr<IndexedDBTransaction> transaction, |
- int64 database_id, |
- int64 object_store_id, |
- const IndexedDBKey* key, |
- bool check_current) { |
- DCHECK(key); |
- DCHECK_EQ(WebIDBKey::NumberType, key->type()); |
- return backing_store->MaybeUpdateKeyGeneratorCurrentNumber( |
- transaction->BackingStoreTransaction(), |
- database_id, |
- object_store_id, |
- static_cast<int64>(floor(key->number())) + 1, |
- check_current); |
-} |
- |
-void IndexedDBDatabaseImpl::Put( |
- int64 transaction_id, |
- int64 object_store_id, |
- std::vector<char>* value, |
- scoped_ptr<IndexedDBKey> key, |
- PutMode put_mode, |
- scoped_refptr<IndexedDBCallbacksWrapper> callbacks, |
- const std::vector<int64>& index_ids, |
- const std::vector<IndexKeys>& index_keys) { |
- IDB_TRACE("IndexedDBDatabaseImpl::put"); |
- TransactionMap::const_iterator trans_iterator = |
- transactions_.find(transaction_id); |
- if (trans_iterator == transactions_.end()) |
- return; |
- IndexedDBTransaction* transaction = trans_iterator->second; |
- DCHECK_NE(transaction->mode(), indexed_db::TRANSACTION_READ_ONLY); |
- |
- const IndexedDBObjectStoreMetadata object_store_metadata = |
- metadata_.object_stores[object_store_id]; |
- |
- DCHECK(key); |
- DCHECK(object_store_metadata.auto_increment || key->IsValid()); |
- transaction->ScheduleTask(new PutOperation(backing_store_, |
- id(), |
- object_store_metadata, |
- value, |
- key.Pass(), |
- put_mode, |
- callbacks, |
- index_ids, |
- index_keys)); |
-} |
- |
-void PutOperation::Perform(IndexedDBTransaction* transaction) { |
- IDB_TRACE("PutOperation"); |
- DCHECK_NE(transaction->mode(), indexed_db::TRANSACTION_READ_ONLY); |
- DCHECK_EQ(index_ids_.size(), index_keys_.size()); |
- bool key_was_generated = false; |
- |
- scoped_ptr<IndexedDBKey> key; |
- if (put_mode_ != IndexedDBDatabase::CURSOR_UPDATE && |
- object_store_.auto_increment && !key_->IsValid()) { |
- scoped_ptr<IndexedDBKey> auto_inc_key = GenerateKey( |
- backing_store_, transaction, database_id_, object_store_.id); |
- key_was_generated = true; |
- if (!auto_inc_key->IsValid()) { |
- callbacks_->OnError(IndexedDBDatabaseError( |
- WebKit::WebIDBDatabaseExceptionConstraintError, |
- "Maximum key generator value reached.")); |
- return; |
- } |
- key = auto_inc_key.Pass(); |
- } else { |
- key = key_.Pass(); |
- } |
- |
- DCHECK(key->IsValid()); |
- |
- IndexedDBBackingStore::RecordIdentifier record_identifier; |
- if (put_mode_ == IndexedDBDatabase::ADD_ONLY) { |
- bool found = false; |
- bool ok = backing_store_->KeyExistsInObjectStore( |
- transaction->BackingStoreTransaction(), |
- database_id_, |
- object_store_.id, |
- *key.get(), |
- &record_identifier, |
- &found); |
- if (!ok) { |
- callbacks_->OnError(IndexedDBDatabaseError( |
- WebKit::WebIDBDatabaseExceptionUnknownError, |
- "Internal error checking key existence.")); |
- return; |
- } |
- if (found) { |
- callbacks_->OnError(IndexedDBDatabaseError( |
- WebKit::WebIDBDatabaseExceptionConstraintError, |
- "Key already exists in the object store.")); |
- return; |
- } |
- } |
- |
- ScopedVector<IndexedDBObjectStoreImpl::IndexWriter> index_writers; |
- string16 error_message; |
- bool obeys_constraints = false; |
- bool backing_store_success = |
- IndexedDBObjectStoreImpl::MakeIndexWriters(transaction, |
- backing_store_.get(), |
- database_id_, |
- object_store_, |
- *key, |
- key_was_generated, |
- index_ids_, |
- index_keys_, |
- &index_writers, |
- &error_message, |
- &obeys_constraints); |
- if (!backing_store_success) { |
- callbacks_->OnError(IndexedDBDatabaseError( |
- WebKit::WebIDBDatabaseExceptionUnknownError, |
- "Internal error: backing store error updating index keys.")); |
- return; |
- } |
- if (!obeys_constraints) { |
- callbacks_->OnError(IndexedDBDatabaseError( |
- WebKit::WebIDBDatabaseExceptionConstraintError, error_message)); |
- return; |
- } |
- |
- // Before this point, don't do any mutation. After this point, rollback the |
- // transaction in case of error. |
- backing_store_success = |
- backing_store_->PutRecord(transaction->BackingStoreTransaction(), |
- database_id_, |
- object_store_.id, |
- *key.get(), |
- value_, |
- &record_identifier); |
- if (!backing_store_success) { |
- callbacks_->OnError(IndexedDBDatabaseError( |
- WebKit::WebIDBDatabaseExceptionUnknownError, |
- "Internal error: backing store error performing put/add.")); |
- return; |
- } |
- |
- for (size_t i = 0; i < index_writers.size(); ++i) { |
- IndexedDBObjectStoreImpl::IndexWriter* index_writer = index_writers[i]; |
- index_writer->WriteIndexKeys(record_identifier, |
- backing_store_, |
- transaction->BackingStoreTransaction(), |
- database_id_, |
- object_store_.id); |
- } |
- |
- if (object_store_.auto_increment && |
- put_mode_ != IndexedDBDatabase::CURSOR_UPDATE && |
- key->type() == WebIDBKey::NumberType) { |
- bool ok = UpdateKeyGenerator(backing_store_, |
- transaction, |
- database_id_, |
- object_store_.id, |
- key.get(), |
- !key_was_generated); |
- if (!ok) { |
- callbacks_->OnError(IndexedDBDatabaseError( |
- WebKit::WebIDBDatabaseExceptionUnknownError, |
- "Internal error updating key generator.")); |
- return; |
- } |
- } |
- |
- callbacks_->OnSuccess(*key); |
-} |
- |
-void IndexedDBDatabaseImpl::SetIndexKeys( |
- int64 transaction_id, |
- int64 object_store_id, |
- scoped_ptr<IndexedDBKey> primary_key, |
- const std::vector<int64>& index_ids, |
- const std::vector<IndexKeys>& index_keys) { |
- IDB_TRACE("IndexedDBDatabaseImpl::set_index_keys"); |
- TransactionMap::const_iterator trans_iterator = |
- transactions_.find(transaction_id); |
- if (trans_iterator == transactions_.end()) |
- return; |
- IndexedDBTransaction* transaction = trans_iterator->second; |
- DCHECK_EQ(transaction->mode(), indexed_db::TRANSACTION_VERSION_CHANGE); |
- |
- scoped_refptr<IndexedDBBackingStore> store = BackingStore(); |
- // TODO(jsbell): This method could be asynchronous, but we need to |
- // evaluate if it's worth the extra complexity. |
- IndexedDBBackingStore::RecordIdentifier record_identifier; |
- bool found = false; |
- bool ok = |
- store->KeyExistsInObjectStore(transaction->BackingStoreTransaction(), |
- metadata_.id, |
- object_store_id, |
- *primary_key, |
- &record_identifier, |
- &found); |
- if (!ok) { |
- transaction->Abort(IndexedDBDatabaseError( |
- WebKit::WebIDBDatabaseExceptionUnknownError, |
- "Internal error setting index keys.")); |
- return; |
- } |
- if (!found) { |
- transaction->Abort(IndexedDBDatabaseError( |
- WebKit::WebIDBDatabaseExceptionUnknownError, |
- "Internal error setting index keys for object store.")); |
- return; |
- } |
- |
- ScopedVector<IndexedDBObjectStoreImpl::IndexWriter> index_writers; |
- string16 error_message; |
- bool obeys_constraints = false; |
- DCHECK(metadata_.object_stores.find(object_store_id) != |
- metadata_.object_stores.end()); |
- const IndexedDBObjectStoreMetadata& object_store_metadata = |
- metadata_.object_stores[object_store_id]; |
- bool backing_store_success = |
- IndexedDBObjectStoreImpl::MakeIndexWriters(transaction, |
- store.get(), |
- id(), |
- object_store_metadata, |
- *primary_key, |
- false, |
- index_ids, |
- index_keys, |
- &index_writers, |
- &error_message, |
- &obeys_constraints); |
- if (!backing_store_success) { |
- transaction->Abort(IndexedDBDatabaseError( |
- WebKit::WebIDBDatabaseExceptionUnknownError, |
- "Internal error: backing store error updating index keys.")); |
- return; |
- } |
- if (!obeys_constraints) { |
- transaction->Abort(IndexedDBDatabaseError( |
- WebKit::WebIDBDatabaseExceptionConstraintError, error_message)); |
- return; |
- } |
- |
- for (size_t i = 0; i < index_writers.size(); ++i) { |
- IndexedDBObjectStoreImpl::IndexWriter* index_writer = index_writers[i]; |
- index_writer->WriteIndexKeys(record_identifier, |
- store.get(), |
- transaction->BackingStoreTransaction(), |
- id(), |
- object_store_id); |
- } |
-} |
- |
-void IndexedDBDatabaseImpl::SetIndexesReady( |
- int64 transaction_id, |
- int64, |
- const std::vector<int64>& index_ids) { |
- IDB_TRACE("IndexedDBObjectStoreImpl::set_indexes_ready"); |
- |
- TransactionMap::const_iterator trans_iterator = |
- transactions_.find(transaction_id); |
- if (trans_iterator == transactions_.end()) |
- return; |
- IndexedDBTransaction* transaction = trans_iterator->second; |
- |
- transaction->ScheduleTask(IndexedDBDatabase::PREEMPTIVE_TASK, |
- new SetIndexesReadyOperation(index_ids.size())); |
-} |
- |
-void SetIndexesReadyOperation::Perform(IndexedDBTransaction* transaction) { |
- IDB_TRACE("SetIndexesReadyOperation"); |
- for (size_t i = 0; i < index_count_; ++i) |
- transaction->DidCompletePreemptiveEvent(); |
-} |
- |
-void IndexedDBDatabaseImpl::OpenCursor( |
- int64 transaction_id, |
- int64 object_store_id, |
- int64 index_id, |
- scoped_ptr<IndexedDBKeyRange> key_range, |
- indexed_db::CursorDirection direction, |
- bool key_only, |
- TaskType task_type, |
- scoped_refptr<IndexedDBCallbacksWrapper> callbacks) { |
- IDB_TRACE("IndexedDBDatabaseImpl::open_cursor"); |
- TransactionMap::const_iterator trans_iterator = |
- transactions_.find(transaction_id); |
- if (trans_iterator == transactions_.end()) |
- return; |
- IndexedDBTransaction* transaction = trans_iterator->second; |
- |
- transaction->ScheduleTask(new OpenCursorOperation( |
- backing_store_, |
- id(), |
- object_store_id, |
- index_id, |
- key_range.Pass(), |
- direction, |
- key_only ? indexed_db::CURSOR_KEY_ONLY : indexed_db::CURSOR_KEY_AND_VALUE, |
- task_type, |
- callbacks)); |
-} |
- |
-void OpenCursorOperation::Perform(IndexedDBTransaction* transaction) { |
- IDB_TRACE("OpenCursorOperation"); |
- |
- // The frontend has begun indexing, so this pauses the transaction |
- // until the indexing is complete. This can't happen any earlier |
- // because we don't want to switch to early mode in case multiple |
- // indexes are being created in a row, with Put()'s in between. |
- if (task_type_ == IndexedDBDatabase::PREEMPTIVE_TASK) |
- transaction->AddPreemptiveEvent(); |
- |
- scoped_ptr<IndexedDBBackingStore::Cursor> backing_store_cursor; |
- if (index_id_ == IndexedDBIndexMetadata::kInvalidId) { |
- DCHECK_NE(cursor_type_, indexed_db::CURSOR_KEY_ONLY); |
- backing_store_cursor = backing_store_->OpenObjectStoreCursor( |
- transaction->BackingStoreTransaction(), |
- database_id_, |
- object_store_id_, |
- *key_range_, |
- direction_); |
- } else { |
- DCHECK_EQ(task_type_, IndexedDBDatabase::NORMAL_TASK); |
- if (cursor_type_ == indexed_db::CURSOR_KEY_ONLY) { |
- backing_store_cursor = backing_store_->OpenIndexKeyCursor( |
- transaction->BackingStoreTransaction(), |
- database_id_, |
- object_store_id_, |
- index_id_, |
- *key_range_, |
- direction_); |
- } else { |
- backing_store_cursor = backing_store_->OpenIndexCursor( |
- transaction->BackingStoreTransaction(), |
- database_id_, |
- object_store_id_, |
- index_id_, |
- *key_range_, |
- direction_); |
- } |
- } |
- |
- if (!backing_store_cursor) { |
- callbacks_->OnSuccess(static_cast<std::vector<char>*>(NULL)); |
- return; |
- } |
- |
- IndexedDBDatabase::TaskType task_type( |
- static_cast<IndexedDBDatabase::TaskType>(task_type_)); |
- scoped_refptr<IndexedDBCursorImpl> cursor = IndexedDBCursorImpl::Create( |
- backing_store_cursor.Pass(), cursor_type_, task_type, transaction); |
- callbacks_->OnSuccess( |
- cursor, cursor->key(), cursor->primary_key(), cursor->Value()); |
-} |
- |
-void IndexedDBDatabaseImpl::Count( |
- int64 transaction_id, |
- int64 object_store_id, |
- int64 index_id, |
- scoped_ptr<IndexedDBKeyRange> key_range, |
- scoped_refptr<IndexedDBCallbacksWrapper> callbacks) { |
- IDB_TRACE("IndexedDBDatabaseImpl::count"); |
- TransactionMap::const_iterator trans_iterator = |
- transactions_.find(transaction_id); |
- if (trans_iterator == transactions_.end()) |
- return; |
- IndexedDBTransaction* transaction = trans_iterator->second; |
- |
- DCHECK(metadata_.object_stores.find(object_store_id) != |
- metadata_.object_stores.end()); |
- transaction->ScheduleTask(new CountOperation(backing_store_, |
- id(), |
- object_store_id, |
- index_id, |
- key_range.Pass(), |
- callbacks)); |
-} |
- |
-void CountOperation::Perform(IndexedDBTransaction* transaction) { |
- IDB_TRACE("CountOperation"); |
- uint32 count = 0; |
- scoped_ptr<IndexedDBBackingStore::Cursor> backing_store_cursor; |
- |
- if (index_id_ == IndexedDBIndexMetadata::kInvalidId) { |
- backing_store_cursor = backing_store_->OpenObjectStoreKeyCursor( |
- transaction->BackingStoreTransaction(), |
- database_id_, |
- object_store_id_, |
- *key_range_, |
- indexed_db::CURSOR_NEXT); |
- } else { |
- backing_store_cursor = backing_store_->OpenIndexKeyCursor( |
- transaction->BackingStoreTransaction(), |
- database_id_, |
- object_store_id_, |
- index_id_, |
- *key_range_, |
- indexed_db::CURSOR_NEXT); |
- } |
- if (!backing_store_cursor) { |
- callbacks_->OnSuccess(count); |
- return; |
- } |
- |
- do { |
- ++count; |
- } while (backing_store_cursor->ContinueFunction(0)); |
- |
- callbacks_->OnSuccess(count); |
-} |
- |
-void IndexedDBDatabaseImpl::DeleteRange( |
- int64 transaction_id, |
- int64 object_store_id, |
- scoped_ptr<IndexedDBKeyRange> key_range, |
- scoped_refptr<IndexedDBCallbacksWrapper> callbacks) { |
- IDB_TRACE("IndexedDBDatabaseImpl::delete_range"); |
- TransactionMap::const_iterator trans_iterator = |
- transactions_.find(transaction_id); |
- if (trans_iterator == transactions_.end()) |
- return; |
- IndexedDBTransaction* transaction = trans_iterator->second; |
- |
- transaction->ScheduleTask(new DeleteRangeOperation( |
- backing_store_, id(), object_store_id, key_range.Pass(), callbacks)); |
-} |
- |
-void DeleteRangeOperation::Perform(IndexedDBTransaction* transaction) { |
- IDB_TRACE("DeleteRangeOperation"); |
- scoped_ptr<IndexedDBBackingStore::Cursor> backing_store_cursor = |
- backing_store_->OpenObjectStoreCursor( |
- transaction->BackingStoreTransaction(), |
- database_id_, |
- object_store_id_, |
- *key_range_, |
- indexed_db::CURSOR_NEXT); |
- if (backing_store_cursor) { |
- do { |
- if (!backing_store_->DeleteRecord( |
- transaction->BackingStoreTransaction(), |
- database_id_, |
- object_store_id_, |
- backing_store_cursor->record_identifier())) { |
- callbacks_->OnError(IndexedDBDatabaseError( |
- WebKit::WebIDBDatabaseExceptionUnknownError, |
- "Internal error deleting data in range")); |
- return; |
- } |
- } while (backing_store_cursor->ContinueFunction(0)); |
- } |
- |
- callbacks_->OnSuccess(); |
-} |
- |
-void IndexedDBDatabaseImpl::Clear( |
- int64 transaction_id, |
- int64 object_store_id, |
- scoped_refptr<IndexedDBCallbacksWrapper> callbacks) { |
- IDB_TRACE("IndexedDBDatabaseImpl::clear"); |
- TransactionMap::const_iterator trans_iterator = |
- transactions_.find(transaction_id); |
- if (trans_iterator == transactions_.end()) |
- return; |
- IndexedDBTransaction* transaction = trans_iterator->second; |
- DCHECK_NE(transaction->mode(), indexed_db::TRANSACTION_READ_ONLY); |
- |
- transaction->ScheduleTask( |
- new ClearOperation(backing_store_, id(), object_store_id, callbacks)); |
-} |
- |
-void ClearOperation::Perform(IndexedDBTransaction* transaction) { |
- IDB_TRACE("ObjectStoreClearOperation"); |
- if (!backing_store_->ClearObjectStore(transaction->BackingStoreTransaction(), |
- database_id_, |
- object_store_id_)) { |
- callbacks_->OnError(IndexedDBDatabaseError( |
- WebKit::WebIDBDatabaseExceptionUnknownError, |
- "Internal error clearing object store")); |
- return; |
- } |
- callbacks_->OnSuccess(); |
-} |
- |
-void DeleteObjectStoreOperation::Perform(IndexedDBTransaction* transaction) { |
- IDB_TRACE("DeleteObjectStoreOperation"); |
- bool ok = |
- backing_store_->DeleteObjectStore(transaction->BackingStoreTransaction(), |
- transaction->database()->id(), |
- object_store_metadata_.id); |
- if (!ok) { |
- string16 error_string = |
- ASCIIToUTF16("Internal error deleting object store '") + |
- object_store_metadata_.name + ASCIIToUTF16("'."); |
- transaction->Abort(IndexedDBDatabaseError( |
- WebKit::WebIDBDatabaseExceptionUnknownError, error_string)); |
- } |
-} |
- |
-void IndexedDBDatabaseImpl::VersionChangeOperation::Perform( |
- IndexedDBTransaction* transaction) { |
- IDB_TRACE("VersionChangeOperation"); |
- int64 database_id = database_->id(); |
- int64 old_version = database_->metadata_.int_version; |
- DCHECK_GT(version_, old_version); |
- database_->metadata_.int_version = version_; |
- if (!database_->backing_store_->UpdateIDBDatabaseIntVersion( |
- transaction->BackingStoreTransaction(), |
- database_id, |
- database_->metadata_.int_version)) { |
- IndexedDBDatabaseError error( |
- WebKit::WebIDBDatabaseExceptionUnknownError, |
- ASCIIToUTF16("Internal error writing data to stable storage when " |
- "updating version.")); |
- callbacks_->OnError(error); |
- transaction->Abort(error); |
- return; |
- } |
- DCHECK(!database_->pending_second_half_open_); |
- database_->pending_second_half_open_.reset(new PendingOpenCall( |
- callbacks_, database_callbacks_, transaction_id_, version_)); |
- callbacks_->OnUpgradeNeeded(old_version, database_, database_->metadata()); |
-} |
- |
-void IndexedDBDatabaseImpl::TransactionStarted( |
- IndexedDBTransaction* transaction) { |
- |
- if (transaction->mode() == indexed_db::TRANSACTION_VERSION_CHANGE) { |
- DCHECK(!running_version_change_transaction_); |
- running_version_change_transaction_ = transaction; |
- } |
-} |
- |
-void IndexedDBDatabaseImpl::TransactionFinished( |
- IndexedDBTransaction* transaction) { |
- |
- DCHECK(transactions_.find(transaction->id()) != transactions_.end()); |
- DCHECK_EQ(transactions_[transaction->id()], transaction); |
- transactions_.erase(transaction->id()); |
- if (transaction->mode() == indexed_db::TRANSACTION_VERSION_CHANGE) { |
- DCHECK_EQ(transaction, running_version_change_transaction_); |
- running_version_change_transaction_ = NULL; |
- } |
-} |
- |
-void IndexedDBDatabaseImpl::TransactionFinishedAndAbortFired( |
- IndexedDBTransaction* transaction) { |
- if (transaction->mode() == indexed_db::TRANSACTION_VERSION_CHANGE) { |
- if (pending_second_half_open_) { |
- pending_second_half_open_->Callbacks()->OnError(IndexedDBDatabaseError( |
- WebKit::WebIDBDatabaseExceptionAbortError, |
- "Version change transaction was aborted in " |
- "upgradeneeded event handler.")); |
- pending_second_half_open_.reset(); |
- } |
- ProcessPendingCalls(); |
- } |
-} |
- |
-void IndexedDBDatabaseImpl::TransactionFinishedAndCompleteFired( |
- IndexedDBTransaction* transaction) { |
- if (transaction->mode() == indexed_db::TRANSACTION_VERSION_CHANGE) { |
- DCHECK(pending_second_half_open_); |
- if (pending_second_half_open_) { |
- DCHECK_EQ(pending_second_half_open_->Version(), metadata_.int_version); |
- DCHECK(metadata_.id != kInvalidId); |
- pending_second_half_open_->Callbacks()->OnSuccess(this, this->metadata()); |
- pending_second_half_open_.reset(); |
- } |
- ProcessPendingCalls(); |
- } |
-} |
- |
-size_t IndexedDBDatabaseImpl::ConnectionCount() const { |
- // This does not include pending open calls, as those should not block version |
- // changes and deletes. |
- return database_callbacks_set_.size(); |
-} |
- |
-void IndexedDBDatabaseImpl::ProcessPendingCalls() { |
- if (pending_second_half_open_) { |
- DCHECK_EQ(pending_second_half_open_->Version(), metadata_.int_version); |
- DCHECK(metadata_.id != kInvalidId); |
- scoped_ptr<PendingOpenCall> pending_call = pending_second_half_open_.Pass(); |
- pending_call->Callbacks()->OnSuccess(this, this->metadata()); |
- // Fall through when complete, as pending opens may be unblocked. |
- } |
- |
- if (pending_run_version_change_transaction_call_ && ConnectionCount() == 1) { |
- DCHECK(pending_run_version_change_transaction_call_->Version() > |
- metadata_.int_version); |
- scoped_ptr<PendingOpenCall> pending_call = |
- pending_run_version_change_transaction_call_.Pass(); |
- RunVersionChangeTransactionFinal(pending_call->Callbacks(), |
- pending_call->DatabaseCallbacks(), |
- pending_call->TransactionId(), |
- pending_call->Version()); |
- DCHECK_EQ(static_cast<size_t>(1), ConnectionCount()); |
- // Fall through would be a no-op, since transaction must complete |
- // asynchronously. |
- DCHECK(IsDeleteDatabaseBlocked()); |
- DCHECK(IsOpenConnectionBlocked()); |
- return; |
- } |
- |
- if (!IsDeleteDatabaseBlocked()) { |
- PendingDeleteCallList pending_delete_calls; |
- pending_delete_calls_.swap(pending_delete_calls); |
- while (!pending_delete_calls.empty()) { |
- // Only the first delete call will delete the database, but each must fire |
- // callbacks. |
- scoped_ptr<PendingDeleteCall> pending_delete_call( |
- pending_delete_calls.front()); |
- pending_delete_calls.pop_front(); |
- DeleteDatabaseFinal(pending_delete_call->Callbacks()); |
- } |
- // delete_database_final should never re-queue calls. |
- DCHECK(pending_delete_calls_.empty()); |
- // Fall through when complete, as pending opens may be unblocked. |
- } |
- |
- if (!IsOpenConnectionBlocked()) { |
- PendingOpenCallList pending_open_calls; |
- pending_open_calls_.swap(pending_open_calls); |
- while (!pending_open_calls.empty()) { |
- scoped_ptr<PendingOpenCall> pending_open_call(pending_open_calls.front()); |
- pending_open_calls.pop_front(); |
- OpenConnection(pending_open_call->Callbacks(), |
- pending_open_call->DatabaseCallbacks(), |
- pending_open_call->TransactionId(), |
- pending_open_call->Version()); |
- } |
- } |
-} |
- |
-void IndexedDBDatabaseImpl::CreateTransaction( |
- int64 transaction_id, |
- scoped_refptr<IndexedDBDatabaseCallbacksWrapper> callbacks, |
- const std::vector<int64>& object_store_ids, |
- uint16 mode) { |
- |
- DCHECK(database_callbacks_set_.has(callbacks)); |
- |
- scoped_refptr<IndexedDBTransaction> transaction = |
- IndexedDBTransaction::Create( |
- transaction_id, |
- callbacks, |
- object_store_ids, |
- static_cast<indexed_db::TransactionMode>(mode), |
- this); |
- DCHECK(transactions_.find(transaction_id) == transactions_.end()); |
- transactions_[transaction_id] = transaction; |
-} |
- |
-bool IndexedDBDatabaseImpl::IsOpenConnectionBlocked() const { |
- return !pending_delete_calls_.empty() || |
- running_version_change_transaction_ || |
- pending_run_version_change_transaction_call_; |
-} |
- |
-void IndexedDBDatabaseImpl::OpenConnection( |
- scoped_refptr<IndexedDBCallbacksWrapper> callbacks, |
- scoped_refptr<IndexedDBDatabaseCallbacksWrapper> database_callbacks, |
- int64 transaction_id, |
- int64 version) { |
- DCHECK(backing_store_.get()); |
- |
- // TODO(jsbell): Should have a priority queue so that higher version |
- // requests are processed first. http://crbug.com/225850 |
- if (IsOpenConnectionBlocked()) { |
- pending_open_calls_.push_back(new PendingOpenCall( |
- callbacks, database_callbacks, transaction_id, version)); |
- return; |
- } |
- |
- if (metadata_.id == kInvalidId) { |
- // The database was deleted then immediately re-opened; OpenInternal() |
- // recreates it in the backing store. |
- if (OpenInternal()) { |
- DCHECK_EQ(metadata_.int_version, |
- IndexedDBDatabaseMetadata::NO_INT_VERSION); |
- } else { |
- string16 message; |
- if (version == IndexedDBDatabaseMetadata::NO_INT_VERSION) |
- message = ASCIIToUTF16( |
- "Internal error opening database with no version specified."); |
- else |
- message = |
- ASCIIToUTF16("Internal error opening database with version ") + |
- Int64ToString16(version); |
- callbacks->OnError(IndexedDBDatabaseError( |
- WebKit::WebIDBDatabaseExceptionUnknownError, message)); |
- return; |
- } |
- } |
- |
- // We infer that the database didn't exist from its lack of either type of |
- // version. |
- bool is_new_database = |
- metadata_.version == kNoStringVersion && |
- metadata_.int_version == IndexedDBDatabaseMetadata::NO_INT_VERSION; |
- |
- if (version == IndexedDBDatabaseMetadata::DEFAULT_INT_VERSION) { |
- // For unit tests only - skip upgrade steps. Calling from script with |
- // DEFAULT_INT_VERSION throws exception. |
- // TODO(jsbell): Assert that we're executing a unit test. |
- DCHECK(is_new_database); |
- database_callbacks_set_.insert(database_callbacks); |
- callbacks->OnSuccess(this, this->metadata()); |
- return; |
- } |
- |
- if (version == IndexedDBDatabaseMetadata::NO_INT_VERSION) { |
- if (!is_new_database) { |
- database_callbacks_set_.insert(database_callbacks); |
- callbacks->OnSuccess(this, this->metadata()); |
- return; |
- } |
- // Spec says: If no version is specified and no database exists, set |
- // database version to 1. |
- version = 1; |
- } |
- |
- if (version > metadata_.int_version) { |
- database_callbacks_set_.insert(database_callbacks); |
- RunVersionChangeTransaction( |
- callbacks, database_callbacks, transaction_id, version); |
- return; |
- } |
- if (version < metadata_.int_version) { |
- callbacks->OnError(IndexedDBDatabaseError( |
- WebKit::WebIDBDatabaseExceptionVersionError, |
- ASCIIToUTF16("The requested version (") + Int64ToString16(version) + |
- ASCIIToUTF16(") is less than the existing version (") + |
- Int64ToString16(metadata_.int_version) + ASCIIToUTF16(")."))); |
- return; |
- } |
- DCHECK_EQ(version, metadata_.int_version); |
- database_callbacks_set_.insert(database_callbacks); |
- callbacks->OnSuccess(this, this->metadata()); |
-} |
- |
-void IndexedDBDatabaseImpl::RunVersionChangeTransaction( |
- scoped_refptr<IndexedDBCallbacksWrapper> callbacks, |
- scoped_refptr<IndexedDBDatabaseCallbacksWrapper> database_callbacks, |
- int64 transaction_id, |
- int64 requested_version) { |
- |
- DCHECK(callbacks); |
- DCHECK(database_callbacks_set_.has(database_callbacks)); |
- if (ConnectionCount() > 1) { |
- // Front end ensures the event is not fired at connections that have |
- // close_pending set. |
- for (DatabaseCallbacksSet::const_iterator it = |
- database_callbacks_set_.begin(); |
- it != database_callbacks_set_.end(); |
- ++it) { |
- if (*it != database_callbacks.get()) |
- (*it)->OnVersionChange(metadata_.int_version, requested_version); |
- } |
- // TODO(jsbell): Remove the call to on_blocked and instead wait |
- // until the frontend tells us that all the "versionchange" events |
- // have been delivered. http://crbug.com/100123 |
- callbacks->OnBlocked(metadata_.int_version); |
- |
- DCHECK(!pending_run_version_change_transaction_call_); |
- pending_run_version_change_transaction_call_.reset(new PendingOpenCall( |
- callbacks, database_callbacks, transaction_id, requested_version)); |
- return; |
- } |
- RunVersionChangeTransactionFinal( |
- callbacks, database_callbacks, transaction_id, requested_version); |
-} |
- |
-void IndexedDBDatabaseImpl::RunVersionChangeTransactionFinal( |
- scoped_refptr<IndexedDBCallbacksWrapper> callbacks, |
- scoped_refptr<IndexedDBDatabaseCallbacksWrapper> database_callbacks, |
- int64 transaction_id, |
- int64 requested_version) { |
- |
- std::vector<int64> object_store_ids; |
- CreateTransaction(transaction_id, |
- database_callbacks, |
- object_store_ids, |
- indexed_db::TRANSACTION_VERSION_CHANGE); |
- scoped_refptr<IndexedDBTransaction> transaction = |
- transactions_[transaction_id]; |
- |
- transaction->ScheduleTask( |
- new VersionChangeOperation(this, |
- transaction_id, |
- requested_version, |
- callbacks, |
- database_callbacks), |
- new VersionChangeAbortOperation( |
- this, metadata_.version, metadata_.int_version)); |
- |
- DCHECK(!pending_second_half_open_); |
-} |
- |
-void IndexedDBDatabaseImpl::DeleteDatabase( |
- scoped_refptr<IndexedDBCallbacksWrapper> callbacks) { |
- |
- if (IsDeleteDatabaseBlocked()) { |
- for (DatabaseCallbacksSet::const_iterator it = |
- database_callbacks_set_.begin(); |
- it != database_callbacks_set_.end(); |
- ++it) { |
- // Front end ensures the event is not fired at connections that have |
- // close_pending set. |
- (*it)->OnVersionChange(metadata_.int_version, |
- IndexedDBDatabaseMetadata::NO_INT_VERSION); |
- } |
- // TODO(jsbell): Only fire on_blocked if there are open |
- // connections after the VersionChangeEvents are received, not |
- // just set up to fire. http://crbug.com/100123 |
- callbacks->OnBlocked(metadata_.int_version); |
- pending_delete_calls_.push_back(new PendingDeleteCall(callbacks)); |
- return; |
- } |
- DeleteDatabaseFinal(callbacks); |
-} |
- |
-bool IndexedDBDatabaseImpl::IsDeleteDatabaseBlocked() const { |
- return !!ConnectionCount(); |
-} |
- |
-void IndexedDBDatabaseImpl::DeleteDatabaseFinal( |
- scoped_refptr<IndexedDBCallbacksWrapper> callbacks) { |
- DCHECK(!IsDeleteDatabaseBlocked()); |
- DCHECK(backing_store_); |
- if (!backing_store_->DeleteDatabase(metadata_.name)) { |
- callbacks->OnError(IndexedDBDatabaseError( |
- WebKit::WebIDBDatabaseExceptionUnknownError, |
- "Internal error deleting database.")); |
- return; |
- } |
- metadata_.version = kNoStringVersion; |
- metadata_.id = kInvalidId; |
- metadata_.int_version = IndexedDBDatabaseMetadata::NO_INT_VERSION; |
- metadata_.object_stores.clear(); |
- callbacks->OnSuccess(); |
-} |
- |
-void IndexedDBDatabaseImpl::Close( |
- scoped_refptr<IndexedDBDatabaseCallbacksWrapper> callbacks) { |
- DCHECK(callbacks); |
- DCHECK(database_callbacks_set_.has(callbacks)); |
- |
- // Close outstanding transactions from the closing connection. This |
- // can not happen if the close is requested by the connection itself |
- // as the front-end defers the close until all transactions are |
- // complete, so something unusual has happened e.g. unexpected |
- // process termination. |
- { |
- TransactionMap transactions(transactions_); |
- for (TransactionMap::const_iterator it = transactions.begin(), |
- end = transactions.end(); |
- it != end; |
- ++it) { |
- if (it->second->connection() == callbacks) |
- it->second->Abort( |
- IndexedDBDatabaseError(WebKit::WebIDBDatabaseExceptionUnknownError, |
- "Connection is closing.")); |
- } |
- } |
- |
- database_callbacks_set_.erase(callbacks); |
- if (pending_second_half_open_ && |
- pending_second_half_open_->DatabaseCallbacks() == callbacks) { |
- pending_second_half_open_->Callbacks()->OnError( |
- IndexedDBDatabaseError(WebKit::WebIDBDatabaseExceptionAbortError, |
- "The connection was closed.")); |
- pending_second_half_open_.reset(); |
- } |
- |
- // process_pending_calls allows the inspector to process a pending open call |
- // and call close, reentering IndexedDBDatabaseImpl::close. Then the |
- // backend would be removed both by the inspector closing its connection, and |
- // by the connection that first called close. |
- // To avoid that situation, don't proceed in case of reentrancy. |
- if (closing_connection_) |
- return; |
- base::AutoReset<bool> ClosingConnection(&closing_connection_, true); |
- ProcessPendingCalls(); |
- |
- // TODO(jsbell): Add a test for the pending_open_calls_ cases below. |
- if (!ConnectionCount() && !pending_open_calls_.size() && |
- !pending_delete_calls_.size()) { |
- DCHECK(transactions_.empty()); |
- |
- backing_store_ = NULL; |
- |
- // This check should only be false in unit tests. |
- // TODO(jsbell): Assert factory_ || we're executing a unit test. |
- if (factory_) |
- factory_->RemoveIDBDatabaseBackend(identifier_); |
- } |
-} |
- |
-void CreateObjectStoreAbortOperation::Perform( |
- IndexedDBTransaction* transaction) { |
- IDB_TRACE("CreateObjectStoreAbortOperation"); |
- DCHECK(!transaction); |
- database_->RemoveObjectStore(object_store_id_); |
-} |
- |
-void DeleteObjectStoreAbortOperation::Perform( |
- IndexedDBTransaction* transaction) { |
- IDB_TRACE("DeleteObjectStoreAbortOperation"); |
- DCHECK(!transaction); |
- database_->AddObjectStore(object_store_metadata_, |
- IndexedDBObjectStoreMetadata::kInvalidId); |
-} |
- |
-void IndexedDBDatabaseImpl::VersionChangeAbortOperation::Perform( |
- IndexedDBTransaction* transaction) { |
- IDB_TRACE("VersionChangeAbortOperation"); |
- DCHECK(!transaction); |
- database_->metadata_.version = previous_version_; |
- database_->metadata_.int_version = previous_int_version_; |
-} |
- |
-} // namespace content |