Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(265)

Side by Side Diff: content/browser/indexed_db/indexed_db_transaction.cc

Issue 18023022: Blob support for IDB [Chromium] (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Use ScopedVector and stl_utils for BlobDataHandles. Created 7 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "content/browser/indexed_db/indexed_db_transaction.h" 5 #include "content/browser/indexed_db/indexed_db_transaction.h"
6 6
7 #include "base/bind.h" 7 #include "base/bind.h"
8 #include "base/logging.h" 8 #include "base/logging.h"
9 #include "base/message_loop/message_loop.h" 9 #include "base/message_loop/message_loop.h"
10 #include "base/strings/utf_string_conversions.h" 10 #include "base/strings/utf_string_conversions.h"
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
53 scoped_refptr<IndexedDBDatabaseCallbacks> callbacks, 53 scoped_refptr<IndexedDBDatabaseCallbacks> callbacks,
54 const std::set<int64>& object_store_ids, 54 const std::set<int64>& object_store_ids,
55 indexed_db::TransactionMode mode, 55 indexed_db::TransactionMode mode,
56 IndexedDBDatabase* database) 56 IndexedDBDatabase* database)
57 : id_(id), 57 : id_(id),
58 object_store_ids_(object_store_ids), 58 object_store_ids_(object_store_ids),
59 mode_(mode), 59 mode_(mode),
60 used_(false), 60 used_(false),
61 state_(CREATED), 61 state_(CREATED),
62 commit_pending_(false), 62 commit_pending_(false),
63 blob_write_success_(false),
63 callbacks_(callbacks), 64 callbacks_(callbacks),
64 database_(database), 65 database_(database),
65 transaction_(database->backing_store()), 66 transaction_(database->backing_store()),
66 backing_store_transaction_begun_(false), 67 backing_store_transaction_begun_(false),
67 should_process_queue_(false), 68 should_process_queue_(false),
68 pending_preemptive_events_(0) { 69 pending_preemptive_events_(0) {
69 database_->transaction_coordinator().DidCreateTransaction(this); 70 database_->transaction_coordinator().DidCreateTransaction(this);
70 71
71 diagnostics_.tasks_scheduled = 0; 72 diagnostics_.tasks_scheduled = 0;
72 diagnostics_.tasks_completed = 0; 73 diagnostics_.tasks_completed = 0;
(...skipping 15 matching lines...) Expand all
88 89
89 used_ = true; 90 used_ = true;
90 task_queue_.push(task); 91 task_queue_.push(task);
91 ++diagnostics_.tasks_scheduled; 92 ++diagnostics_.tasks_scheduled;
92 abort_task_stack_.push(abort_task); 93 abort_task_stack_.push(abort_task);
93 RunTasksIfStarted(); 94 RunTasksIfStarted();
94 } 95 }
95 96
96 void IndexedDBTransaction::ScheduleTask(IndexedDBDatabase::TaskType type, 97 void IndexedDBTransaction::ScheduleTask(IndexedDBDatabase::TaskType type,
97 Operation task) { 98 Operation task) {
98 if (state_ == FINISHED) 99 if (IsStatePastRunning())
99 return; 100 return;
100 101
101 used_ = true; 102 used_ = true;
102 if (type == IndexedDBDatabase::NORMAL_TASK) { 103 if (type == IndexedDBDatabase::NORMAL_TASK) {
103 task_queue_.push(task); 104 task_queue_.push(task);
104 ++diagnostics_.tasks_scheduled; 105 ++diagnostics_.tasks_scheduled;
105 } else { 106 } else {
106 preemptive_task_queue_.push(task); 107 preemptive_task_queue_.push(task);
107 } 108 }
108 RunTasksIfStarted(); 109 RunTasksIfStarted();
(...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after
199 state_ = STARTED; 200 state_ = STARTED;
200 database_->TransactionStarted(this); 201 database_->TransactionStarted(this);
201 diagnostics_.start_time = base::Time::Now(); 202 diagnostics_.start_time = base::Time::Now();
202 203
203 if (!used_) 204 if (!used_)
204 return; 205 return;
205 206
206 RunTasksIfStarted(); 207 RunTasksIfStarted();
207 } 208 }
208 209
210 class BlobWriteCallbackImpl : public IndexedDBBackingStore::BlobWriteCallback {
211 public:
212 BlobWriteCallbackImpl(scoped_refptr<IndexedDBTransaction> transaction)
213 : transaction_(transaction) {
214 }
215 virtual ~BlobWriteCallbackImpl() {
216 }
217 virtual void didSucceed() {
218 transaction_->BlobWriteComplete(true);
219 }
220 virtual void didFail() {
221 transaction_->BlobWriteComplete(false);
222 }
223 private:
224 scoped_refptr<IndexedDBTransaction> transaction_;
225 };
226
227 void IndexedDBTransaction::BlobWriteComplete(bool success)
228 {
229 IDB_TRACE("IndexedDBTransaction::BlobWriteComplete");
230 if (state_ == FINISHED) // aborted
231 return;
232 DCHECK_EQ(state_, COMMITTING);
233 if (success)
234 CommitPhaseTwo();
235 else
236 Abort(IndexedDBDatabaseError(blink::WebIDBDatabaseExceptionDataError,
237 "Failed to write blobs."));
238 }
239
209 void IndexedDBTransaction::Commit() { 240 void IndexedDBTransaction::Commit() {
210 IDB_TRACE("IndexedDBTransaction::Commit"); 241 IDB_TRACE("IndexedDBTransaction::Commit");
211 242
212 // In multiprocess ports, front-end may have requested a commit but 243 // In multiprocess ports, front-end may have requested a commit but
213 // an abort has already been initiated asynchronously by the 244 // an abort has already been initiated asynchronously by the
214 // back-end. 245 // back-end.
215 if (state_ == FINISHED) 246 if (IsStatePastRunning())
216 return; 247 return;
217 248
218 DCHECK(!used_ || state_ == STARTED); 249 DCHECK(!used_ || state_ == STARTED);
219 commit_pending_ = true; 250 commit_pending_ = true;
220 251
221 // Front-end has requested a commit, but there may be tasks like 252 // Front-end has requested a commit, but there may be tasks like
222 // create_index which are considered synchronous by the front-end 253 // create_index which are considered synchronous by the front-end
223 // but are processed asynchronously. 254 // but are processed asynchronously.
224 if (HasPendingTasks()) 255 if (HasPendingTasks())
225 return; 256 return;
226 257
258 state_ = COMMITTING;
259
260 if (!used_)
261 CommitPhaseTwo();
262 else {
263 scoped_refptr<IndexedDBBackingStore::BlobWriteCallback> callback(
264 new BlobWriteCallbackImpl(this));
265 // CommitPhaseOne will call the callback synchronously if there are no blobs
266 // to write.
267 if (!transaction_.CommitPhaseOne(callback))
268 Abort(IndexedDBDatabaseError(blink::WebIDBDatabaseExceptionDataError,
269 "Error processing blob journal."));
270 }
271 }
272
273 void IndexedDBTransaction::CommitPhaseTwo() {
274 DCHECK_EQ(state_, COMMITTING);
275 state_ = FINISHED;
276
227 // The last reference to this object may be released while performing the 277 // The last reference to this object may be released while performing the
228 // commit steps below. We therefore take a self reference to keep ourselves 278 // commit steps below. We therefore take a self reference to keep ourselves
229 // alive while executing this method. 279 // alive while executing this method.
230 scoped_refptr<IndexedDBTransaction> protect(this); 280 scoped_refptr<IndexedDBTransaction> protect(this);
231 281
232 // TODO(jsbell): Run abort tasks if commit fails? http://crbug.com/241843 282 // TODO(jsbell): Run abort tasks if commit fails? http://crbug.com/241843
233 abort_task_stack_.clear(); 283 abort_task_stack_.clear();
234 284
235 state_ = FINISHED; 285 state_ = FINISHED;
236 286
237 bool committed = !used_ || transaction_.Commit(); 287 bool committed = !used_ || transaction_.CommitPhaseTwo();
238 288
239 // Backing store resources (held via cursors) must be released 289 // Backing store resources (held via cursors) must be released
240 // before script callbacks are fired, as the script callbacks may 290 // before script callbacks are fired, as the script callbacks may
241 // release references and allow the backing store itself to be 291 // release references and allow the backing store itself to be
242 // released, and order is critical. 292 // released, and order is critical.
243 CloseOpenCursors(); 293 CloseOpenCursors();
244 transaction_.Reset(); 294 transaction_.Reset();
245 295
246 // Transactions must also be marked as completed before the 296 // Transactions must also be marked as completed before the
247 // front-end is notified, as the transaction completion unblocks 297 // front-end is notified, as the transaction completion unblocks
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
279 backing_store_transaction_begun_ = true; 329 backing_store_transaction_begun_ = true;
280 } 330 }
281 331
282 // The last reference to this object may be released while performing the 332 // The last reference to this object may be released while performing the
283 // tasks. Take take a self reference to keep this object alive so that 333 // tasks. Take take a self reference to keep this object alive so that
284 // the loop termination conditions can be checked. 334 // the loop termination conditions can be checked.
285 scoped_refptr<IndexedDBTransaction> protect(this); 335 scoped_refptr<IndexedDBTransaction> protect(this);
286 336
287 TaskQueue* task_queue = 337 TaskQueue* task_queue =
288 pending_preemptive_events_ ? &preemptive_task_queue_ : &task_queue_; 338 pending_preemptive_events_ ? &preemptive_task_queue_ : &task_queue_;
289 while (!task_queue->empty() && state_ != FINISHED) { 339 while (!task_queue->empty() && !IsStatePastRunning()) {
290 DCHECK_EQ(STARTED, state_); 340 DCHECK_EQ(state_, STARTED);
291 Operation task(task_queue->pop()); 341 Operation task(task_queue->pop());
292 task.Run(this); 342 task.Run(this);
293 if (!pending_preemptive_events_) { 343 if (!pending_preemptive_events_) {
294 DCHECK(diagnostics_.tasks_completed < diagnostics_.tasks_scheduled); 344 DCHECK(diagnostics_.tasks_completed < diagnostics_.tasks_scheduled);
295 ++diagnostics_.tasks_completed; 345 ++diagnostics_.tasks_completed;
296 } 346 }
297 347
298 // Event itself may change which queue should be processed next. 348 // Event itself may change which queue should be processed next.
299 task_queue = 349 task_queue =
300 pending_preemptive_events_ ? &preemptive_task_queue_ : &task_queue_; 350 pending_preemptive_events_ ? &preemptive_task_queue_ : &task_queue_;
301 } 351 }
302 352
303 // If there are no pending tasks, we haven't already committed/aborted, 353 // If there are no pending tasks, we haven't already committed/aborted,
304 // and the front-end requested a commit, it is now safe to do so. 354 // and the front-end requested a commit, it is now safe to do so.
305 if (!HasPendingTasks() && state_ != FINISHED && commit_pending_) 355 if (!HasPendingTasks() && !IsStatePastRunning() && commit_pending_)
306 Commit(); 356 Commit();
307 } 357 }
308 358
309 void IndexedDBTransaction::CloseOpenCursors() { 359 void IndexedDBTransaction::CloseOpenCursors() {
310 for (std::set<IndexedDBCursor*>::iterator i = open_cursors_.begin(); 360 for (std::set<IndexedDBCursor*>::iterator i = open_cursors_.begin();
311 i != open_cursors_.end(); 361 i != open_cursors_.end();
312 ++i) 362 ++i)
313 (*i)->Close(); 363 (*i)->Close();
314 open_cursors_.clear(); 364 open_cursors_.clear();
315 } 365 }
316 366
317 } // namespace content 367 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698