void DOMStorageDBThread::PendingOperations::Add(DOMStorageDBThread::DBOperation* aOperation) { // Optimize: when a key to remove has never been written to disk // just bypass this operation. A kew is new when an operation scheduled // to write it to the database is of type opAddItem. if (CheckForCoalesceOpportunity(aOperation, DBOperation::opAddItem, DBOperation::opRemoveItem)) { mUpdates.Remove(aOperation->Target()); delete aOperation; return; } // Optimize: when changing a key that is new and has never been // written to disk, keep type of the operation to store it at opAddItem. // This allows optimization to just forget adding a new key when // it is removed from the storage before flush. if (CheckForCoalesceOpportunity(aOperation, DBOperation::opAddItem, DBOperation::opUpdateItem)) { aOperation->mType = DBOperation::opAddItem; } // Optimize: to prevent lose of remove operation on a key when doing // remove/set/remove on a previously existing key we have to change // opAddItem to opUpdateItem on the new operation when there is opRemoveItem // pending for the key. if (CheckForCoalesceOpportunity(aOperation, DBOperation::opRemoveItem, DBOperation::opAddItem)) { aOperation->mType = DBOperation::opUpdateItem; } switch (aOperation->Type()) { // Operations on single keys case DBOperation::opAddItem: case DBOperation::opUpdateItem: case DBOperation::opRemoveItem: // Override any existing operation for the target (=scope+key). mUpdates.Put(aOperation->Target(), aOperation); break; // Clear operations case DBOperation::opClear: case DBOperation::opClearMatchingScope: // Drop all update (insert/remove) operations for equivavelent or matching scope. // We do this as an optimization as well as a must based on the logic, // if we would not delete the update tasks, changes would have been stored // to the database after clear operations have been executed. mUpdates.Enumerate(ForgetUpdatesForScope, aOperation); mClears.Put(aOperation->Target(), aOperation); break; case DBOperation::opClearAll: // Drop simply everything, this is a super-operation. mUpdates.Clear(); mClears.Clear(); mClears.Put(aOperation->Target(), aOperation); break; default: MOZ_ASSERT(false); break; } }
void StorageDBThread::PendingOperations::Add(StorageDBThread::DBOperation* aOperation) { // Optimize: when a key to remove has never been written to disk // just bypass this operation. A key is new when an operation scheduled // to write it to the database is of type opAddItem. if (CheckForCoalesceOpportunity(aOperation, DBOperation::opAddItem, DBOperation::opRemoveItem)) { mUpdates.Remove(aOperation->Target()); delete aOperation; return; } // Optimize: when changing a key that is new and has never been // written to disk, keep type of the operation to store it at opAddItem. // This allows optimization to just forget adding a new key when // it is removed from the storage before flush. if (CheckForCoalesceOpportunity(aOperation, DBOperation::opAddItem, DBOperation::opUpdateItem)) { aOperation->mType = DBOperation::opAddItem; } // Optimize: to prevent lose of remove operation on a key when doing // remove/set/remove on a previously existing key we have to change // opAddItem to opUpdateItem on the new operation when there is opRemoveItem // pending for the key. if (CheckForCoalesceOpportunity(aOperation, DBOperation::opRemoveItem, DBOperation::opAddItem)) { aOperation->mType = DBOperation::opUpdateItem; } switch (aOperation->Type()) { // Operations on single keys case DBOperation::opAddItem: case DBOperation::opUpdateItem: case DBOperation::opRemoveItem: // Override any existing operation for the target (=scope+key). mUpdates.Put(aOperation->Target(), aOperation); break; // Clear operations case DBOperation::opClear: case DBOperation::opClearMatchingOrigin: case DBOperation::opClearMatchingOriginAttributes: // Drop all update (insert/remove) operations for equivavelent or matching // scope. We do this as an optimization as well as a must based on the // logic, if we would not delete the update tasks, changes would have been // stored to the database after clear operations have been executed. for (auto iter = mUpdates.Iter(); !iter.Done(); iter.Next()) { nsAutoPtr<DBOperation>& pendingTask = iter.Data(); if (aOperation->Type() == DBOperation::opClear && (pendingTask->OriginNoSuffix() != aOperation->OriginNoSuffix() || pendingTask->OriginSuffix() != aOperation->OriginSuffix())) { continue; } if (aOperation->Type() == DBOperation::opClearMatchingOrigin && !StringBeginsWith(pendingTask->OriginNoSuffix(), aOperation->Origin())) { continue; } if (aOperation->Type() == DBOperation::opClearMatchingOriginAttributes && !OriginPatternMatches(pendingTask->OriginSuffix(), aOperation->OriginPattern())) { continue; } iter.Remove(); } mClears.Put(aOperation->Target(), aOperation); break; case DBOperation::opClearAll: // Drop simply everything, this is a super-operation. mUpdates.Clear(); mClears.Clear(); mClears.Put(aOperation->Target(), aOperation); break; default: MOZ_ASSERT(false); break; } }