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