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