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

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: Merged out--bot failed due to staleness. Created 6 years, 6 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 70 matching lines...) Expand 10 before | Expand all | Expand 10 after
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(IndexedDBDatabase::TaskType type, 89 void IndexedDBTransaction::ScheduleTask(IndexedDBDatabase::TaskType type,
90 Operation task) { 90 Operation task) {
91 DCHECK_NE(state_, COMMITTING);
91 if (state_ == FINISHED) 92 if (state_ == FINISHED)
92 return; 93 return;
93 94
94 timeout_timer_.Stop(); 95 timeout_timer_.Stop();
95 used_ = true; 96 used_ = true;
96 if (type == IndexedDBDatabase::NORMAL_TASK) { 97 if (type == IndexedDBDatabase::NORMAL_TASK) {
97 task_queue_.push(task); 98 task_queue_.push(task);
98 ++diagnostics_.tasks_scheduled; 99 ++diagnostics_.tasks_scheduled;
99 } else { 100 } else {
100 preemptive_task_queue_.push(task); 101 preemptive_task_queue_.push(task);
(...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after
199 DCHECK_EQ(CREATED, state_); 200 DCHECK_EQ(CREATED, state_);
200 state_ = STARTED; 201 state_ = STARTED;
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 void Run(bool succeeded) OVERRIDE {
215 transaction_->BlobWriteComplete(succeeded);
216 }
217
218 protected:
219 virtual ~BlobWriteCallbackImpl() {}
220
221 private:
222 scoped_refptr<IndexedDBTransaction> transaction_;
223 };
224
225 void IndexedDBTransaction::BlobWriteComplete(bool success) {
226 IDB_TRACE("IndexedDBTransaction::BlobWriteComplete");
227 if (state_ == FINISHED) // aborted
228 return;
229 DCHECK_EQ(state_, COMMITTING);
230 if (success)
231 CommitPhaseTwo();
232 else
233 Abort(IndexedDBDatabaseError(blink::WebIDBDatabaseExceptionDataError,
234 "Failed to write blobs."));
235 }
236
209 void IndexedDBTransaction::Commit() { 237 void IndexedDBTransaction::Commit() {
210 IDB_TRACE("IndexedDBTransaction::Commit"); 238 IDB_TRACE("IndexedDBTransaction::Commit");
211 239
212 // In multiprocess ports, front-end may have requested a commit but 240 // In multiprocess ports, front-end may have requested a commit but
213 // an abort has already been initiated asynchronously by the 241 // an abort has already been initiated asynchronously by the
214 // back-end. 242 // back-end.
215 if (state_ == FINISHED) 243 if (state_ == FINISHED)
216 return; 244 return;
245 DCHECK_NE(state_, COMMITTING);
217 246
218 DCHECK(!used_ || state_ == STARTED); 247 DCHECK(!used_ || state_ == STARTED);
219 commit_pending_ = true; 248 commit_pending_ = true;
220 249
221 // Front-end has requested a commit, but there may be tasks like 250 // Front-end has requested a commit, but there may be tasks like
222 // create_index which are considered synchronous by the front-end 251 // create_index which are considered synchronous by the front-end
223 // but are processed asynchronously. 252 // but are processed asynchronously.
224 if (HasPendingTasks()) 253 if (HasPendingTasks())
225 return; 254 return;
226 255
256 state_ = COMMITTING;
257
258 if (!used_)
259 CommitPhaseTwo();
260 else {
261 scoped_refptr<IndexedDBBackingStore::BlobWriteCallback> callback(
262 new BlobWriteCallbackImpl(this));
263 // CommitPhaseOne will call the callback synchronously if there are no blobs
264 // to write.
265 if (!transaction_->CommitPhaseOne(callback).ok())
266 Abort(IndexedDBDatabaseError(blink::WebIDBDatabaseExceptionDataError,
267 "Error processing blob journal."));
268 }
269 }
270
271 void IndexedDBTransaction::CommitPhaseTwo() {
272 // Abort may have been called just as the blob write completed.
273 if (state_ == FINISHED)
274 return;
275
276 DCHECK_EQ(state_, COMMITTING);
277
227 // 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
228 // 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
229 // alive while executing this method. 280 // alive while executing this method.
230 scoped_refptr<IndexedDBTransaction> protect(this); 281 scoped_refptr<IndexedDBTransaction> protect(this);
231 282
232 timeout_timer_.Stop(); 283 timeout_timer_.Stop();
233 284
234 state_ = FINISHED; 285 state_ = FINISHED;
235 286
236 bool committed = !used_ || transaction_->Commit().ok(); 287 bool committed = !used_ || transaction_->CommitPhaseTwo().ok();
237 288
238 // Backing store resources (held via cursors) must be released 289 // Backing store resources (held via cursors) must be released
239 // before script callbacks are fired, as the script callbacks may 290 // before script callbacks are fired, as the script callbacks may
240 // release references and allow the backing store itself to be 291 // release references and allow the backing store itself to be
241 // released, and order is critical. 292 // released, and order is critical.
242 CloseOpenCursors(); 293 CloseOpenCursors();
243 transaction_->Reset(); 294 transaction_->Reset();
244 295
245 // Transactions must also be marked as completed before the 296 // Transactions must also be marked as completed before the
246 // front-end is notified, as the transaction completion unblocks 297 // front-end is notified, as the transaction completion unblocks
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
282 } 333 }
283 334
284 // 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
285 // 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
286 // the loop termination conditions can be checked. 337 // the loop termination conditions can be checked.
287 scoped_refptr<IndexedDBTransaction> protect(this); 338 scoped_refptr<IndexedDBTransaction> protect(this);
288 339
289 TaskQueue* task_queue = 340 TaskQueue* task_queue =
290 pending_preemptive_events_ ? &preemptive_task_queue_ : &task_queue_; 341 pending_preemptive_events_ ? &preemptive_task_queue_ : &task_queue_;
291 while (!task_queue->empty() && state_ != FINISHED) { 342 while (!task_queue->empty() && state_ != FINISHED) {
292 DCHECK_EQ(STARTED, state_); 343 DCHECK_EQ(state_, STARTED);
293 Operation task(task_queue->pop()); 344 Operation task(task_queue->pop());
294 task.Run(this); 345 task.Run(this);
295 if (!pending_preemptive_events_) { 346 if (!pending_preemptive_events_) {
296 DCHECK(diagnostics_.tasks_completed < diagnostics_.tasks_scheduled); 347 DCHECK(diagnostics_.tasks_completed < diagnostics_.tasks_scheduled);
297 ++diagnostics_.tasks_completed; 348 ++diagnostics_.tasks_completed;
298 } 349 }
299 350
300 // Event itself may change which queue should be processed next. 351 // Event itself may change which queue should be processed next.
301 task_queue = 352 task_queue =
302 pending_preemptive_events_ ? &preemptive_task_queue_ : &task_queue_; 353 pending_preemptive_events_ ? &preemptive_task_queue_ : &task_queue_;
303 } 354 }
304 355
305 // 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,
306 // 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.
307 if (!HasPendingTasks() && state_ != FINISHED && commit_pending_) { 358 if (!HasPendingTasks() && state_ != FINISHED && commit_pending_) {
308 Commit(); 359 Commit();
309 return; 360 return;
310 } 361 }
311 362
312 // The transaction may have been aborted while processing tasks. 363 // The transaction may have been aborted while processing tasks.
313 if (state_ == FINISHED) 364 if (state_ == FINISHED)
314 return; 365 return;
315 366
367 DCHECK(state_ == STARTED);
368
316 // Otherwise, start a timer in case the front-end gets wedged and 369 // Otherwise, start a timer in case the front-end gets wedged and
317 // never requests further activity. Read-only transactions don't 370 // never requests further activity. Read-only transactions don't
318 // block other transactions, so don't time those out. 371 // block other transactions, so don't time those out.
319 if (mode_ != indexed_db::TRANSACTION_READ_ONLY) { 372 if (mode_ != indexed_db::TRANSACTION_READ_ONLY) {
320 timeout_timer_.Start( 373 timeout_timer_.Start(
321 FROM_HERE, 374 FROM_HERE,
322 base::TimeDelta::FromSeconds(kInactivityTimeoutPeriodSeconds), 375 base::TimeDelta::FromSeconds(kInactivityTimeoutPeriodSeconds),
323 base::Bind(&IndexedDBTransaction::Timeout, this)); 376 base::Bind(&IndexedDBTransaction::Timeout, this));
324 } 377 }
325 } 378 }
326 379
327 void IndexedDBTransaction::Timeout() { 380 void IndexedDBTransaction::Timeout() {
328 Abort(IndexedDBDatabaseError( 381 Abort(IndexedDBDatabaseError(
329 blink::WebIDBDatabaseExceptionTimeoutError, 382 blink::WebIDBDatabaseExceptionTimeoutError,
330 base::ASCIIToUTF16("Transaction timed out due to inactivity."))); 383 base::ASCIIToUTF16("Transaction timed out due to inactivity.")));
331 } 384 }
332 385
333 void IndexedDBTransaction::CloseOpenCursors() { 386 void IndexedDBTransaction::CloseOpenCursors() {
334 for (std::set<IndexedDBCursor*>::iterator i = open_cursors_.begin(); 387 for (std::set<IndexedDBCursor*>::iterator i = open_cursors_.begin();
335 i != open_cursors_.end(); 388 i != open_cursors_.end();
336 ++i) 389 ++i)
337 (*i)->Close(); 390 (*i)->Close();
338 open_cursors_.clear(); 391 open_cursors_.clear();
339 } 392 }
340 393
341 } // namespace content 394 } // namespace content
OLDNEW
« no previous file with comments | « content/browser/indexed_db/indexed_db_transaction.h ('k') | content/browser/indexed_db/indexed_db_transaction_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698