summaryrefslogtreecommitdiff
path: root/chromium/content/browser/indexed_db/indexed_db_transaction.h
blob: 24f44490537ffff7d208b1b95d7bd01fbd7f7dc9 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
// Copyright (c) 2013 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef CONTENT_BROWSER_INDEXED_DB_INDEXED_DB_TRANSACTION_H_
#define CONTENT_BROWSER_INDEXED_DB_INDEXED_DB_TRANSACTION_H_

#include <queue>
#include <set>
#include <stack>

#include "base/basictypes.h"
#include "base/memory/ref_counted.h"
#include "base/memory/scoped_ptr.h"
#include "base/time/time.h"
#include "content/browser/indexed_db/indexed_db_backing_store.h"
#include "content/browser/indexed_db/indexed_db_database.h"
#include "content/browser/indexed_db/indexed_db_database_error.h"

namespace content {

class IndexedDBCursor;
class IndexedDBDatabaseCallbacks;

class IndexedDBTransaction : public base::RefCounted<IndexedDBTransaction> {
 public:
  typedef base::Callback<void(IndexedDBTransaction*)> Operation;

  IndexedDBTransaction(int64 id,
                       scoped_refptr<IndexedDBDatabaseCallbacks> callbacks,
                       const std::set<int64>& object_store_ids,
                       indexed_db::TransactionMode,
                       IndexedDBDatabase* db);

  virtual void Abort();
  void Commit();

  void Abort(const IndexedDBDatabaseError& error);
  void Run();
  indexed_db::TransactionMode mode() const { return mode_; }
  const std::set<int64>& scope() const { return object_store_ids_; }
  void ScheduleTask(Operation task) {
    ScheduleTask(IndexedDBDatabase::NORMAL_TASK, task);
  }

  void ScheduleTask(Operation task, Operation abort_task);
  void ScheduleTask(IndexedDBDatabase::TaskType, Operation task);
  void RegisterOpenCursor(IndexedDBCursor* cursor);
  void UnregisterOpenCursor(IndexedDBCursor* cursor);
  void AddPreemptiveEvent() { pending_preemptive_events_++; }
  void DidCompletePreemptiveEvent() {
    pending_preemptive_events_--;
    DCHECK_GE(pending_preemptive_events_, 0);
  }
  IndexedDBBackingStore::Transaction* BackingStoreTransaction() {
    return &transaction_;
  }
  int64 id() const { return id_; }

  IndexedDBDatabase* database() const { return database_; }
  IndexedDBDatabaseCallbacks* connection() const { return callbacks_; }
  bool IsRunning() const { return state_ == RUNNING; }

  // The following types/accessors are for diagnostics only.
  enum QueueStatus {
    CREATED,
    BLOCKED,
    UNBLOCKED,
  };

  QueueStatus queue_status() const { return queue_status_; }
  void set_queue_status(QueueStatus status) { queue_status_ = status; }
  base::Time creation_time() const { return creation_time_; }
  base::Time start_time() const { return start_time_; }
  int tasks_scheduled() const { return tasks_scheduled_; }
  int tasks_completed() const { return tasks_completed_; }

 protected:
  virtual ~IndexedDBTransaction();
  friend class base::RefCounted<IndexedDBTransaction>;

 private:
  enum State {
    UNUSED,         // Created, but no tasks yet.
    START_PENDING,  // Enqueued tasks, but backing store transaction not yet
                    // started.
    RUNNING,        // Backing store transaction started but not yet finished.
    FINISHED,       // Either aborted or committed.
  };

  void EnsureTasksRunning();
  void Start();

  bool IsTaskQueueEmpty() const;
  bool HasPendingTasks() const;

  void ProcessTaskQueue();
  void CloseOpenCursors();

  const int64 id_;
  const std::set<int64> object_store_ids_;
  const indexed_db::TransactionMode mode_;

  State state_;
  bool commit_pending_;
  scoped_refptr<IndexedDBDatabaseCallbacks> callbacks_;
  scoped_refptr<IndexedDBDatabase> database_;

  class TaskQueue {
   public:
    TaskQueue();
    ~TaskQueue();
    bool empty() const { return queue_.empty(); }
    void push(Operation task) { queue_.push(task); }
    Operation pop();
    void clear();

   private:
    std::queue<Operation> queue_;
  };

  class TaskStack {
   public:
    TaskStack();
    ~TaskStack();
    bool empty() const { return stack_.empty(); }
    void push(Operation task) { stack_.push(task); }
    Operation pop();
    void clear();

   private:
    std::stack<Operation> stack_;
  };

  TaskQueue task_queue_;
  TaskQueue preemptive_task_queue_;
  TaskStack abort_task_stack_;

  IndexedDBBackingStore::Transaction transaction_;

  bool should_process_queue_;
  int pending_preemptive_events_;

  std::set<IndexedDBCursor*> open_cursors_;

  // The following members are for diagnostics only.
  QueueStatus queue_status_;
  base::Time creation_time_;
  base::Time start_time_;
  int tasks_scheduled_;
  int tasks_completed_;
};

}  // namespace content

#endif  // CONTENT_BROWSER_INDEXED_DB_INDEXED_DB_TRANSACTION_H_