1868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)// Copyright (c) 2013 The Chromium Authors. All rights reserved.
2868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
3868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)// found in the LICENSE file.
4868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
5868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#ifndef CONTENT_BROWSER_INDEXED_DB_INDEXED_DB_TRANSACTION_H_
6868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#define CONTENT_BROWSER_INDEXED_DB_INDEXED_DB_TRANSACTION_H_
7868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
8868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include <queue>
9868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include <set>
10868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include <stack>
11868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
12868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/basictypes.h"
13868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/memory/ref_counted.h"
14868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/memory/scoped_ptr.h"
15d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)#include "base/time/time.h"
16a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "base/timer/timer.h"
17868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "content/browser/indexed_db/indexed_db_backing_store.h"
18868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "content/browser/indexed_db/indexed_db_database.h"
19868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "content/browser/indexed_db/indexed_db_database_error.h"
20868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
21868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)namespace content {
22868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
2346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)class BlobWriteCallbackImpl;
24868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)class IndexedDBCursor;
25eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochclass IndexedDBDatabaseCallbacks;
26868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
27a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)class CONTENT_EXPORT IndexedDBTransaction
28a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    : public NON_EXPORTED_BASE(base::RefCounted<IndexedDBTransaction>) {
29868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) public:
303551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  typedef base::Callback<void(IndexedDBTransaction*)> Operation;
313551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
32a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  IndexedDBTransaction(
33a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      int64 id,
34a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      scoped_refptr<IndexedDBDatabaseCallbacks> callbacks,
35a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      const std::set<int64>& object_store_ids,
36a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      indexed_db::TransactionMode,
37a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      IndexedDBDatabase* db,
38a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      IndexedDBBackingStore::Transaction* backing_store_transaction);
39868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
40868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  virtual void Abort();
41868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  void Commit();
42868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  void Abort(const IndexedDBDatabaseError& error);
43f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
44f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // Called by the transaction coordinator when this transaction is unblocked.
45f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  void Start();
46f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
47868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  indexed_db::TransactionMode mode() const { return mode_; }
48868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  const std::set<int64>& scope() const { return object_store_ids_; }
49f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
503551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  void ScheduleTask(Operation task) {
513551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    ScheduleTask(IndexedDBDatabase::NORMAL_TASK, task);
52eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  }
533551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  void ScheduleTask(IndexedDBDatabase::TaskType, Operation task);
54cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  void ScheduleAbortTask(Operation abort_task);
55868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  void RegisterOpenCursor(IndexedDBCursor* cursor);
56868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  void UnregisterOpenCursor(IndexedDBCursor* cursor);
57868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  void AddPreemptiveEvent() { pending_preemptive_events_++; }
58868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  void DidCompletePreemptiveEvent() {
59868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    pending_preemptive_events_--;
60868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    DCHECK_GE(pending_preemptive_events_, 0);
61868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
62868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  IndexedDBBackingStore::Transaction* BackingStoreTransaction() {
63a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    return transaction_.get();
64868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
65868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  int64 id() const { return id_; }
66868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
67eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  IndexedDBDatabase* database() const { return database_; }
68eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  IndexedDBDatabaseCallbacks* connection() const { return callbacks_; }
69868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
70f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  enum State {
7146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    CREATED,     // Created, but not yet started by coordinator.
7246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    STARTED,     // Started by the coordinator.
7346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    COMMITTING,  // In the process of committing, possibly waiting for blobs
7446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)                 // to be written.
7546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    FINISHED,    // Either aborted or committed.
76d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  };
77d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
78f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  State state() const { return state_; }
79a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  bool IsTimeoutTimerRunning() const { return timeout_timer_.IsRunning(); }
80d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
81f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  struct Diagnostics {
82f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    base::Time creation_time;
83f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    base::Time start_time;
84f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    int tasks_scheduled;
85f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    int tasks_completed;
86f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  };
87f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
88f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  const Diagnostics& diagnostics() const { return diagnostics_; }
89868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
90868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) private:
9146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  friend class BlobWriteCallbackImpl;
9246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
93c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  FRIEND_TEST_ALL_PREFIXES(IndexedDBTransactionTestMode, AbortPreemptive);
94c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  FRIEND_TEST_ALL_PREFIXES(IndexedDBTransactionTest, Timeout);
95a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  FRIEND_TEST_ALL_PREFIXES(IndexedDBTransactionTest,
96a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch                           SchedulePreemptiveTask);
970529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  FRIEND_TEST_ALL_PREFIXES(IndexedDBTransactionTestMode,
980529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch                           ScheduleNormalTask);
99c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
100f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  friend class base::RefCounted<IndexedDBTransaction>;
101f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  virtual ~IndexedDBTransaction();
102868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
103f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  void RunTasksIfStarted();
104868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
105868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  bool IsTaskQueueEmpty() const;
106868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  bool HasPendingTasks() const;
107868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
10846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  void BlobWriteComplete(bool success);
1097dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  void ProcessTaskQueue();
110868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  void CloseOpenCursors();
11146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  void CommitPhaseTwo();
112a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  void Timeout();
113868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
114868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  const int64 id_;
115868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  const std::set<int64> object_store_ids_;
116868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  const indexed_db::TransactionMode mode_;
117868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
118f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  bool used_;
119868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  State state_;
120868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  bool commit_pending_;
121eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_refptr<IndexedDBDatabaseCallbacks> callbacks_;
122868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  scoped_refptr<IndexedDBDatabase> database_;
123868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
124868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  class TaskQueue {
125868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)   public:
126868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    TaskQueue();
127868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    ~TaskQueue();
128868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    bool empty() const { return queue_.empty(); }
1293551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    void push(Operation task) { queue_.push(task); }
1303551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    Operation pop();
131868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    void clear();
132868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
133868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)   private:
1343551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    std::queue<Operation> queue_;
135f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
136f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    DISALLOW_COPY_AND_ASSIGN(TaskQueue);
137868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  };
138868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
139868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  class TaskStack {
140868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)   public:
141868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    TaskStack();
142868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    ~TaskStack();
143868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    bool empty() const { return stack_.empty(); }
1443551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    void push(Operation task) { stack_.push(task); }
1453551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    Operation pop();
146868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    void clear();
147868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
148868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)   private:
1493551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    std::stack<Operation> stack_;
150f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
151f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    DISALLOW_COPY_AND_ASSIGN(TaskStack);
152868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  };
153868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
154868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  TaskQueue task_queue_;
155868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  TaskQueue preemptive_task_queue_;
156868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  TaskStack abort_task_stack_;
157868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
158a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  scoped_ptr<IndexedDBBackingStore::Transaction> transaction_;
159f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  bool backing_store_transaction_begun_;
160868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1617dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  bool should_process_queue_;
162868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  int pending_preemptive_events_;
163868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
164868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  std::set<IndexedDBCursor*> open_cursors_;
165a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
166a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  // This timer is started after requests have been processed. If no subsequent
167a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  // requests are processed before the timer fires, assume the script is
168a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  // unresponsive and abort to unblock the transaction queue.
169a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  base::OneShotTimer<IndexedDBTransaction> timeout_timer_;
170a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
171f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  Diagnostics diagnostics_;
172868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)};
173868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
174868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}  // namespace content
175868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
176868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#endif  // CONTENT_BROWSER_INDEXED_DB_INDEXED_DB_TRANSACTION_H_
177