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. 4 5 #ifndef CONTENT_BROWSER_INDEXED_DB_INDEXED_DB_TRANSACTION_H_ 6 #define CONTENT_BROWSER_INDEXED_DB_INDEXED_DB_TRANSACTION_H_ 7 8 #include <queue> 9 #include <set> 10 #include <stack> 11 12 #include "base/basictypes.h" 13 #include "base/memory/ref_counted.h" 14 #include "base/memory/scoped_ptr.h" 15 #include "base/time/time.h" 16 #include "base/timer/timer.h" 17 #include "content/browser/indexed_db/indexed_db_backing_store.h" 18 #include "content/browser/indexed_db/indexed_db_database.h" 19 #include "content/browser/indexed_db/indexed_db_database_error.h" 20 21 namespace content { 22 23 class BlobWriteCallbackImpl; 24 class IndexedDBCursor; 25 class IndexedDBDatabaseCallbacks; 26 27 class CONTENT_EXPORT IndexedDBTransaction 28 : public NON_EXPORTED_BASE(base::RefCounted<IndexedDBTransaction>) { 29 public: 30 typedef base::Callback<void(IndexedDBTransaction*)> Operation; 31 32 IndexedDBTransaction( 33 int64 id, 34 scoped_refptr<IndexedDBDatabaseCallbacks> callbacks, 35 const std::set<int64>& object_store_ids, 36 indexed_db::TransactionMode, 37 IndexedDBDatabase* db, 38 IndexedDBBackingStore::Transaction* backing_store_transaction); 39 40 virtual void Abort(); 41 void Commit(); 42 void Abort(const IndexedDBDatabaseError& error); 43 44 // Called by the transaction coordinator when this transaction is unblocked. 45 void Start(); 46 47 indexed_db::TransactionMode mode() const { return mode_; } 48 const std::set<int64>& scope() const { return object_store_ids_; } 49 50 void ScheduleTask(Operation task) { 51 ScheduleTask(IndexedDBDatabase::NORMAL_TASK, task); 52 } 53 void ScheduleTask(IndexedDBDatabase::TaskType, Operation task); 54 void ScheduleAbortTask(Operation abort_task); 55 void RegisterOpenCursor(IndexedDBCursor* cursor); 56 void UnregisterOpenCursor(IndexedDBCursor* cursor); 57 void AddPreemptiveEvent() { pending_preemptive_events_++; } 58 void DidCompletePreemptiveEvent() { 59 pending_preemptive_events_--; 60 DCHECK_GE(pending_preemptive_events_, 0); 61 } 62 IndexedDBBackingStore::Transaction* BackingStoreTransaction() { 63 return transaction_.get(); 64 } 65 int64 id() const { return id_; } 66 67 IndexedDBDatabase* database() const { return database_; } 68 IndexedDBDatabaseCallbacks* connection() const { return callbacks_; } 69 70 enum State { 71 CREATED, // Created, but not yet started by coordinator. 72 STARTED, // Started by the coordinator. 73 COMMITTING, // In the process of committing, possibly waiting for blobs 74 // to be written. 75 FINISHED, // Either aborted or committed. 76 }; 77 78 State state() const { return state_; } 79 bool IsTimeoutTimerRunning() const { return timeout_timer_.IsRunning(); } 80 81 struct Diagnostics { 82 base::Time creation_time; 83 base::Time start_time; 84 int tasks_scheduled; 85 int tasks_completed; 86 }; 87 88 const Diagnostics& diagnostics() const { return diagnostics_; } 89 90 private: 91 friend class BlobWriteCallbackImpl; 92 93 FRIEND_TEST_ALL_PREFIXES(IndexedDBTransactionTestMode, AbortPreemptive); 94 FRIEND_TEST_ALL_PREFIXES(IndexedDBTransactionTest, Timeout); 95 FRIEND_TEST_ALL_PREFIXES(IndexedDBTransactionTest, 96 SchedulePreemptiveTask); 97 FRIEND_TEST_ALL_PREFIXES(IndexedDBTransactionTestMode, 98 ScheduleNormalTask); 99 100 friend class base::RefCounted<IndexedDBTransaction>; 101 virtual ~IndexedDBTransaction(); 102 103 void RunTasksIfStarted(); 104 105 bool IsTaskQueueEmpty() const; 106 bool HasPendingTasks() const; 107 108 void BlobWriteComplete(bool success); 109 void ProcessTaskQueue(); 110 void CloseOpenCursors(); 111 void CommitPhaseTwo(); 112 void Timeout(); 113 114 const int64 id_; 115 const std::set<int64> object_store_ids_; 116 const indexed_db::TransactionMode mode_; 117 118 bool used_; 119 State state_; 120 bool commit_pending_; 121 scoped_refptr<IndexedDBDatabaseCallbacks> callbacks_; 122 scoped_refptr<IndexedDBDatabase> database_; 123 124 class TaskQueue { 125 public: 126 TaskQueue(); 127 ~TaskQueue(); 128 bool empty() const { return queue_.empty(); } 129 void push(Operation task) { queue_.push(task); } 130 Operation pop(); 131 void clear(); 132 133 private: 134 std::queue<Operation> queue_; 135 136 DISALLOW_COPY_AND_ASSIGN(TaskQueue); 137 }; 138 139 class TaskStack { 140 public: 141 TaskStack(); 142 ~TaskStack(); 143 bool empty() const { return stack_.empty(); } 144 void push(Operation task) { stack_.push(task); } 145 Operation pop(); 146 void clear(); 147 148 private: 149 std::stack<Operation> stack_; 150 151 DISALLOW_COPY_AND_ASSIGN(TaskStack); 152 }; 153 154 TaskQueue task_queue_; 155 TaskQueue preemptive_task_queue_; 156 TaskStack abort_task_stack_; 157 158 scoped_ptr<IndexedDBBackingStore::Transaction> transaction_; 159 bool backing_store_transaction_begun_; 160 161 bool should_process_queue_; 162 int pending_preemptive_events_; 163 164 std::set<IndexedDBCursor*> open_cursors_; 165 166 // This timer is started after requests have been processed. If no subsequent 167 // requests are processed before the timer fires, assume the script is 168 // unresponsive and abort to unblock the transaction queue. 169 base::OneShotTimer<IndexedDBTransaction> timeout_timer_; 170 171 Diagnostics diagnostics_; 172 }; 173 174 } // namespace content 175 176 #endif // CONTENT_BROWSER_INDEXED_DB_INDEXED_DB_TRANSACTION_H_ 177