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

Side by Side Diff: third_party/WebKit/Source/modules/indexeddb/IDBTransaction.cpp

Issue 2314933005: Align IndexedDB metadata rollback on transaction abort to spec. (Closed)
Patch Set: Add failing tests. Created 4 years, 3 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
« no previous file with comments | « third_party/WebKit/Source/modules/indexeddb/IDBTransaction.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 100 matching lines...) Expand 10 before | Expand all | Expand 10 after
111 ASSERT(m_requestList.isEmpty() || m_contextStopped); 111 ASSERT(m_requestList.isEmpty() || m_contextStopped);
112 } 112 }
113 113
114 DEFINE_TRACE(IDBTransaction) 114 DEFINE_TRACE(IDBTransaction)
115 { 115 {
116 visitor->trace(m_database); 116 visitor->trace(m_database);
117 visitor->trace(m_openDBRequest); 117 visitor->trace(m_openDBRequest);
118 visitor->trace(m_error); 118 visitor->trace(m_error);
119 visitor->trace(m_requestList); 119 visitor->trace(m_requestList);
120 visitor->trace(m_objectStoreMap); 120 visitor->trace(m_objectStoreMap);
121 visitor->trace(m_createdObjectStores);
122 visitor->trace(m_deletedObjectStores); 121 visitor->trace(m_deletedObjectStores);
123 visitor->trace(m_objectStoreCleanupMap);
124 EventTargetWithInlineData::trace(visitor); 122 EventTargetWithInlineData::trace(visitor);
125 ActiveDOMObject::trace(visitor); 123 ActiveDOMObject::trace(visitor);
126 } 124 }
127 125
128 void IDBTransaction::setError(DOMException* error) 126 void IDBTransaction::setError(DOMException* error)
129 { 127 {
130 ASSERT(m_state != Finished); 128 ASSERT(m_state != Finished);
131 ASSERT(error); 129 ASSERT(error);
132 130
133 // The first error to be set is the true cause of the 131 // The first error to be set is the true cause of the
(...skipping 22 matching lines...) Expand all
156 int64_t objectStoreId = m_database->findObjectStoreId(name); 154 int64_t objectStoreId = m_database->findObjectStoreId(name);
157 if (objectStoreId == IDBObjectStoreMetadata::InvalidId) { 155 if (objectStoreId == IDBObjectStoreMetadata::InvalidId) {
158 ASSERT(isVersionChange()); 156 ASSERT(isVersionChange());
159 exceptionState.throwDOMException(NotFoundError, IDBDatabase::noSuchObjec tStoreErrorMessage); 157 exceptionState.throwDOMException(NotFoundError, IDBDatabase::noSuchObjec tStoreErrorMessage);
160 return nullptr; 158 return nullptr;
161 } 159 }
162 160
163 const IDBDatabaseMetadata& metadata = m_database->metadata(); 161 const IDBDatabaseMetadata& metadata = m_database->metadata();
164 162
165 IDBObjectStore* objectStore = IDBObjectStore::create(metadata.objectStores.g et(objectStoreId), this); 163 IDBObjectStore* objectStore = IDBObjectStore::create(metadata.objectStores.g et(objectStoreId), this);
164 DCHECK(!m_objectStoreMap.contains(name));
166 m_objectStoreMap.set(name, objectStore); 165 m_objectStoreMap.set(name, objectStore);
167 m_objectStoreCleanupMap.set(objectStore, objectStore->metadata());
168 return objectStore; 166 return objectStore;
169 } 167 }
170 168
171 void IDBTransaction::objectStoreCreated(const String& name, IDBObjectStore* obje ctStore) 169 void IDBTransaction::objectStoreCreated(const String& name, IDBObjectStore* obje ctStore)
172 { 170 {
173 ASSERT(m_state != Finished); 171 DCHECK(m_state != Finished);
174 ASSERT(isVersionChange()); 172 DCHECK(isVersionChange());
173 DCHECK(!m_objectStoreMap.contains(name));
175 m_objectStoreMap.set(name, objectStore); 174 m_objectStoreMap.set(name, objectStore);
176 m_objectStoreCleanupMap.set(objectStore, objectStore->metadata());
177 m_createdObjectStores.add(objectStore);
178 } 175 }
179 176
180 void IDBTransaction::objectStoreDeleted(const String& name) 177 void IDBTransaction::objectStoreDeleted(const String& name)
181 { 178 {
182 ASSERT(m_state != Finished); 179 ASSERT(m_state != Finished);
183 ASSERT(isVersionChange()); 180 ASSERT(isVersionChange());
184 IDBObjectStoreMap::iterator it = m_objectStoreMap.find(name); 181 IDBObjectStoreMap::iterator it = m_objectStoreMap.find(name);
185 if (it != m_objectStoreMap.end()) { 182 if (it != m_objectStoreMap.end()) {
186 IDBObjectStore* objectStore = it->value; 183 IDBObjectStore* objectStore = it->value;
187 m_objectStoreMap.remove(name); 184 m_objectStoreMap.remove(name);
188 objectStore->markDeleted(); 185 objectStore->markDeleted();
189 m_objectStoreCleanupMap.set(objectStore, objectStore->metadata());
190 m_deletedObjectStores.add(objectStore); 186 m_deletedObjectStores.add(objectStore);
191 } 187 }
192 } 188 }
193 189
194 void IDBTransaction::setActive(bool active) 190 void IDBTransaction::setActive(bool active)
195 { 191 {
196 DCHECK_NE(m_state, Finished) << "A finished transaction tried to setActive(" << (active ? "true" : "false") << ")"; 192 DCHECK_NE(m_state, Finished) << "A finished transaction tried to setActive(" << (active ? "true" : "false") << ")";
197 if (m_state == Finishing) 193 if (m_state == Finishing)
198 return; 194 return;
199 ASSERT(active != (m_state == Active)); 195 ASSERT(active != (m_state == Active));
(...skipping 12 matching lines...) Expand all
212 208
213 m_state = Finishing; 209 m_state = Finishing;
214 210
215 if (m_contextStopped) 211 if (m_contextStopped)
216 return; 212 return;
217 213
218 for (IDBRequest* request : m_requestList) 214 for (IDBRequest* request : m_requestList)
219 request->abort(); 215 request->abort();
220 m_requestList.clear(); 216 m_requestList.clear();
221 217
222 for (IDBObjectStore* store : m_createdObjectStores) { 218 if (isVersionChange()) {
223 store->abort(); 219 // Marking created object stores as deleted.
224 store->markDeleted(); 220 for (auto storeMapIterator : m_objectStoreMap) {
221 IDBObjectStore* store = storeMapIterator.value;
222 auto it = m_previousMetadata.objectStores.find(store->id());
223 if (it == m_previousMetadata.objectStores.end()) {
224 store->versionChangeTransactionAborted();
225 store->markDeleted();
226 }
227 }
225 } 228 }
226 229
227 if (backendDB()) 230 if (backendDB())
228 backendDB()->abort(m_id); 231 backendDB()->abort(m_id);
229 } 232 }
230 233
231 void IDBTransaction::registerRequest(IDBRequest* request) 234 void IDBTransaction::registerRequest(IDBRequest* request)
232 { 235 {
233 ASSERT(request); 236 ASSERT(request);
234 ASSERT(m_state == Active); 237 ASSERT(m_state == Active);
(...skipping 19 matching lines...) Expand all
254 if (m_state != Finishing) { 257 if (m_state != Finishing) {
255 // Abort was not triggered by front-end. 258 // Abort was not triggered by front-end.
256 ASSERT(error); 259 ASSERT(error);
257 setError(error); 260 setError(error);
258 261
259 // Outstanding requests must be aborted. 262 // Outstanding requests must be aborted.
260 for (IDBRequest* request : m_requestList) 263 for (IDBRequest* request : m_requestList)
261 request->abort(); 264 request->abort();
262 m_requestList.clear(); 265 m_requestList.clear();
263 266
264 // Newly created stores must be marked as deleted. 267 if (isVersionChange()) {
265 for (IDBObjectStore* store : m_createdObjectStores) 268 for (IDBObjectStore* store : m_deletedObjectStores) {
266 store->markDeleted(); 269 if (!m_previousMetadata.objectStores.contains(store->id()))
270 store->markDeleted();
271 store->versionChangeTransactionAborted();
272 }
267 273
268 // Used stores may need to mark indexes as deleted. 274 for (const auto& storeMapIterator : m_objectStoreMap) {
269 for (auto& it : m_objectStoreCleanupMap) 275 IDBObjectStore* store = storeMapIterator.value;
270 it.key->abort(); 276
277 // Newly created stores must be marked as deleted.
278 if (!m_previousMetadata.objectStores.contains(store->id()))
279 store->markDeleted();
280
281 // Modified stores may need to mark indexes as deleted.
282 store->versionChangeTransactionAborted();
283 }
284 }
271 285
272 m_state = Finishing; 286 m_state = Finishing;
273 } 287 }
274 288
275 if (isVersionChange()) { 289 if (isVersionChange()) {
276 for (auto& it : m_objectStoreCleanupMap) 290 for (IDBObjectStore* store : m_deletedObjectStores) {
277 it.key->setMetadata(it.value); 291 const auto& it = m_previousMetadata.objectStores.find(store->id());
292 if (it != m_previousMetadata.objectStores.end())
293 store->rollbackMetadata(it->value);
294 }
295 for (const auto& storeMapIterator : m_objectStoreMap) {
296 IDBObjectStore* store = storeMapIterator.value;
297 const auto& it = m_previousMetadata.objectStores.find(store->id());
298 if (it != m_previousMetadata.objectStores.end())
299 store->rollbackMetadata(it->value);
300 }
278 m_database->setMetadata(m_previousMetadata); 301 m_database->setMetadata(m_previousMetadata);
279 m_database->close(); 302 m_database->close();
280 } 303 }
281 m_objectStoreCleanupMap.clear();
282 304
283 // Enqueue events before notifying database, as database may close which enq ueues more events and order matters. 305 // Enqueue events before notifying database, as database may close which enq ueues more events and order matters.
284 enqueueEvent(Event::createBubble(EventTypeNames::abort)); 306 enqueueEvent(Event::createBubble(EventTypeNames::abort));
285 307
286 m_database->transactionFinished(this); 308 m_database->transactionFinished(this);
287 } 309 }
288 310
289 void IDBTransaction::onComplete() 311 void IDBTransaction::onComplete()
290 { 312 {
291 IDB_TRACE("IDBTransaction::onComplete"); 313 IDB_TRACE("IDBTransaction::onComplete");
292 if (m_contextStopped) { 314 if (m_contextStopped) {
293 m_database->transactionFinished(this); 315 m_database->transactionFinished(this);
294 return; 316 return;
295 } 317 }
296 318
297 ASSERT(m_state != Finished); 319 ASSERT(m_state != Finished);
298 m_state = Finishing; 320 m_state = Finishing;
299 m_objectStoreCleanupMap.clear();
300 321
301 // Enqueue events before notifying database, as database may close which enq ueues more events and order matters. 322 // Enqueue events before notifying database, as database may close which enq ueues more events and order matters.
302 enqueueEvent(Event::create(EventTypeNames::complete)); 323 enqueueEvent(Event::create(EventTypeNames::complete));
303 324
304 m_database->transactionFinished(this); 325 m_database->transactionFinished(this);
305 } 326 }
306 327
307 bool IDBTransaction::hasPendingActivity() const 328 bool IDBTransaction::hasPendingActivity() const
308 { 329 {
309 // FIXME: In an ideal world, we should return true as long as anyone has a o r can 330 // FIXME: In an ideal world, we should return true as long as anyone has a o r can
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after
376 ASSERT(event->target() == this); 397 ASSERT(event->target() == this);
377 m_state = Finished; 398 m_state = Finished;
378 399
379 // Break reference cycles. 400 // Break reference cycles.
380 // TODO(jsbell): This can be removed c/o Oilpan. 401 // TODO(jsbell): This can be removed c/o Oilpan.
381 for (auto& it : m_objectStoreMap) 402 for (auto& it : m_objectStoreMap)
382 it.value->transactionFinished(); 403 it.value->transactionFinished();
383 m_objectStoreMap.clear(); 404 m_objectStoreMap.clear();
384 for (auto& it : m_deletedObjectStores) 405 for (auto& it : m_deletedObjectStores)
385 it->transactionFinished(); 406 it->transactionFinished();
386 m_createdObjectStores.clear();
387 m_deletedObjectStores.clear(); 407 m_deletedObjectStores.clear();
388 408
389 HeapVector<Member<EventTarget>> targets; 409 HeapVector<Member<EventTarget>> targets;
390 targets.append(this); 410 targets.append(this);
391 targets.append(db()); 411 targets.append(db());
392 412
393 // FIXME: When we allow custom event dispatching, this will probably need to change. 413 // FIXME: When we allow custom event dispatching, this will probably need to change.
394 ASSERT(event->type() == EventTypeNames::complete || event->type() == EventTy peNames::abort); 414 ASSERT(event->type() == EventTypeNames::complete || event->type() == EventTy peNames::abort);
395 DispatchEventResult dispatchResult = IDBEventDispatcher::dispatch(event, tar gets); 415 DispatchEventResult dispatchResult = IDBEventDispatcher::dispatch(event, tar gets);
396 // FIXME: Try to construct a test where |this| outlives openDBRequest and we 416 // FIXME: Try to construct a test where |this| outlives openDBRequest and we
(...skipping 26 matching lines...) Expand all
423 event->setTarget(this); 443 event->setTarget(this);
424 eventQueue->enqueueEvent(event); 444 eventQueue->enqueueEvent(event);
425 } 445 }
426 446
427 WebIDBDatabase* IDBTransaction::backendDB() const 447 WebIDBDatabase* IDBTransaction::backendDB() const
428 { 448 {
429 return m_database->backend(); 449 return m_database->backend();
430 } 450 }
431 451
432 } // namespace blink 452 } // namespace blink
OLDNEW
« no previous file with comments | « third_party/WebKit/Source/modules/indexeddb/IDBTransaction.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698