OLD | NEW |
---|---|
1 /* | 1 /* |
2 * Copyright (C) 2010 Google Inc. All rights reserved. | 2 * Copyright (C) 2010 Google Inc. All rights reserved. |
3 * | 3 * |
4 * Redistribution and use in source and binary forms, with or without | 4 * Redistribution and use in source and binary forms, with or without |
5 * modification, are permitted provided that the following conditions | 5 * modification, are permitted provided that the following conditions |
6 * are met: | 6 * are met: |
7 * | 7 * |
8 * 1. Redistributions of source code must retain the above copyright | 8 * 1. Redistributions of source code must retain the above copyright |
9 * notice, this list of conditions and the following disclaimer. | 9 * notice, this list of conditions and the following disclaimer. |
10 * 2. Redistributions in binary form must reproduce the above copyright | 10 * 2. Redistributions in binary form must reproduce the above copyright |
(...skipping 109 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
120 DCHECK(m_requestList.isEmpty() || m_contextStopped); | 120 DCHECK(m_requestList.isEmpty() || m_contextStopped); |
121 } | 121 } |
122 | 122 |
123 DEFINE_TRACE(IDBTransaction) | 123 DEFINE_TRACE(IDBTransaction) |
124 { | 124 { |
125 visitor->trace(m_database); | 125 visitor->trace(m_database); |
126 visitor->trace(m_openDBRequest); | 126 visitor->trace(m_openDBRequest); |
127 visitor->trace(m_error); | 127 visitor->trace(m_error); |
128 visitor->trace(m_requestList); | 128 visitor->trace(m_requestList); |
129 visitor->trace(m_objectStoreMap); | 129 visitor->trace(m_objectStoreMap); |
130 visitor->trace(m_createdObjectStores); | 130 visitor->trace(m_oldStoreMetadata); |
131 visitor->trace(m_deletedObjectStores); | 131 visitor->trace(m_deletedIndexes); |
132 visitor->trace(m_objectStoreCleanupMap); | |
133 EventTargetWithInlineData::trace(visitor); | 132 EventTargetWithInlineData::trace(visitor); |
134 ActiveDOMObject::trace(visitor); | 133 ActiveDOMObject::trace(visitor); |
135 } | 134 } |
136 | 135 |
137 void IDBTransaction::setError(DOMException* error) | 136 void IDBTransaction::setError(DOMException* error) |
138 { | 137 { |
139 DCHECK_NE(m_state, Finished); | 138 DCHECK_NE(m_state, Finished); |
140 DCHECK(error); | 139 DCHECK(error); |
141 | 140 |
142 // The first error to be set is the true cause of the | 141 // The first error to be set is the true cause of the |
143 // transaction abort. | 142 // transaction abort. |
144 if (!m_error) { | 143 if (!m_error) |
145 m_error = error; | 144 m_error = error; |
146 } | |
147 } | 145 } |
148 | 146 |
149 IDBObjectStore* IDBTransaction::objectStore(const String& name, ExceptionState& exceptionState) | 147 IDBObjectStore* IDBTransaction::objectStore(const String& name, ExceptionState& exceptionState) |
150 { | 148 { |
151 if (isFinished()) { | 149 if (isFinished()) { |
152 exceptionState.throwDOMException(InvalidStateError, IDBDatabase::transac tionFinishedErrorMessage); | 150 exceptionState.throwDOMException(InvalidStateError, IDBDatabase::transac tionFinishedErrorMessage); |
153 return nullptr; | 151 return nullptr; |
154 } | 152 } |
155 | 153 |
156 IDBObjectStoreMap::iterator it = m_objectStoreMap.find(name); | 154 IDBObjectStoreMap::iterator it = m_objectStoreMap.find(name); |
157 if (it != m_objectStoreMap.end()) | 155 if (it != m_objectStoreMap.end()) |
158 return it->value; | 156 return it->value; |
159 | 157 |
160 if (!isVersionChange() && !m_scope.contains(name)) { | 158 if (!isVersionChange() && !m_scope.contains(name)) { |
161 exceptionState.throwDOMException(NotFoundError, IDBDatabase::noSuchObjec tStoreErrorMessage); | 159 exceptionState.throwDOMException(NotFoundError, IDBDatabase::noSuchObjec tStoreErrorMessage); |
162 return nullptr; | 160 return nullptr; |
163 } | 161 } |
164 | 162 |
165 int64_t objectStoreId = m_database->findObjectStoreId(name); | 163 int64_t objectStoreId = m_database->findObjectStoreId(name); |
166 if (objectStoreId == IDBObjectStoreMetadata::InvalidId) { | 164 if (objectStoreId == IDBObjectStoreMetadata::InvalidId) { |
167 DCHECK(isVersionChange()); | 165 DCHECK(isVersionChange()); |
168 exceptionState.throwDOMException(NotFoundError, IDBDatabase::noSuchObjec tStoreErrorMessage); | 166 exceptionState.throwDOMException(NotFoundError, IDBDatabase::noSuchObjec tStoreErrorMessage); |
169 return nullptr; | 167 return nullptr; |
170 } | 168 } |
171 | 169 |
172 DCHECK(m_database->metadata().objectStores.contains(objectStoreId)); | 170 DCHECK(m_database->metadata().objectStores.contains(objectStoreId)); |
173 const IDBObjectStoreMetadata& objectStoreMetadata = m_database->metadata().o bjectStores.get(objectStoreId); | 171 RefPtr<IDBObjectStoreMetadata> objectStoreMetadata = m_database->metadata(). objectStores.get(objectStoreId); |
172 DCHECK(objectStoreMetadata.get()); | |
174 | 173 |
175 IDBObjectStore* objectStore = IDBObjectStore::create(objectStoreMetadata, th is); | 174 IDBObjectStore* objectStore = IDBObjectStore::create(std::move(objectStoreMe tadata), this); |
176 DCHECK(!m_objectStoreMap.contains(name)); | 175 DCHECK(!m_objectStoreMap.contains(name)); |
177 m_objectStoreMap.set(name, objectStore); | 176 m_objectStoreMap.set(name, objectStore); |
178 m_objectStoreCleanupMap.set(objectStore, objectStore->metadata()); | 177 |
178 if (isVersionChange()) { | |
179 DCHECK(objectStore->id() <= oldMaxObjectStoreId()) << "Object store IDs are not assigned sequentially"; | |
180 RefPtr<IDBObjectStoreMetadata> backupMetadata = objectStore->metadata(). createCopy(); | |
181 m_oldStoreMetadata.set(objectStore, std::move(backupMetadata)); | |
182 } | |
179 return objectStore; | 183 return objectStore; |
180 } | 184 } |
181 | 185 |
182 void IDBTransaction::objectStoreCreated(const String& name, IDBObjectStore* obje ctStore) | 186 void IDBTransaction::objectStoreCreated(const String& name, IDBObjectStore* obje ctStore) |
183 { | 187 { |
184 DCHECK_NE(m_state, Finished) << "A finished transaction created an object st ore"; | 188 DCHECK_NE(m_state, Finished) << "A finished transaction created an object st ore"; |
185 DCHECK_EQ(m_mode, WebIDBTransactionModeVersionChange) << "A non-versionchang e transaction created an object store"; | 189 DCHECK_EQ(m_mode, WebIDBTransactionModeVersionChange) << "A non-versionchang e transaction created an object store"; |
186 DCHECK(!m_objectStoreMap.contains(name)) << "An object store was created wit h the name of an existing store"; | 190 DCHECK(!m_objectStoreMap.contains(name)) << "An object store was created wit h the name of an existing store"; |
191 DCHECK(objectStore->id() > oldMaxObjectStoreId()) << "Object store IDs are n ot assigned sequentially"; | |
187 m_objectStoreMap.set(name, objectStore); | 192 m_objectStoreMap.set(name, objectStore); |
188 m_objectStoreCleanupMap.set(objectStore, objectStore->metadata()); | |
189 m_createdObjectStores.add(objectStore); | |
190 } | 193 } |
191 | 194 |
192 void IDBTransaction::objectStoreDeleted(const String& name) | 195 void IDBTransaction::objectStoreDeleted(const int64_t objectStoreId, const Strin g& name) |
193 { | 196 { |
194 DCHECK_NE(m_state, Finished) << "A finished transaction deleted an object st ore"; | 197 DCHECK_NE(m_state, Finished) << "A finished transaction deleted an object st ore"; |
195 DCHECK_EQ(m_mode, WebIDBTransactionModeVersionChange) << "A non-versionchang e transaction deleted an object store"; | 198 DCHECK_EQ(m_mode, WebIDBTransactionModeVersionChange) << "A non-versionchang e transaction deleted an object store"; |
196 IDBObjectStoreMap::iterator it = m_objectStoreMap.find(name); | 199 IDBObjectStoreMap::iterator it = m_objectStoreMap.find(name); |
197 if (it != m_objectStoreMap.end()) { | 200 if (it == m_objectStoreMap.end()) { |
201 DCHECK(m_database->metadata().objectStores.contains(objectStoreId)); | |
jsbell
2016/09/26 22:23:40
Can you add a comment about what it means when the
pwnall
2016/09/27 00:12:19
Done.
Thank you! I think future me will be really
| |
202 RefPtr<IDBObjectStoreMetadata> metadata = m_database->metadata().objectS tores.get(objectStoreId); | |
203 DCHECK(metadata.get()); | |
204 DCHECK_EQ(metadata->name, name); | |
205 m_deletedObjectStores.append(std::move(metadata)); | |
206 } else { | |
198 IDBObjectStore* objectStore = it->value; | 207 IDBObjectStore* objectStore = it->value; |
199 m_objectStoreMap.remove(name); | 208 m_objectStoreMap.remove(name); |
200 objectStore->markDeleted(); | 209 objectStore->markDeleted(); |
201 m_objectStoreCleanupMap.set(objectStore, objectStore->metadata()); | 210 if (objectStore->id() > m_oldDatabaseMetadata.maxObjectStoreId) { |
202 m_deletedObjectStores.add(objectStore); | 211 // This store was created and deleted in the same transaction, so it |
212 // will not be restored even if the transaction aborts. We have just | |
213 // removed our last reference to it. | |
214 DCHECK(!m_oldStoreMetadata.contains(objectStore)); | |
215 objectStore->clearIndexCache(); | |
216 } else { | |
217 DCHECK(m_oldStoreMetadata.contains(objectStore)); | |
218 } | |
203 } | 219 } |
204 } | 220 } |
205 | 221 |
206 void IDBTransaction::objectStoreRenamed(const String& oldName, const String& new Name) | 222 void IDBTransaction::objectStoreRenamed(const String& oldName, const String& new Name) |
207 { | 223 { |
208 DCHECK_NE(m_state, Finished) << "A finished transaction renamed an object st ore"; | 224 DCHECK_NE(m_state, Finished) << "A finished transaction renamed an object st ore"; |
209 DCHECK_EQ(m_mode, WebIDBTransactionModeVersionChange) << "A non-versionchang e transaction renamed an object store"; | 225 DCHECK_EQ(m_mode, WebIDBTransactionModeVersionChange) << "A non-versionchang e transaction renamed an object store"; |
210 | 226 |
211 DCHECK(!m_objectStoreMap.contains(newName)); | 227 DCHECK(!m_objectStoreMap.contains(newName)); |
212 DCHECK(m_objectStoreMap.contains(oldName)) << "The object store had to be ac cessed in order to be renamed."; | 228 DCHECK(m_objectStoreMap.contains(oldName)) << "The object store had to be ac cessed in order to be renamed."; |
213 m_objectStoreMap.set(newName, m_objectStoreMap.take(oldName)); | 229 m_objectStoreMap.set(newName, m_objectStoreMap.take(oldName)); |
214 } | 230 } |
215 | 231 |
232 void IDBTransaction::indexDeleted(IDBIndex* index) | |
233 { | |
234 DCHECK(index); | |
235 DCHECK(!index->isDeleted()) << "indexDeleted called twice for the same index "; | |
236 | |
237 IDBObjectStore* objectStore = index->objectStore(); | |
238 DCHECK_EQ(objectStore->transaction(), this); | |
239 DCHECK(m_objectStoreMap.contains(objectStore->name())) << "An index was dele ted without accessing its object store"; | |
240 | |
241 const auto& objectStoreIterator = m_oldStoreMetadata.find(objectStore); | |
jsbell
2016/09/26 22:23:40
Can you add a comment about what this case means?
pwnall
2016/09/27 00:12:19
Done.
Future me thanks you!
| |
242 if (objectStoreIterator == m_oldStoreMetadata.end()) | |
243 return; | |
244 | |
245 const IDBObjectStoreMetadata* oldStoreMetadata = objectStoreIterator->value. get(); | |
246 DCHECK(oldStoreMetadata); | |
jsbell
2016/09/26 22:23:40
Can you add a comment about what this case means?
pwnall
2016/09/27 00:12:19
Done.
Once again, future me thanks you!
| |
247 if (!oldStoreMetadata->indexes.contains(index->id())) | |
248 return; | |
249 | |
250 m_deletedIndexes.append(index); | |
251 } | |
252 | |
216 void IDBTransaction::setActive(bool active) | 253 void IDBTransaction::setActive(bool active) |
217 { | 254 { |
218 DCHECK_NE(m_state, Finished) << "A finished transaction tried to setActive(" << (active ? "true" : "false") << ")"; | 255 DCHECK_NE(m_state, Finished) << "A finished transaction tried to setActive(" << (active ? "true" : "false") << ")"; |
219 if (m_state == Finishing) | 256 if (m_state == Finishing) |
220 return; | 257 return; |
221 DCHECK_NE(active, (m_state == Active)); | 258 DCHECK_NE(active, (m_state == Active)); |
222 m_state = active ? Active : Inactive; | 259 m_state = active ? Active : Inactive; |
223 | 260 |
224 if (!active && m_requestList.isEmpty() && backendDB()) | 261 if (!active && m_requestList.isEmpty() && backendDB()) |
225 backendDB()->commit(m_id); | 262 backendDB()->commit(m_id); |
(...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
315 if (modeString == IndexedDBNames::readonly) | 352 if (modeString == IndexedDBNames::readonly) |
316 return WebIDBTransactionModeReadOnly; | 353 return WebIDBTransactionModeReadOnly; |
317 if (modeString == IndexedDBNames::readwrite) | 354 if (modeString == IndexedDBNames::readwrite) |
318 return WebIDBTransactionModeReadWrite; | 355 return WebIDBTransactionModeReadWrite; |
319 if (modeString == IndexedDBNames::versionchange) | 356 if (modeString == IndexedDBNames::versionchange) |
320 return WebIDBTransactionModeVersionChange; | 357 return WebIDBTransactionModeVersionChange; |
321 NOTREACHED(); | 358 NOTREACHED(); |
322 return WebIDBTransactionModeReadOnly; | 359 return WebIDBTransactionModeReadOnly; |
323 } | 360 } |
324 | 361 |
362 WebIDBDatabase* IDBTransaction::backendDB() const | |
363 { | |
364 return m_database->backend(); | |
365 } | |
366 | |
325 const String& IDBTransaction::mode() const | 367 const String& IDBTransaction::mode() const |
326 { | 368 { |
327 switch (m_mode) { | 369 switch (m_mode) { |
328 case WebIDBTransactionModeReadOnly: | 370 case WebIDBTransactionModeReadOnly: |
329 return IndexedDBNames::readonly; | 371 return IndexedDBNames::readonly; |
330 | 372 |
331 case WebIDBTransactionModeReadWrite: | 373 case WebIDBTransactionModeReadWrite: |
332 return IndexedDBNames::readwrite; | 374 return IndexedDBNames::readwrite; |
333 | 375 |
334 case WebIDBTransactionModeVersionChange: | 376 case WebIDBTransactionModeVersionChange: |
335 return IndexedDBNames::versionchange; | 377 return IndexedDBNames::versionchange; |
336 } | 378 } |
337 | 379 |
338 NOTREACHED(); | 380 NOTREACHED(); |
339 return IndexedDBNames::readonly; | 381 return IndexedDBNames::readonly; |
340 } | 382 } |
341 | 383 |
342 WebIDBDatabase* IDBTransaction::backendDB() const | |
343 { | |
344 return m_database->backend(); | |
345 } | |
346 | |
347 DOMStringList* IDBTransaction::objectStoreNames() const | 384 DOMStringList* IDBTransaction::objectStoreNames() const |
348 { | 385 { |
349 if (isVersionChange()) | 386 if (isVersionChange()) |
350 return m_database->objectStoreNames(); | 387 return m_database->objectStoreNames(); |
351 | 388 |
352 DOMStringList* objectStoreNames = DOMStringList::create(DOMStringList::Index edDB); | 389 DOMStringList* objectStoreNames = DOMStringList::create(DOMStringList::Index edDB); |
353 for (const String& objectStoreName : m_scope) | 390 for (const String& objectStoreName : m_scope) |
354 objectStoreNames->append(objectStoreName); | 391 objectStoreNames->append(objectStoreName); |
355 objectStoreNames->sort(); | 392 objectStoreNames->sort(); |
356 return objectStoreNames; | 393 return objectStoreNames; |
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
423 request->abort(); | 460 request->abort(); |
424 m_requestList.clear(); | 461 m_requestList.clear(); |
425 } | 462 } |
426 | 463 |
427 void IDBTransaction::revertDatabaseMetadata() | 464 void IDBTransaction::revertDatabaseMetadata() |
428 { | 465 { |
429 DCHECK_NE(m_state, Active); | 466 DCHECK_NE(m_state, Active); |
430 if (!isVersionChange()) | 467 if (!isVersionChange()) |
431 return; | 468 return; |
432 | 469 |
433 // Newly created stores must be marked as deleted. | 470 // Mark stores created by this transaction as deleted. |
434 for (IDBObjectStore* store : m_createdObjectStores) { | 471 for (auto& it : m_objectStoreMap) { |
435 store->abort(); | 472 IDBObjectStore* objectStore = it.value; |
436 store->markDeleted(); | 473 const int64_t objectStoreId = objectStore->id(); |
474 if (objectStoreId <= oldMaxObjectStoreId()) { | |
475 DCHECK(m_oldStoreMetadata.contains(objectStore)); | |
476 continue; | |
477 } | |
478 | |
479 DCHECK(!m_oldStoreMetadata.contains(objectStore)); | |
480 m_database->revertObjectStoreCreation(objectStoreId); | |
481 objectStore->markDeleted(); | |
437 } | 482 } |
438 | 483 |
439 // Used stores may need to mark indexes as deleted. | 484 for (auto& it : m_oldStoreMetadata) { |
440 for (auto& it : m_objectStoreCleanupMap) { | 485 IDBObjectStore* objectStore = it.key; |
441 it.key->abort(); | 486 RefPtr<IDBObjectStoreMetadata> oldMetadata = it.value; |
442 it.key->setMetadata(it.value); | 487 |
488 m_database->revertObjectStoreMetadata(oldMetadata); | |
489 objectStore->revertMetadata(oldMetadata); | |
443 } | 490 } |
444 | 491 for (auto& it : m_deletedIndexes) { |
445 m_database->setMetadata(m_oldDatabaseMetadata); | 492 IDBIndex* index = static_cast<IDBIndex*>(it); |
493 index->objectStore()->revertDeletedIndexMetadata(*index); | |
494 } | |
495 for (auto& it: m_deletedObjectStores) { | |
496 RefPtr<IDBObjectStoreMetadata> oldMedata = static_cast<RefPtr<IDBObjectS toreMetadata>>(it); | |
497 m_database->revertObjectStoreMetadata(std::move(it)); | |
498 } | |
499 m_database->setDatabaseMetadata(m_oldDatabaseMetadata); | |
446 } | 500 } |
447 | 501 |
448 void IDBTransaction::finished() | 502 void IDBTransaction::finished() |
449 { | 503 { |
450 #if DCHECK_IS_ON() | 504 #if DCHECK_IS_ON() |
451 DCHECK(!m_finishCalled); | 505 DCHECK(!m_finishCalled); |
452 m_finishCalled = true; | 506 m_finishCalled = true; |
453 #endif // DCHECK_IS_ON() | 507 #endif // DCHECK_IS_ON() |
454 | 508 |
455 m_database->transactionFinished(this); | 509 m_database->transactionFinished(this); |
456 | 510 |
457 // Break reference cycles. | 511 // Remove references to the IDBObjectStore and IDBIndex instances held by |
jsbell
2016/09/26 22:23:40
This comment is misleading; they types can be GC'd
pwnall
2016/09/27 00:12:19
Gah, sorry for the poor explanation.
I was thinki
| |
458 // TODO(jsbell): This can be removed c/o Oilpan. | 512 // this transaction, so OilPan can garbage-collect the instances that aren't |
459 for (auto& it : m_objectStoreMap) | 513 // used by JavaScript. |
460 it.value->transactionFinished(); | 514 |
515 for (auto& it : m_objectStoreMap) { | |
516 IDBObjectStore* objectStore = it.value; | |
517 if (!isVersionChange() || objectStore->id() > oldMaxObjectStoreId()) { | |
518 DCHECK(!m_oldStoreMetadata.contains(objectStore)); | |
519 objectStore->clearIndexCache(); | |
520 } else { | |
521 // We'll call clearIndexCache() on this store in the loop below. | |
522 DCHECK(m_oldStoreMetadata.contains(objectStore)); | |
523 } | |
524 } | |
461 m_objectStoreMap.clear(); | 525 m_objectStoreMap.clear(); |
462 for (auto& it : m_deletedObjectStores) | 526 |
463 it->transactionFinished(); | 527 for (auto& it : m_oldStoreMetadata) { |
464 m_createdObjectStores.clear(); | 528 IDBObjectStore* objectStore = it.key; |
529 objectStore->clearIndexCache(); | |
530 } | |
531 m_oldStoreMetadata.clear(); | |
532 | |
533 m_deletedIndexes.clear(); | |
465 m_deletedObjectStores.clear(); | 534 m_deletedObjectStores.clear(); |
466 | |
467 m_objectStoreCleanupMap.clear(); | |
468 } | 535 } |
469 | 536 |
470 } // namespace blink | 537 } // namespace blink |
OLD | NEW |