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 "base/time/time.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 
     21 namespace content {
     22 
     23 class IndexedDBCursor;
     24 class IndexedDBDatabaseCallbacks;
     25 
     26 class CONTENT_EXPORT IndexedDBTransaction
     27     : public NON_EXPORTED_BASE(base::RefCounted<IndexedDBTransaction>) {
     28  public:
     29   typedef base::Callback<void(IndexedDBTransaction*)> Operation;
     30 
     31   IndexedDBTransaction(
     32       int64 id,
     33       scoped_refptr<IndexedDBDatabaseCallbacks> callbacks,
     34       const std::set<int64>& object_store_ids,
     35       indexed_db::TransactionMode,
     36       IndexedDBDatabase* db,
     37       IndexedDBBackingStore::Transaction* backing_store_transaction);
     38 
     39   virtual void Abort();
     40   void Commit();
     41   void Abort(const IndexedDBDatabaseError& error);
     42 
     43   // Called by the transaction coordinator when this transaction is unblocked.
     44   void Start();
     45 
     46   indexed_db::TransactionMode mode() const { return mode_; }
     47   const std::set<int64>& scope() const { return object_store_ids_; }
     48 
     49   void ScheduleTask(Operation task) {
     50     ScheduleTask(IndexedDBDatabase::NORMAL_TASK, task);
     51   }
     52   void ScheduleTask(Operation task, Operation abort_task);
     53   void ScheduleTask(IndexedDBDatabase::TaskType, Operation task);
     54   void RegisterOpenCursor(IndexedDBCursor* cursor);
     55   void UnregisterOpenCursor(IndexedDBCursor* cursor);
     56   void AddPreemptiveEvent() { pending_preemptive_events_++; }
     57   void DidCompletePreemptiveEvent() {
     58     pending_preemptive_events_--;
     59     DCHECK_GE(pending_preemptive_events_, 0);
     60   }
     61   IndexedDBBackingStore::Transaction* BackingStoreTransaction() {
     62     return transaction_.get();
     63   }
     64   int64 id() const { return id_; }
     65 
     66   IndexedDBDatabase* database() const { return database_; }
     67   IndexedDBDatabaseCallbacks* connection() const { return callbacks_; }
     68 
     69   enum State {
     70     CREATED,   // Created, but not yet started by coordinator.
     71     STARTED,   // Started by the coordinator.
     72     FINISHED,  // Either aborted or committed.
     73   };
     74 
     75   State state() const { return state_; }
     76   bool IsTimeoutTimerRunning() const { return timeout_timer_.IsRunning(); }
     77 
     78   struct Diagnostics {
     79     base::Time creation_time;
     80     base::Time start_time;
     81     int tasks_scheduled;
     82     int tasks_completed;
     83   };
     84 
     85   const Diagnostics& diagnostics() const { return diagnostics_; }
     86 
     87  private:
     88   friend class base::RefCounted<IndexedDBTransaction>;
     89   virtual ~IndexedDBTransaction();
     90 
     91   void RunTasksIfStarted();
     92 
     93   bool IsTaskQueueEmpty() const;
     94   bool HasPendingTasks() const;
     95 
     96   void ProcessTaskQueue();
     97   void CloseOpenCursors();
     98   void Timeout();
     99 
    100   const int64 id_;
    101   const std::set<int64> object_store_ids_;
    102   const indexed_db::TransactionMode mode_;
    103 
    104   bool used_;
    105   State state_;
    106   bool commit_pending_;
    107   scoped_refptr<IndexedDBDatabaseCallbacks> callbacks_;
    108   scoped_refptr<IndexedDBDatabase> database_;
    109 
    110   class TaskQueue {
    111    public:
    112     TaskQueue();
    113     ~TaskQueue();
    114     bool empty() const { return queue_.empty(); }
    115     void push(Operation task) { queue_.push(task); }
    116     Operation pop();
    117     void clear();
    118 
    119    private:
    120     std::queue<Operation> queue_;
    121   };
    122 
    123   class TaskStack {
    124    public:
    125     TaskStack();
    126     ~TaskStack();
    127     bool empty() const { return stack_.empty(); }
    128     void push(Operation task) { stack_.push(task); }
    129     Operation pop();
    130     void clear();
    131 
    132    private:
    133     std::stack<Operation> stack_;
    134   };
    135 
    136   TaskQueue task_queue_;
    137   TaskQueue preemptive_task_queue_;
    138   TaskStack abort_task_stack_;
    139 
    140   scoped_ptr<IndexedDBBackingStore::Transaction> transaction_;
    141   bool backing_store_transaction_begun_;
    142 
    143   bool should_process_queue_;
    144   int pending_preemptive_events_;
    145 
    146   std::set<IndexedDBCursor*> open_cursors_;
    147 
    148   // This timer is started after requests have been processed. If no subsequent
    149   // requests are processed before the timer fires, assume the script is
    150   // unresponsive and abort to unblock the transaction queue.
    151   base::OneShotTimer<IndexedDBTransaction> timeout_timer_;
    152 
    153   Diagnostics diagnostics_;
    154 };
    155 
    156 }  // namespace content
    157 
    158 #endif  // CONTENT_BROWSER_INDEXED_DB_INDEXED_DB_TRANSACTION_H_
    159