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

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

Issue 2472213003: [IndexedDB] Refactoring to remove ref ptrs and host transaction ids. (Closed)
Patch Set: comments Created 4 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
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/location.h" 8 #include "base/location.h"
9 #include "base/logging.h" 9 #include "base/logging.h"
10 #include "base/memory/ptr_util.h" 10 #include "base/memory/ptr_util.h"
(...skipping 12 matching lines...) Expand all
23 #include "third_party/leveldatabase/env_chromium.h" 23 #include "third_party/leveldatabase/env_chromium.h"
24 24
25 namespace content { 25 namespace content {
26 26
27 namespace { 27 namespace {
28 28
29 const int64_t kInactivityTimeoutPeriodSeconds = 60; 29 const int64_t kInactivityTimeoutPeriodSeconds = 60;
30 30
31 // Helper for posting a task to call IndexedDBTransaction::Commit when we know 31 // Helper for posting a task to call IndexedDBTransaction::Commit when we know
32 // the transaction had no requests and therefore the commit must succeed. 32 // the transaction had no requests and therefore the commit must succeed.
33 void CommitUnused(scoped_refptr<IndexedDBTransaction> transaction) { 33 void CommitUnused(base::WeakPtr<IndexedDBTransaction> transaction) {
34 if (!transaction)
35 return;
34 leveldb::Status status = transaction->Commit(); 36 leveldb::Status status = transaction->Commit();
35 DCHECK(status.ok()); 37 DCHECK(status.ok());
36 } 38 }
37 39
38 // The database will be closed during this call. 40 // The database will be closed during this call.
39 void ReportError(leveldb::Status status, 41 void ReportError(leveldb::Status status,
40 const scoped_refptr<IndexedDBDatabase> database, 42 const scoped_refptr<IndexedDBDatabase> database,
41 IndexedDBFactory* factory) { 43 IndexedDBFactory* factory) {
42 DCHECK(!status.ok()); 44 DCHECK(!status.ok());
43 if (status.IsCorruption()) { 45 if (status.IsCorruption()) {
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
78 80
79 IndexedDBTransaction::AbortOperation IndexedDBTransaction::TaskStack::pop() { 81 IndexedDBTransaction::AbortOperation IndexedDBTransaction::TaskStack::pop() {
80 DCHECK(!stack_.empty()); 82 DCHECK(!stack_.empty());
81 AbortOperation task = std::move(stack_.top()); 83 AbortOperation task = std::move(stack_.top());
82 stack_.pop(); 84 stack_.pop();
83 return task; 85 return task;
84 } 86 }
85 87
86 IndexedDBTransaction::IndexedDBTransaction( 88 IndexedDBTransaction::IndexedDBTransaction(
87 int64_t id, 89 int64_t id,
88 base::WeakPtr<IndexedDBConnection> connection, 90 IndexedDBConnection* connection,
89 const std::set<int64_t>& object_store_ids, 91 const std::set<int64_t>& object_store_ids,
90 blink::WebIDBTransactionMode mode, 92 blink::WebIDBTransactionMode mode,
91 IndexedDBBackingStore::Transaction* backing_store_transaction) 93 IndexedDBBackingStore::Transaction* backing_store_transaction)
92 : id_(id), 94 : id_(id),
93 object_store_ids_(object_store_ids), 95 object_store_ids_(object_store_ids),
94 mode_(mode), 96 mode_(mode),
95 connection_(std::move(connection)), 97 connection_(std::move(connection)),
96 transaction_(backing_store_transaction) { 98 transaction_(backing_store_transaction),
99 ptr_factory_(this) {
97 callbacks_ = connection_->callbacks(); 100 callbacks_ = connection_->callbacks();
98 database_ = connection_->database(); 101 database_ = connection_->database();
99 102
100 database_->transaction_coordinator().DidCreateTransaction(this);
101
102 diagnostics_.tasks_scheduled = 0; 103 diagnostics_.tasks_scheduled = 0;
103 diagnostics_.tasks_completed = 0; 104 diagnostics_.tasks_completed = 0;
104 diagnostics_.creation_time = base::Time::Now(); 105 diagnostics_.creation_time = base::Time::Now();
105 } 106 }
106 107
107 IndexedDBTransaction::~IndexedDBTransaction() { 108 IndexedDBTransaction::~IndexedDBTransaction() {
108 // It shouldn't be possible for this object to get deleted until it's either 109 // It shouldn't be possible for this object to get deleted until it's either
109 // complete or aborted. 110 // complete or aborted.
110 DCHECK_EQ(state_, FINISHED); 111 DCHECK_EQ(state_, FINISHED);
111 DCHECK(preemptive_task_queue_.empty()); 112 DCHECK(preemptive_task_queue_.empty());
112 DCHECK_EQ(pending_preemptive_events_, 0); 113 DCHECK_EQ(pending_preemptive_events_, 0);
113 DCHECK(task_queue_.empty()); 114 DCHECK(task_queue_.empty());
114 DCHECK(abort_task_stack_.empty()); 115 DCHECK(abort_task_stack_.empty());
115 DCHECK(pending_observers_.empty());
116 DCHECK(!processing_event_queue_); 116 DCHECK(!processing_event_queue_);
117 } 117 }
118 118
119 void IndexedDBTransaction::ScheduleTask(blink::WebIDBTaskType type, 119 void IndexedDBTransaction::ScheduleTask(blink::WebIDBTaskType type,
120 Operation task) { 120 Operation task) {
121 DCHECK_NE(state_, COMMITTING); 121 DCHECK_NE(state_, COMMITTING);
122 if (state_ == FINISHED) 122 if (state_ == FINISHED)
123 return; 123 return;
124 124
125 timeout_timer_.Stop(); 125 timeout_timer_.Stop();
(...skipping 19 matching lines...) Expand all
145 // Not started by the coordinator yet. 145 // Not started by the coordinator yet.
146 if (state_ != STARTED) 146 if (state_ != STARTED)
147 return; 147 return;
148 148
149 // A task is already posted. 149 // A task is already posted.
150 if (should_process_queue_) 150 if (should_process_queue_)
151 return; 151 return;
152 152
153 should_process_queue_ = true; 153 should_process_queue_ = true;
154 base::ThreadTaskRunnerHandle::Get()->PostTask( 154 base::ThreadTaskRunnerHandle::Get()->PostTask(
155 FROM_HERE, base::Bind(&IndexedDBTransaction::ProcessTaskQueue, this)); 155 FROM_HERE, base::Bind(&IndexedDBTransaction::ProcessTaskQueue,
156 ptr_factory_.GetWeakPtr()));
156 } 157 }
157 158
158 void IndexedDBTransaction::Abort() { 159 void IndexedDBTransaction::Abort() {
159 Abort(IndexedDBDatabaseError(blink::WebIDBDatabaseExceptionUnknownError, 160 Abort(IndexedDBDatabaseError(blink::WebIDBDatabaseExceptionUnknownError,
160 "Internal error (unknown cause)")); 161 "Internal error (unknown cause)"));
161 } 162 }
162 163
163 void IndexedDBTransaction::Abort(const IndexedDBDatabaseError& error) { 164 void IndexedDBTransaction::Abort(const IndexedDBDatabaseError& error) {
164 IDB_TRACE1("IndexedDBTransaction::Abort", "txn.id", id()); 165 IDB_TRACE1("IndexedDBTransaction::Abort", "txn.id", id());
166 DCHECK(!processing_event_queue_);
165 if (state_ == FINISHED) 167 if (state_ == FINISHED)
166 return; 168 return;
167 169
168 // The last reference to this object may be released while performing the
169 // abort steps below. We therefore take a self reference to keep ourselves
170 // alive while executing this method.
171 scoped_refptr<IndexedDBTransaction> protect(this);
172
173 timeout_timer_.Stop(); 170 timeout_timer_.Stop();
174 171
175 state_ = FINISHED; 172 state_ = FINISHED;
176 should_process_queue_ = false; 173 should_process_queue_ = false;
177 174
178 if (backing_store_transaction_begun_) 175 if (backing_store_transaction_begun_)
179 transaction_->Rollback(); 176 transaction_->Rollback();
180 177
181 // Run the abort tasks, if any. 178 // Run the abort tasks, if any.
182 while (!abort_task_stack_.empty()) 179 while (!abort_task_stack_.empty())
(...skipping 12 matching lines...) Expand all
195 192
196 // Transactions must also be marked as completed before the 193 // Transactions must also be marked as completed before the
197 // front-end is notified, as the transaction completion unblocks 194 // front-end is notified, as the transaction completion unblocks
198 // operations like closing connections. 195 // operations like closing connections.
199 database_->transaction_coordinator().DidFinishTransaction(this); 196 database_->transaction_coordinator().DidFinishTransaction(this);
200 #ifndef NDEBUG 197 #ifndef NDEBUG
201 DCHECK(!database_->transaction_coordinator().IsActive(this)); 198 DCHECK(!database_->transaction_coordinator().IsActive(this));
202 #endif 199 #endif
203 200
204 if (callbacks_.get()) 201 if (callbacks_.get())
205 callbacks_->OnAbort(id_, error); 202 callbacks_->OnAbort(*this, error);
206 203
207 database_->TransactionFinished(this, false); 204 database_->TransactionFinished(this, false);
208 205
209 database_ = NULL; 206 // RemoveTransaction will delete |this|.
210 connection_ = nullptr; 207 connection_->RemoveTransaction(id_);
211 pending_observers_.clear();
212 } 208 }
213 209
214 bool IndexedDBTransaction::IsTaskQueueEmpty() const { 210 bool IndexedDBTransaction::IsTaskQueueEmpty() const {
215 return preemptive_task_queue_.empty() && task_queue_.empty(); 211 return preemptive_task_queue_.empty() && task_queue_.empty();
216 } 212 }
217 213
218 bool IndexedDBTransaction::HasPendingTasks() const { 214 bool IndexedDBTransaction::HasPendingTasks() const {
219 return pending_preemptive_events_ || !IsTaskQueueEmpty(); 215 return pending_preemptive_events_ || !IsTaskQueueEmpty();
220 } 216 }
221 217
(...skipping 10 matching lines...) Expand all
232 DCHECK_EQ(CREATED, state_); 228 DCHECK_EQ(CREATED, state_);
233 state_ = STARTED; 229 state_ = STARTED;
234 diagnostics_.start_time = base::Time::Now(); 230 diagnostics_.start_time = base::Time::Now();
235 231
236 if (!used_) { 232 if (!used_) {
237 if (commit_pending_) { 233 if (commit_pending_) {
238 // The transaction has never had requests issued against it, but the 234 // The transaction has never had requests issued against it, but the
239 // front-end previously requested a commit; do the commit now, but not 235 // front-end previously requested a commit; do the commit now, but not
240 // re-entrantly as that may renter the coordinator. 236 // re-entrantly as that may renter the coordinator.
241 base::ThreadTaskRunnerHandle::Get()->PostTask( 237 base::ThreadTaskRunnerHandle::Get()->PostTask(
242 FROM_HERE, base::Bind(&CommitUnused, make_scoped_refptr(this))); 238 FROM_HERE, base::Bind(&CommitUnused, ptr_factory_.GetWeakPtr()));
243 } 239 }
244 return; 240 return;
245 } 241 }
246 242
247 RunTasksIfStarted(); 243 RunTasksIfStarted();
248 } 244 }
249 245
250 class BlobWriteCallbackImpl : public IndexedDBBackingStore::BlobWriteCallback { 246 class BlobWriteCallbackImpl : public IndexedDBBackingStore::BlobWriteCallback {
251 public: 247 public:
252 explicit BlobWriteCallbackImpl( 248 explicit BlobWriteCallbackImpl(
253 scoped_refptr<IndexedDBTransaction> transaction) 249 base::WeakPtr<IndexedDBTransaction> transaction)
254 : transaction_(transaction) {} 250 : transaction_(std::move(transaction)) {}
255 void Run(bool succeeded) override { 251
256 transaction_->BlobWriteComplete(succeeded); 252 leveldb::Status Run(IndexedDBBackingStore::BlobWriteResult result) override {
253 if (!transaction_)
254 return leveldb::Status::OK();
255 return transaction_->BlobWriteComplete(result);
257 } 256 }
258 257
259 protected: 258 protected:
260 ~BlobWriteCallbackImpl() override {} 259 ~BlobWriteCallbackImpl() override {}
261 260
262 private: 261 private:
263 scoped_refptr<IndexedDBTransaction> transaction_; 262 base::WeakPtr<IndexedDBTransaction> transaction_;
264 }; 263 };
265 264
266 void IndexedDBTransaction::BlobWriteComplete(bool success) { 265 leveldb::Status IndexedDBTransaction::BlobWriteComplete(
266 IndexedDBBackingStore::BlobWriteResult result) {
267 IDB_TRACE("IndexedDBTransaction::BlobWriteComplete"); 267 IDB_TRACE("IndexedDBTransaction::BlobWriteComplete");
268 if (state_ == FINISHED) // aborted 268 if (state_ == FINISHED) // aborted
269 return; 269 return leveldb::Status::OK();
270 DCHECK_EQ(state_, COMMITTING); 270 DCHECK_EQ(state_, COMMITTING);
271 271
272 if (!success) { 272 leveldb::Status s = leveldb::Status::OK();
273 Abort(IndexedDBDatabaseError(blink::WebIDBDatabaseExceptionDataError, 273 // Switch statement to protect against adding new enum values.
274 "Failed to write blobs.")); 274 switch (result) {
275 return; 275 case IndexedDBBackingStore::BlobWriteResult::FAILURE_ASYNC:
276 Abort(IndexedDBDatabaseError(blink::WebIDBDatabaseExceptionDataError,
277 "Failed to write blobs."));
278 return leveldb::Status::OK();
279 case IndexedDBBackingStore::BlobWriteResult::SUCCESS_ASYNC:
280 case IndexedDBBackingStore::BlobWriteResult::SUCCESS_SYNC: {
281 // Save the database as |this| can be destroyed in the next line. We also
282 // make
283 // sure to handle the error if we're not being called synchronously.
284 scoped_refptr<IndexedDBDatabase> database = database_;
285 s = CommitPhaseTwo();
286 if (!s.ok() &&
287 result == IndexedDBBackingStore::BlobWriteResult::SUCCESS_ASYNC)
288 ReportError(s, database, database->factory());
289 break;
290 }
276 } 291 }
277 // Save the database as |this| can be destroyed in the next line. 292 return s;
278 scoped_refptr<IndexedDBDatabase> database = database_;
279 leveldb::Status s = CommitPhaseTwo();
280 if (!s.ok())
281 ReportError(s, database, database->factory());
282 } 293 }
283 294
284 leveldb::Status IndexedDBTransaction::Commit() { 295 leveldb::Status IndexedDBTransaction::Commit() {
285 IDB_TRACE1("IndexedDBTransaction::Commit", "txn.id", id()); 296 IDB_TRACE1("IndexedDBTransaction::Commit", "txn.id", id());
286 297
287 timeout_timer_.Stop(); 298 timeout_timer_.Stop();
288 299
289 // In multiprocess ports, front-end may have requested a commit but 300 // In multiprocess ports, front-end may have requested a commit but
290 // an abort has already been initiated asynchronously by the 301 // an abort has already been initiated asynchronously by the
291 // back-end. 302 // back-end.
(...skipping 16 matching lines...) Expand all
308 if (HasPendingTasks()) 319 if (HasPendingTasks())
309 return leveldb::Status::OK(); 320 return leveldb::Status::OK();
310 321
311 state_ = COMMITTING; 322 state_ = COMMITTING;
312 323
313 leveldb::Status s; 324 leveldb::Status s;
314 if (!used_) { 325 if (!used_) {
315 s = CommitPhaseTwo(); 326 s = CommitPhaseTwo();
316 } else { 327 } else {
317 scoped_refptr<IndexedDBBackingStore::BlobWriteCallback> callback( 328 scoped_refptr<IndexedDBBackingStore::BlobWriteCallback> callback(
318 new BlobWriteCallbackImpl(this)); 329 new BlobWriteCallbackImpl(ptr_factory_.GetWeakPtr()));
319 // CommitPhaseOne will call the callback synchronously if there are no blobs 330 // CommitPhaseOne will call the callback synchronously if there are no blobs
320 // to write. 331 // to write.
321 s = transaction_->CommitPhaseOne(callback); 332 s = transaction_->CommitPhaseOne(callback);
322 if (!s.ok())
323 Abort(IndexedDBDatabaseError(blink::WebIDBDatabaseExceptionDataError,
324 "Error processing blob journal."));
325 } 333 }
326 334
327 return s; 335 return s;
328 } 336 }
329 337
330 leveldb::Status IndexedDBTransaction::CommitPhaseTwo() { 338 leveldb::Status IndexedDBTransaction::CommitPhaseTwo() {
331 // Abort may have been called just as the blob write completed. 339 // Abort may have been called just as the blob write completed.
332 if (state_ == FINISHED) 340 if (state_ == FINISHED)
333 return leveldb::Status::OK(); 341 return leveldb::Status::OK();
334 342
335 DCHECK_EQ(state_, COMMITTING); 343 DCHECK_EQ(state_, COMMITTING);
336 344
337 // The last reference to this object may be released while performing the
338 // commit steps below. We therefore take a self reference to keep ourselves
339 // alive while executing this method.
340 scoped_refptr<IndexedDBTransaction> protect(this);
341
342 state_ = FINISHED; 345 state_ = FINISHED;
343 346
344 leveldb::Status s; 347 leveldb::Status s;
345 bool committed; 348 bool committed;
346 if (!used_) { 349 if (!used_) {
347 committed = true; 350 committed = true;
348 } else { 351 } else {
349 s = transaction_->CommitPhaseTwo(); 352 s = transaction_->CommitPhaseTwo();
350 committed = s.ok(); 353 committed = s.ok();
351 } 354 }
(...skipping 16 matching lines...) Expand all
368 // SendObservations must be called before OnComplete to ensure consistency 371 // SendObservations must be called before OnComplete to ensure consistency
369 // of callbacks at renderer. 372 // of callbacks at renderer.
370 if (!connection_changes_map_.empty()) { 373 if (!connection_changes_map_.empty()) {
371 database_->SendObservations(std::move(connection_changes_map_)); 374 database_->SendObservations(std::move(connection_changes_map_));
372 connection_changes_map_.clear(); 375 connection_changes_map_.clear();
373 } 376 }
374 { 377 {
375 IDB_TRACE1( 378 IDB_TRACE1(
376 "IndexedDBTransaction::CommitPhaseTwo.TransactionCompleteCallbacks", 379 "IndexedDBTransaction::CommitPhaseTwo.TransactionCompleteCallbacks",
377 "txn.id", id()); 380 "txn.id", id());
378 callbacks_->OnComplete(id_); 381 callbacks_->OnComplete(*this);
379 } 382 }
380 if (!pending_observers_.empty() && connection_) { 383 if (!pending_observers_.empty() && connection_) {
381 connection_->ActivatePendingObservers(std::move(pending_observers_)); 384 connection_->ActivatePendingObservers(std::move(pending_observers_));
382 pending_observers_.clear(); 385 pending_observers_.clear();
383 } 386 }
384 387
385 database_->TransactionFinished(this, true); 388 database_->TransactionFinished(this, true);
389 // RemoveTransaction will delete |this|.
390 connection_->RemoveTransaction(id_);
391 return s;
386 } else { 392 } else {
387 while (!abort_task_stack_.empty()) 393 while (!abort_task_stack_.empty())
388 abort_task_stack_.pop().Run(); 394 abort_task_stack_.pop().Run();
389 395
390 IndexedDBDatabaseError error; 396 IndexedDBDatabaseError error;
391 if (leveldb_env::IndicatesDiskFull(s)) { 397 if (leveldb_env::IndicatesDiskFull(s)) {
392 error = IndexedDBDatabaseError( 398 error = IndexedDBDatabaseError(
393 blink::WebIDBDatabaseExceptionQuotaError, 399 blink::WebIDBDatabaseExceptionQuotaError,
394 "Encountered disk full while committing transaction."); 400 "Encountered disk full while committing transaction.");
395 } else { 401 } else {
396 error = IndexedDBDatabaseError(blink::WebIDBDatabaseExceptionUnknownError, 402 error = IndexedDBDatabaseError(blink::WebIDBDatabaseExceptionUnknownError,
397 "Internal error committing transaction."); 403 "Internal error committing transaction.");
398 } 404 }
399 callbacks_->OnAbort(id_, error); 405 callbacks_->OnAbort(*this, error);
400
401 database_->TransactionFinished(this, false); 406 database_->TransactionFinished(this, false);
402 } 407 }
403
404 database_ = NULL;
405 return s; 408 return s;
406 } 409 }
407 410
408 void IndexedDBTransaction::ProcessTaskQueue() { 411 void IndexedDBTransaction::ProcessTaskQueue() {
409 IDB_TRACE1("IndexedDBTransaction::ProcessTaskQueue", "txn.id", id()); 412 IDB_TRACE1("IndexedDBTransaction::ProcessTaskQueue", "txn.id", id());
410 413
411 DCHECK(!processing_event_queue_); 414 DCHECK(!processing_event_queue_);
412 415
413 // May have been aborted. 416 // May have been aborted.
414 if (!should_process_queue_) 417 if (!should_process_queue_)
415 return; 418 return;
416 419
417 processing_event_queue_ = true; 420 processing_event_queue_ = true;
418 421
419 DCHECK(!IsTaskQueueEmpty()); 422 DCHECK(!IsTaskQueueEmpty());
420 should_process_queue_ = false; 423 should_process_queue_ = false;
421 424
422 if (!backing_store_transaction_begun_) { 425 if (!backing_store_transaction_begun_) {
423 transaction_->Begin(); 426 transaction_->Begin();
424 backing_store_transaction_begun_ = true; 427 backing_store_transaction_begun_ = true;
425 } 428 }
426 429
427 // The last reference to this object may be released while performing the
428 // tasks. Take take a self reference to keep this object alive so that
429 // the loop termination conditions can be checked.
430 scoped_refptr<IndexedDBTransaction> protect(this);
431
432 TaskQueue* task_queue = 430 TaskQueue* task_queue =
433 pending_preemptive_events_ ? &preemptive_task_queue_ : &task_queue_; 431 pending_preemptive_events_ ? &preemptive_task_queue_ : &task_queue_;
434 while (!task_queue->empty() && state_ != FINISHED) { 432 while (!task_queue->empty() && state_ != FINISHED) {
435 DCHECK_EQ(state_, STARTED); 433 DCHECK_EQ(state_, STARTED);
436 Operation task(task_queue->pop()); 434 Operation task(task_queue->pop());
437 leveldb::Status result = task.Run(this); 435 leveldb::Status result = task.Run(this);
438 if (!pending_preemptive_events_) { 436 if (!pending_preemptive_events_) {
439 DCHECK(diagnostics_.tasks_completed < diagnostics_.tasks_scheduled); 437 DCHECK(diagnostics_.tasks_completed < diagnostics_.tasks_scheduled);
440 ++diagnostics_.tasks_completed; 438 ++diagnostics_.tasks_completed;
441 } 439 }
442 if (!result.ok()) { 440 if (!result.ok()) {
443 processing_event_queue_ = false; 441 processing_event_queue_ = false;
444 if (!result.ok()) 442 ReportError(result, database_, database_->factory());
445 ReportError(result, database_, database_->factory());
446 return; 443 return;
447 } 444 }
448 445
449 // Event itself may change which queue should be processed next. 446 // Event itself may change which queue should be processed next.
450 task_queue = 447 task_queue =
451 pending_preemptive_events_ ? &preemptive_task_queue_ : &task_queue_; 448 pending_preemptive_events_ ? &preemptive_task_queue_ : &task_queue_;
452 } 449 }
453 450
454 // If there are no pending tasks, we haven't already committed/aborted, 451 // If there are no pending tasks, we haven't already committed/aborted,
455 // and the front-end requested a commit, it is now safe to do so. 452 // and the front-end requested a commit, it is now safe to do so.
456 if (!HasPendingTasks() && state_ != FINISHED && commit_pending_) { 453 if (!HasPendingTasks() && state_ != FINISHED && commit_pending_) {
454 processing_event_queue_ = false;
455 // This can delete |this|.
457 leveldb::Status result = Commit(); 456 leveldb::Status result = Commit();
458 processing_event_queue_ = false;
459 if (!result.ok()) 457 if (!result.ok())
460 ReportError(result, database_, database_->factory()); 458 ReportError(result, database_, database_->factory());
461 return; 459 return;
462 } 460 }
463 461
464 // The transaction may have been aborted while processing tasks. 462 // The transaction may have been aborted while processing tasks.
465 if (state_ == FINISHED) { 463 if (state_ == FINISHED) {
466 processing_event_queue_ = false; 464 processing_event_queue_ = false;
467 return; 465 return;
468 } 466 }
469 467
470 DCHECK(state_ == STARTED); 468 DCHECK(state_ == STARTED);
471 469
472 // Otherwise, start a timer in case the front-end gets wedged and 470 // Otherwise, start a timer in case the front-end gets wedged and
473 // never requests further activity. Read-only transactions don't 471 // never requests further activity. Read-only transactions don't
474 // block other transactions, so don't time those out. 472 // block other transactions, so don't time those out.
475 if (mode_ != blink::WebIDBTransactionModeReadOnly) { 473 if (mode_ != blink::WebIDBTransactionModeReadOnly) {
476 timeout_timer_.Start(FROM_HERE, GetInactivityTimeout(), 474 timeout_timer_.Start(
477 base::Bind(&IndexedDBTransaction::Timeout, this)); 475 FROM_HERE, GetInactivityTimeout(),
476 base::Bind(&IndexedDBTransaction::Timeout, ptr_factory_.GetWeakPtr()));
478 } 477 }
479 processing_event_queue_ = false; 478 processing_event_queue_ = false;
480 } 479 }
481 480
482 base::TimeDelta IndexedDBTransaction::GetInactivityTimeout() const { 481 base::TimeDelta IndexedDBTransaction::GetInactivityTimeout() const {
483 return base::TimeDelta::FromSeconds(kInactivityTimeoutPeriodSeconds); 482 return base::TimeDelta::FromSeconds(kInactivityTimeoutPeriodSeconds);
484 } 483 }
485 484
486 void IndexedDBTransaction::Timeout() { 485 void IndexedDBTransaction::Timeout() {
487 Abort(IndexedDBDatabaseError( 486 Abort(IndexedDBDatabaseError(
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
530 void IndexedDBTransaction::RecordObserverForLastObservation( 529 void IndexedDBTransaction::RecordObserverForLastObservation(
531 int32_t connection_id, 530 int32_t connection_id,
532 int32_t observer_id) { 531 int32_t observer_id) {
533 auto it = connection_changes_map_.find(connection_id); 532 auto it = connection_changes_map_.find(connection_id);
534 DCHECK(it != connection_changes_map_.end()); 533 DCHECK(it != connection_changes_map_.end());
535 it->second->observation_index_map[observer_id].push_back( 534 it->second->observation_index_map[observer_id].push_back(
536 it->second->observations.size() - 1); 535 it->second->observations.size() - 1);
537 } 536 }
538 537
539 } // namespace content 538 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698