Home | History | Annotate | Download | only in indexed_db
      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 
     19 namespace content {
     20 
     21 class IndexedDBCursor;
     22 class IndexedDBDatabaseCallbacks;
     23 
     24 class 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