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

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: Handle the rest of Josh's feedback. 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 virtual ~BlobWriteCallbackImpl() {}
215 virtual void didSucceed() { transaction_->BlobWriteComplete(true); }
jsbell 2013/12/20 00:44:20 Nit: Chromium naming style
ericu 2014/02/20 00:50:29 Done.
216 virtual void didFail() { transaction_->BlobWriteComplete(false); }
217
218 private:
219 scoped_refptr<IndexedDBTransaction> transaction_;
220 };
221
222 void IndexedDBTransaction::BlobWriteComplete(bool success) {
223 IDB_TRACE("IndexedDBTransaction::BlobWriteComplete");
224 if (state_ == FINISHED) // aborted
225 return;
226 DCHECK_EQ(state_, COMMITTING);
227 if (success)
228 CommitPhaseTwo();
229 else
230 Abort(IndexedDBDatabaseError(blink::WebIDBDatabaseExceptionDataError,
231 "Failed to write blobs."));
232 }
233
209 void IndexedDBTransaction::Commit() { 234 void IndexedDBTransaction::Commit() {
210 IDB_TRACE("IndexedDBTransaction::Commit"); 235 IDB_TRACE("IndexedDBTransaction::Commit");
211 236
212 // In multiprocess ports, front-end may have requested a commit but 237 // In multiprocess ports, front-end may have requested a commit but
213 // an abort has already been initiated asynchronously by the 238 // an abort has already been initiated asynchronously by the
214 // back-end. 239 // back-end.
215 if (state_ == FINISHED) 240 if (IsStatePastRunning())
jsbell 2013/12/20 00:44:20 Can state_ ever be COMMITTING here? The DCHECK(!us
ericu 2014/02/20 00:50:29 You're right that it shouldn't ever happen. Howev
216 return; 241 return;
217 242
218 DCHECK(!used_ || state_ == STARTED); 243 DCHECK(!used_ || state_ == STARTED);
219 commit_pending_ = true; 244 commit_pending_ = true;
220 245
221 // Front-end has requested a commit, but there may be tasks like 246 // Front-end has requested a commit, but there may be tasks like
222 // create_index which are considered synchronous by the front-end 247 // create_index which are considered synchronous by the front-end
223 // but are processed asynchronously. 248 // but are processed asynchronously.
224 if (HasPendingTasks()) 249 if (HasPendingTasks())
225 return; 250 return;
226 251
252 state_ = COMMITTING;
253
254 if (!used_)
255 CommitPhaseTwo();
256 else {
257 scoped_refptr<IndexedDBBackingStore::BlobWriteCallback> callback(
258 new BlobWriteCallbackImpl(this));
259 // CommitPhaseOne will call the callback synchronously if there are no blobs
260 // to write.
261 if (!transaction_.CommitPhaseOne(callback))
262 Abort(IndexedDBDatabaseError(blink::WebIDBDatabaseExceptionDataError,
263 "Error processing blob journal."));
264 }
265 }
266
267 void IndexedDBTransaction::CommitPhaseTwo() {
268 DCHECK_EQ(state_, COMMITTING);
269
227 // The last reference to this object may be released while performing the 270 // 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 271 // commit steps below. We therefore take a self reference to keep ourselves
229 // alive while executing this method. 272 // alive while executing this method.
230 scoped_refptr<IndexedDBTransaction> protect(this); 273 scoped_refptr<IndexedDBTransaction> protect(this);
231 274
232 // TODO(jsbell): Run abort tasks if commit fails? http://crbug.com/241843 275 // TODO(jsbell): Run abort tasks if commit fails? http://crbug.com/241843
jsbell 2013/12/20 00:44:20 This should be resolved; needs a rebase?
ericu 2014/02/20 00:50:29 Done.
233 abort_task_stack_.clear(); 276 abort_task_stack_.clear();
234 277
235 state_ = FINISHED; 278 state_ = FINISHED;
236 279
237 bool committed = !used_ || transaction_.Commit(); 280 bool committed = !used_ || transaction_.CommitPhaseTwo();
238 281
239 // Backing store resources (held via cursors) must be released 282 // Backing store resources (held via cursors) must be released
240 // before script callbacks are fired, as the script callbacks may 283 // before script callbacks are fired, as the script callbacks may
241 // release references and allow the backing store itself to be 284 // release references and allow the backing store itself to be
242 // released, and order is critical. 285 // released, and order is critical.
243 CloseOpenCursors(); 286 CloseOpenCursors();
244 transaction_.Reset(); 287 transaction_.Reset();
245 288
246 // Transactions must also be marked as completed before the 289 // Transactions must also be marked as completed before the
247 // front-end is notified, as the transaction completion unblocks 290 // 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; 322 backing_store_transaction_begun_ = true;
280 } 323 }
281 324
282 // The last reference to this object may be released while performing the 325 // 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 326 // tasks. Take take a self reference to keep this object alive so that
284 // the loop termination conditions can be checked. 327 // the loop termination conditions can be checked.
285 scoped_refptr<IndexedDBTransaction> protect(this); 328 scoped_refptr<IndexedDBTransaction> protect(this);
286 329
287 TaskQueue* task_queue = 330 TaskQueue* task_queue =
288 pending_preemptive_events_ ? &preemptive_task_queue_ : &task_queue_; 331 pending_preemptive_events_ ? &preemptive_task_queue_ : &task_queue_;
289 while (!task_queue->empty() && state_ != FINISHED) { 332 while (!task_queue->empty() && !IsStatePastRunning()) {
290 DCHECK_EQ(STARTED, state_); 333 DCHECK_EQ(state_, STARTED);
291 Operation task(task_queue->pop()); 334 Operation task(task_queue->pop());
292 task.Run(this); 335 task.Run(this);
293 if (!pending_preemptive_events_) { 336 if (!pending_preemptive_events_) {
294 DCHECK(diagnostics_.tasks_completed < diagnostics_.tasks_scheduled); 337 DCHECK(diagnostics_.tasks_completed < diagnostics_.tasks_scheduled);
295 ++diagnostics_.tasks_completed; 338 ++diagnostics_.tasks_completed;
296 } 339 }
297 340
298 // Event itself may change which queue should be processed next. 341 // Event itself may change which queue should be processed next.
299 task_queue = 342 task_queue =
300 pending_preemptive_events_ ? &preemptive_task_queue_ : &task_queue_; 343 pending_preemptive_events_ ? &preemptive_task_queue_ : &task_queue_;
301 } 344 }
302 345
303 // If there are no pending tasks, we haven't already committed/aborted, 346 // 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. 347 // and the front-end requested a commit, it is now safe to do so.
305 if (!HasPendingTasks() && state_ != FINISHED && commit_pending_) 348 if (!HasPendingTasks() && !IsStatePastRunning() && commit_pending_)
jsbell 2013/12/20 00:44:20 FYI, if you rebase, a test will appear below this
ericu 2014/02/20 00:50:29 Hmm...I'm not sure about that one. It looks like
jsbell 2014/02/20 22:55:50 There shouldn't be; commit_pending_ should only be
306 Commit(); 349 Commit();
307 } 350 }
308 351
309 void IndexedDBTransaction::CloseOpenCursors() { 352 void IndexedDBTransaction::CloseOpenCursors() {
310 for (std::set<IndexedDBCursor*>::iterator i = open_cursors_.begin(); 353 for (std::set<IndexedDBCursor*>::iterator i = open_cursors_.begin();
311 i != open_cursors_.end(); 354 i != open_cursors_.end();
312 ++i) 355 ++i)
313 (*i)->Close(); 356 (*i)->Close();
314 open_cursors_.clear(); 357 open_cursors_.clear();
315 } 358 }
316 359
317 } // namespace content 360 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698