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

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: DeleteRange now seems to work. Created 6 years, 7 months 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 69 matching lines...) Expand 10 before | Expand all | Expand 10 after
80 // It shouldn't be possible for this object to get deleted until it's either 80 // It shouldn't be possible for this object to get deleted until it's either
81 // complete or aborted. 81 // complete or aborted.
82 DCHECK_EQ(state_, FINISHED); 82 DCHECK_EQ(state_, FINISHED);
83 DCHECK(preemptive_task_queue_.empty()); 83 DCHECK(preemptive_task_queue_.empty());
84 DCHECK_EQ(pending_preemptive_events_, 0); 84 DCHECK_EQ(pending_preemptive_events_, 0);
85 DCHECK(task_queue_.empty()); 85 DCHECK(task_queue_.empty());
86 DCHECK(abort_task_stack_.empty()); 86 DCHECK(abort_task_stack_.empty());
87 } 87 }
88 88
89 void IndexedDBTransaction::ScheduleTask(Operation task, Operation abort_task) { 89 void IndexedDBTransaction::ScheduleTask(Operation task, Operation abort_task) {
90 if (state_ == FINISHED) 90 if (IsStatePastStarted())
91 return; 91 return;
92 92
93 timeout_timer_.Stop(); 93 timeout_timer_.Stop();
94 used_ = true; 94 used_ = true;
95 task_queue_.push(task); 95 task_queue_.push(task);
96 ++diagnostics_.tasks_scheduled; 96 ++diagnostics_.tasks_scheduled;
97 abort_task_stack_.push(abort_task); 97 abort_task_stack_.push(abort_task);
98 RunTasksIfStarted(); 98 RunTasksIfStarted();
99 } 99 }
100 100
101 void IndexedDBTransaction::ScheduleTask(IndexedDBDatabase::TaskType type, 101 void IndexedDBTransaction::ScheduleTask(IndexedDBDatabase::TaskType type,
102 Operation task) { 102 Operation task) {
103 if (state_ == FINISHED) 103 if (IsStatePastStarted())
104 return; 104 return;
105 105
106 timeout_timer_.Stop(); 106 timeout_timer_.Stop();
107 used_ = true; 107 used_ = true;
108 if (type == IndexedDBDatabase::NORMAL_TASK) { 108 if (type == IndexedDBDatabase::NORMAL_TASK) {
109 task_queue_.push(task); 109 task_queue_.push(task);
110 ++diagnostics_.tasks_scheduled; 110 ++diagnostics_.tasks_scheduled;
111 } else { 111 } else {
112 preemptive_task_queue_.push(task); 112 preemptive_task_queue_.push(task);
113 } 113 }
(...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after
205 DCHECK_EQ(CREATED, state_); 205 DCHECK_EQ(CREATED, state_);
206 state_ = STARTED; 206 state_ = STARTED;
207 diagnostics_.start_time = base::Time::Now(); 207 diagnostics_.start_time = base::Time::Now();
208 208
209 if (!used_) 209 if (!used_)
210 return; 210 return;
211 211
212 RunTasksIfStarted(); 212 RunTasksIfStarted();
213 } 213 }
214 214
215 class BlobWriteCallbackImpl : public IndexedDBBackingStore::BlobWriteCallback {
216 public:
217 BlobWriteCallbackImpl(scoped_refptr<IndexedDBTransaction> transaction)
218 : transaction_(transaction) {}
219 virtual ~BlobWriteCallbackImpl() {}
220 virtual void Run(bool succeeded) {
221 transaction_->BlobWriteComplete(succeeded);
222 }
223
224 private:
225 scoped_refptr<IndexedDBTransaction> transaction_;
226 };
227
228 void IndexedDBTransaction::BlobWriteComplete(bool success) {
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
215 void IndexedDBTransaction::Commit() { 240 void IndexedDBTransaction::Commit() {
216 IDB_TRACE("IndexedDBTransaction::Commit"); 241 IDB_TRACE("IndexedDBTransaction::Commit");
217 242
218 // In multiprocess ports, front-end may have requested a commit but 243 // In multiprocess ports, front-end may have requested a commit but
219 // an abort has already been initiated asynchronously by the 244 // an abort has already been initiated asynchronously by the
220 // back-end. 245 // back-end.
221 if (state_ == FINISHED) 246 if (IsStatePastStarted()) {
247 DCHECK(state_ == FINISHED);
222 return; 248 return;
249 }
223 250
224 DCHECK(!used_ || state_ == STARTED); 251 DCHECK(!used_ || state_ == STARTED);
225 commit_pending_ = true; 252 commit_pending_ = true;
226 253
227 // Front-end has requested a commit, but there may be tasks like 254 // Front-end has requested a commit, but there may be tasks like
228 // create_index which are considered synchronous by the front-end 255 // create_index which are considered synchronous by the front-end
229 // but are processed asynchronously. 256 // but are processed asynchronously.
230 if (HasPendingTasks()) 257 if (HasPendingTasks())
231 return; 258 return;
232 259
260 state_ = COMMITTING;
261
262 if (!used_)
263 CommitPhaseTwo();
264 else {
265 scoped_refptr<IndexedDBBackingStore::BlobWriteCallback> callback(
266 new BlobWriteCallbackImpl(this));
267 // CommitPhaseOne will call the callback synchronously if there are no blobs
268 // to write.
269 if (!transaction_->CommitPhaseOne(callback).ok())
270 Abort(IndexedDBDatabaseError(blink::WebIDBDatabaseExceptionDataError,
271 "Error processing blob journal."));
272 }
273 }
274
275 void IndexedDBTransaction::CommitPhaseTwo() {
jsbell 2014/05/20 22:02:19 Is it possible for an Abort() to slip in between C
ericu 2014/05/21 18:14:47 Ah, yes it is. For CommitPhaseTwo to be called af
276 DCHECK_EQ(state_, COMMITTING);
277
233 // The last reference to this object may be released while performing the 278 // The last reference to this object may be released while performing the
234 // commit steps below. We therefore take a self reference to keep ourselves 279 // commit steps below. We therefore take a self reference to keep ourselves
235 // alive while executing this method. 280 // alive while executing this method.
236 scoped_refptr<IndexedDBTransaction> protect(this); 281 scoped_refptr<IndexedDBTransaction> protect(this);
237 282
238 timeout_timer_.Stop(); 283 timeout_timer_.Stop();
239 284
240 state_ = FINISHED; 285 state_ = FINISHED;
241 286
242 bool committed = !used_ || transaction_->Commit().ok(); 287 bool committed = !used_ || transaction_->CommitPhaseTwo().ok();
243 288
244 // Backing store resources (held via cursors) must be released 289 // Backing store resources (held via cursors) must be released
245 // before script callbacks are fired, as the script callbacks may 290 // before script callbacks are fired, as the script callbacks may
246 // release references and allow the backing store itself to be 291 // release references and allow the backing store itself to be
247 // released, and order is critical. 292 // released, and order is critical.
248 CloseOpenCursors(); 293 CloseOpenCursors();
249 transaction_->Reset(); 294 transaction_->Reset();
250 295
251 // Transactions must also be marked as completed before the 296 // Transactions must also be marked as completed before the
252 // front-end is notified, as the transaction completion unblocks 297 // front-end is notified, as the transaction completion unblocks
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
287 backing_store_transaction_begun_ = true; 332 backing_store_transaction_begun_ = true;
288 } 333 }
289 334
290 // The last reference to this object may be released while performing the 335 // The last reference to this object may be released while performing the
291 // tasks. Take take a self reference to keep this object alive so that 336 // tasks. Take take a self reference to keep this object alive so that
292 // the loop termination conditions can be checked. 337 // the loop termination conditions can be checked.
293 scoped_refptr<IndexedDBTransaction> protect(this); 338 scoped_refptr<IndexedDBTransaction> protect(this);
294 339
295 TaskQueue* task_queue = 340 TaskQueue* task_queue =
296 pending_preemptive_events_ ? &preemptive_task_queue_ : &task_queue_; 341 pending_preemptive_events_ ? &preemptive_task_queue_ : &task_queue_;
297 while (!task_queue->empty() && state_ != FINISHED) { 342 while (!task_queue->empty() && !IsStatePastStarted()) {
298 DCHECK_EQ(STARTED, state_); 343 DCHECK_EQ(state_, STARTED);
299 Operation task(task_queue->pop()); 344 Operation task(task_queue->pop());
300 task.Run(this); 345 task.Run(this);
301 if (!pending_preemptive_events_) { 346 if (!pending_preemptive_events_) {
302 DCHECK(diagnostics_.tasks_completed < diagnostics_.tasks_scheduled); 347 DCHECK(diagnostics_.tasks_completed < diagnostics_.tasks_scheduled);
303 ++diagnostics_.tasks_completed; 348 ++diagnostics_.tasks_completed;
304 } 349 }
305 350
306 // Event itself may change which queue should be processed next. 351 // Event itself may change which queue should be processed next.
307 task_queue = 352 task_queue =
308 pending_preemptive_events_ ? &preemptive_task_queue_ : &task_queue_; 353 pending_preemptive_events_ ? &preemptive_task_queue_ : &task_queue_;
309 } 354 }
310 355
311 // If there are no pending tasks, we haven't already committed/aborted, 356 // If there are no pending tasks, we haven't already committed/aborted,
312 // and the front-end requested a commit, it is now safe to do so. 357 // and the front-end requested a commit, it is now safe to do so.
313 if (!HasPendingTasks() && state_ != FINISHED && commit_pending_) { 358 if (!HasPendingTasks() && !IsStatePastStarted() && commit_pending_) {
314 Commit(); 359 Commit();
315 return; 360 return;
316 } 361 }
317 362
318 // The transaction may have been aborted while processing tasks. 363 // The transaction may have been aborted while processing tasks.
319 if (state_ == FINISHED) 364 if (state_ == FINISHED)
320 return; 365 return;
321 366
322 // Otherwise, start a timer in case the front-end gets wedged and 367 // Otherwise, start a timer in case the front-end gets wedged and
323 // never requests further activity. Read-only transactions don't 368 // never requests further activity. Read-only transactions don't
(...skipping 14 matching lines...) Expand all
338 383
339 void IndexedDBTransaction::CloseOpenCursors() { 384 void IndexedDBTransaction::CloseOpenCursors() {
340 for (std::set<IndexedDBCursor*>::iterator i = open_cursors_.begin(); 385 for (std::set<IndexedDBCursor*>::iterator i = open_cursors_.begin();
341 i != open_cursors_.end(); 386 i != open_cursors_.end();
342 ++i) 387 ++i)
343 (*i)->Close(); 388 (*i)->Close();
344 open_cursors_.clear(); 389 open_cursors_.clear();
345 } 390 }
346 391
347 } // namespace content 392 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698