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 "content/browser/indexed_db/indexed_db_backing_store.h" 16#include "content/browser/indexed_db/indexed_db_database.h" 17#include "content/browser/indexed_db/indexed_db_database_error.h" 18 19namespace content { 20 21class IndexedDBCursor; 22class IndexedDBDatabaseCallbacks; 23 24class IndexedDBTransaction : public base::RefCounted<IndexedDBTransaction> { 25 public: 26 IndexedDBTransaction(int64 id, 27 scoped_refptr<IndexedDBDatabaseCallbacks> callbacks, 28 const std::set<int64>& object_store_ids, 29 indexed_db::TransactionMode, 30 IndexedDBDatabase* db); 31 32 virtual void Abort(); 33 void Commit(); 34 35 class Operation { 36 public: 37 Operation() {} 38 virtual ~Operation() {} 39 virtual void Perform(IndexedDBTransaction* transaction) = 0; 40 }; 41 42 void Abort(const IndexedDBDatabaseError& error); 43 void Run(); 44 indexed_db::TransactionMode mode() const { return mode_; } 45 const std::set<int64>& scope() const { return object_store_ids_; } 46 void ScheduleTask(Operation* task) { 47 ScheduleTask(IndexedDBDatabase::NORMAL_TASK, task, NULL); 48 } 49 void ScheduleTask(Operation* task, Operation* abort_task) { 50 ScheduleTask(IndexedDBDatabase::NORMAL_TASK, task, abort_task); 51 } 52 void ScheduleTask(IndexedDBDatabase::TaskType task_type, Operation* task) { 53 ScheduleTask(task_type, task, NULL); 54 } 55 void ScheduleTask(IndexedDBDatabase::TaskType task_type, 56 Operation* task, 57 Operation* abort_task); 58 void RegisterOpenCursor(IndexedDBCursor* cursor); 59 void UnregisterOpenCursor(IndexedDBCursor* cursor); 60 void AddPreemptiveEvent() { pending_preemptive_events_++; } 61 void DidCompletePreemptiveEvent() { 62 pending_preemptive_events_--; 63 DCHECK_GE(pending_preemptive_events_, 0); 64 } 65 IndexedDBBackingStore::Transaction* BackingStoreTransaction() { 66 return &transaction_; 67 } 68 int64 id() const { return id_; } 69 70 IndexedDBDatabase* database() const { return database_; } 71 IndexedDBDatabaseCallbacks* connection() const { return callbacks_; } 72 bool IsRunning() const { return state_ == RUNNING; } 73 74 protected: 75 virtual ~IndexedDBTransaction(); 76 friend class base::RefCounted<IndexedDBTransaction>; 77 78 private: 79 enum State { 80 UNUSED, // Created, but no tasks yet. 81 START_PENDING, // Enqueued tasks, but backing store transaction not yet 82 // started. 83 RUNNING, // Backing store transaction started but not yet finished. 84 FINISHED, // Either aborted or committed. 85 }; 86 87 void Start(); 88 89 bool IsTaskQueueEmpty() const; 90 bool HasPendingTasks() const; 91 92 void ProcessTaskQueue(); 93 void CloseOpenCursors(); 94 95 const int64 id_; 96 const std::set<int64> object_store_ids_; 97 const indexed_db::TransactionMode mode_; 98 99 State state_; 100 bool commit_pending_; 101 scoped_refptr<IndexedDBDatabaseCallbacks> callbacks_; 102 scoped_refptr<IndexedDBDatabase> database_; 103 104 class TaskQueue { 105 public: 106 TaskQueue(); 107 ~TaskQueue(); 108 bool empty() const { return queue_.empty(); } 109 void push(Operation* task) { queue_.push(task); } 110 scoped_ptr<Operation> pop(); 111 void clear(); 112 113 private: 114 std::queue<Operation*> queue_; 115 }; 116 117 class TaskStack { 118 public: 119 TaskStack(); 120 ~TaskStack(); 121 bool empty() const { return stack_.empty(); } 122 void push(Operation* task) { stack_.push(task); } 123 scoped_ptr<Operation> pop(); 124 void clear(); 125 126 private: 127 std::stack<Operation*> stack_; 128 }; 129 130 TaskQueue task_queue_; 131 TaskQueue preemptive_task_queue_; 132 TaskStack abort_task_stack_; 133 134 IndexedDBBackingStore::Transaction transaction_; 135 136 bool should_process_queue_; 137 int pending_preemptive_events_; 138 139 std::set<IndexedDBCursor*> open_cursors_; 140}; 141 142} // namespace content 143 144#endif // CONTENT_BROWSER_INDEXED_DB_INDEXED_DB_TRANSACTION_H_ 145