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