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