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 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177
|
// 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 "base/timer/timer.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"
#include "third_party/WebKit/public/platform/WebIDBTypes.h"
namespace content {
class BlobWriteCallbackImpl;
class IndexedDBCursor;
class IndexedDBDatabaseCallbacks;
class CONTENT_EXPORT IndexedDBTransaction
: public NON_EXPORTED_BASE(base::RefCounted<IndexedDBTransaction>) {
public:
typedef base::Callback<void(IndexedDBTransaction*)> Operation;
enum State {
CREATED, // Created, but not yet started by coordinator.
STARTED, // Started by the coordinator.
COMMITTING, // In the process of committing, possibly waiting for blobs
// to be written.
FINISHED, // Either aborted or committed.
};
IndexedDBTransaction(
int64 id,
scoped_refptr<IndexedDBDatabaseCallbacks> callbacks,
const std::set<int64>& object_store_ids,
blink::WebIDBTransactionMode,
IndexedDBDatabase* db,
IndexedDBBackingStore::Transaction* backing_store_transaction);
virtual void Abort();
leveldb::Status Commit();
void Abort(const IndexedDBDatabaseError& error);
// Called by the transaction coordinator when this transaction is unblocked.
void Start();
blink::WebIDBTransactionMode mode() const { return mode_; }
const std::set<int64>& scope() const { return object_store_ids_; }
void ScheduleTask(Operation task) {
ScheduleTask(blink::WebIDBTaskTypeNormal, task);
}
void ScheduleTask(blink::WebIDBTaskType, Operation task);
void ScheduleAbortTask(Operation abort_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_.get();
}
int64 id() const { return id_; }
IndexedDBDatabase* database() const { return database_.get(); }
IndexedDBDatabaseCallbacks* connection() const { return callbacks_.get(); }
State state() const { return state_; }
bool IsTimeoutTimerRunning() const { return timeout_timer_.IsRunning(); }
struct Diagnostics {
base::Time creation_time;
base::Time start_time;
int tasks_scheduled;
int tasks_completed;
};
const Diagnostics& diagnostics() const { return diagnostics_; }
private:
friend class BlobWriteCallbackImpl;
FRIEND_TEST_ALL_PREFIXES(IndexedDBTransactionTestMode, AbortPreemptive);
FRIEND_TEST_ALL_PREFIXES(IndexedDBTransactionTest, Timeout);
FRIEND_TEST_ALL_PREFIXES(IndexedDBTransactionTest,
SchedulePreemptiveTask);
FRIEND_TEST_ALL_PREFIXES(IndexedDBTransactionTestMode,
ScheduleNormalTask);
friend class base::RefCounted<IndexedDBTransaction>;
virtual ~IndexedDBTransaction();
void RunTasksIfStarted();
bool IsTaskQueueEmpty() const;
bool HasPendingTasks() const;
void BlobWriteComplete(bool success);
void ProcessTaskQueue();
void CloseOpenCursors();
leveldb::Status CommitPhaseTwo();
void Timeout();
const int64 id_;
const std::set<int64> object_store_ids_;
const blink::WebIDBTransactionMode mode_;
bool used_;
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_;
DISALLOW_COPY_AND_ASSIGN(TaskQueue);
};
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_;
DISALLOW_COPY_AND_ASSIGN(TaskStack);
};
TaskQueue task_queue_;
TaskQueue preemptive_task_queue_;
TaskStack abort_task_stack_;
scoped_ptr<IndexedDBBackingStore::Transaction> transaction_;
bool backing_store_transaction_begun_;
bool should_process_queue_;
int pending_preemptive_events_;
std::set<IndexedDBCursor*> open_cursors_;
// This timer is started after requests have been processed. If no subsequent
// requests are processed before the timer fires, assume the script is
// unresponsive and abort to unblock the transaction queue.
base::OneShotTimer<IndexedDBTransaction> timeout_timer_;
Diagnostics diagnostics_;
};
} // namespace content
#endif // CONTENT_BROWSER_INDEXED_DB_INDEXED_DB_TRANSACTION_H_
|