18e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project/* 2e458d70a0d18538346f41b503114c9ebe6b2ce12Leon Clarke * Copyright (C) 2008, 2009, 2010 Apple Inc. All Rights Reserved. 38e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * 48e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * Redistribution and use in source and binary forms, with or without 58e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * modification, are permitted provided that the following conditions 68e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * are met: 78e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * 1. Redistributions of source code must retain the above copyright 88e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * notice, this list of conditions and the following disclaimer. 98e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * 2. Redistributions in binary form must reproduce the above copyright 108e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * notice, this list of conditions and the following disclaimer in the 118e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * documentation and/or other materials provided with the distribution. 128e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * 138e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY 148e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 158e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 168e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR 178e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 188e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 198e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 208e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 218e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 228e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 23231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 248e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project */ 258e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 268e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "config.h" 270bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch#include "StorageAreaSync.h" 288e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 29b679b2a6c810dd2f9e8d7072e542b884a4e7060fBen Murdoch#if ENABLE(DOM_STORAGE) 30b679b2a6c810dd2f9e8d7072e542b884a4e7060fBen Murdoch 318e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "EventNames.h" 32545e470e52f0ac6a3a072bf559c796b42c6066b6Ben Murdoch#include "FileSystem.h" 335f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian#include "HTMLElement.h" 3406ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen#include "SQLiteFileSystem.h" 358e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "SQLiteStatement.h" 3606ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen#include "SecurityOrigin.h" 370bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch#include "StorageAreaImpl.h" 380bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch#include "StorageSyncManager.h" 392bde8e466a4451c7319e3a072d118917957d6554Steve Block#include "StorageTracker.h" 405f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian#include "SuddenTermination.h" 41dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block#include <wtf/text/CString.h> 428e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 438e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectnamespace WebCore { 448e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 450bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch// If the StorageArea undergoes rapid changes, don't sync each change to disk. 468e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project// Instead, queue up a batch of items to sync and actually do the sync at the following interval. 470bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdochstatic const double StorageSyncInterval = 1.0; 488e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 49dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block// A sane limit on how many items we'll schedule to sync all at once. This makes it 50dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block// much harder to starve the rest of LocalStorage and the OS's IO subsystem in general. 51dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blockstatic const int MaxiumItemsToSync = 100; 52dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block 53e458d70a0d18538346f41b503114c9ebe6b2ce12Leon Clarkeinline StorageAreaSync::StorageAreaSync(PassRefPtr<StorageSyncManager> storageSyncManager, PassRefPtr<StorageAreaImpl> storageArea, const String& databaseIdentifier) 540bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch : m_syncTimer(this, &StorageAreaSync::syncTimerFired) 558e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project , m_itemsCleared(false) 568e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project , m_finalSyncScheduled(false) 570bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch , m_storageArea(storageArea) 580bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch , m_syncManager(storageSyncManager) 59643ca7872b450ea4efacab6188849e5aac2ba161Steve Block , m_databaseIdentifier(databaseIdentifier.crossThreadString()) 608e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project , m_clearItemsWhileSyncing(false) 618e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project , m_syncScheduled(false) 62dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block , m_syncInProgress(false) 63545e470e52f0ac6a3a072bf559c796b42c6066b6Ben Murdoch , m_databaseOpenFailed(false) 642bde8e466a4451c7319e3a072d118917957d6554Steve Block , m_syncCloseDatabase(false) 658e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project , m_importComplete(false) 668e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 67231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block ASSERT(isMainThread()); 680bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch ASSERT(m_storageArea); 690bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch ASSERT(m_syncManager); 70e458d70a0d18538346f41b503114c9ebe6b2ce12Leon Clarke} 71e458d70a0d18538346f41b503114c9ebe6b2ce12Leon Clarke 72e458d70a0d18538346f41b503114c9ebe6b2ce12Leon ClarkePassRefPtr<StorageAreaSync> StorageAreaSync::create(PassRefPtr<StorageSyncManager> storageSyncManager, PassRefPtr<StorageAreaImpl> storageArea, const String& databaseIdentifier) 73e458d70a0d18538346f41b503114c9ebe6b2ce12Leon Clarke{ 74e458d70a0d18538346f41b503114c9ebe6b2ce12Leon Clarke RefPtr<StorageAreaSync> area = adoptRef(new StorageAreaSync(storageSyncManager, storageArea, databaseIdentifier)); 750bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 760bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch // FIXME: If it can't import, then the default WebKit behavior should be that of private browsing, 77e458d70a0d18538346f41b503114c9ebe6b2ce12Leon Clarke // not silently ignoring it. https://bugs.webkit.org/show_bug.cgi?id=25894 78e458d70a0d18538346f41b503114c9ebe6b2ce12Leon Clarke if (!area->m_syncManager->scheduleImport(area.get())) 79e458d70a0d18538346f41b503114c9ebe6b2ce12Leon Clarke area->m_importComplete = true; 80e458d70a0d18538346f41b503114c9ebe6b2ce12Leon Clarke 81e458d70a0d18538346f41b503114c9ebe6b2ce12Leon Clarke return area.release(); 828e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 838e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 840bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben MurdochStorageAreaSync::~StorageAreaSync() 858e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 86231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block ASSERT(isMainThread()); 878e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project ASSERT(!m_syncTimer.isActive()); 88643ca7872b450ea4efacab6188849e5aac2ba161Steve Block ASSERT(m_finalSyncScheduled); 898e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 908e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 910bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdochvoid StorageAreaSync::scheduleFinalSync() 928e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 930bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch ASSERT(isMainThread()); 940bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch // FIXME: We do this to avoid races, but it'd be better to make things safe without blocking. 950bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch blockUntilImportComplete(); 96643ca7872b450ea4efacab6188849e5aac2ba161Steve Block m_storageArea = 0; // This is done in blockUntilImportComplete() but this is here as a form of documentation that we must be absolutely sure the ref count cycle is broken. 97231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block 985f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian if (m_syncTimer.isActive()) 995f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian m_syncTimer.stop(); 1005f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian else { 1015f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian // The following is balanced by the call to enableSuddenTermination in the 1025f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian // syncTimerFired function. 1035f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian disableSuddenTermination(); 1045f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian } 1050bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch // FIXME: This is synchronous. We should do it on the background process, but 1060bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch // we should do it safely. 1078e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_finalSyncScheduled = true; 108dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block syncTimerFired(&m_syncTimer); 10906ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen m_syncManager->scheduleDeleteEmptyDatabase(this); 1108e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 1118e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 1120bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdochvoid StorageAreaSync::scheduleItemForSync(const String& key, const String& value) 1138e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 1148e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project ASSERT(isMainThread()); 1158e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project ASSERT(!m_finalSyncScheduled); 1168e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 1178e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_changedItems.set(key, value); 1185f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian if (!m_syncTimer.isActive()) { 1190bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch m_syncTimer.startOneShot(StorageSyncInterval); 1205f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian 1215f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian // The following is balanced by the call to enableSuddenTermination in the 1225f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian // syncTimerFired function. 1235f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian disableSuddenTermination(); 1245f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian } 1258e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 1268e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 1270bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdochvoid StorageAreaSync::scheduleClear() 1288e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 1298e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project ASSERT(isMainThread()); 1308e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project ASSERT(!m_finalSyncScheduled); 1318e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 1328e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_changedItems.clear(); 1338e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_itemsCleared = true; 1345f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian if (!m_syncTimer.isActive()) { 1350bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch m_syncTimer.startOneShot(StorageSyncInterval); 1365f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian 1375f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian // The following is balanced by the call to enableSuddenTermination in the 1385f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian // syncTimerFired function. 1395f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian disableSuddenTermination(); 1405f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian } 1418e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 1428e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 1432bde8e466a4451c7319e3a072d118917957d6554Steve Blockvoid StorageAreaSync::scheduleCloseDatabase() 1442bde8e466a4451c7319e3a072d118917957d6554Steve Block{ 1452bde8e466a4451c7319e3a072d118917957d6554Steve Block ASSERT(isMainThread()); 1462bde8e466a4451c7319e3a072d118917957d6554Steve Block ASSERT(!m_finalSyncScheduled); 1472bde8e466a4451c7319e3a072d118917957d6554Steve Block 1482bde8e466a4451c7319e3a072d118917957d6554Steve Block if (!m_database.isOpen()) 1492bde8e466a4451c7319e3a072d118917957d6554Steve Block return; 1502bde8e466a4451c7319e3a072d118917957d6554Steve Block 1512bde8e466a4451c7319e3a072d118917957d6554Steve Block m_syncCloseDatabase = true; 1522bde8e466a4451c7319e3a072d118917957d6554Steve Block 1532bde8e466a4451c7319e3a072d118917957d6554Steve Block if (!m_syncTimer.isActive()) { 1542bde8e466a4451c7319e3a072d118917957d6554Steve Block m_syncTimer.startOneShot(StorageSyncInterval); 1552bde8e466a4451c7319e3a072d118917957d6554Steve Block 1562bde8e466a4451c7319e3a072d118917957d6554Steve Block // The following is balanced by the call to enableSuddenTermination in the 1572bde8e466a4451c7319e3a072d118917957d6554Steve Block // syncTimerFired function. 1582bde8e466a4451c7319e3a072d118917957d6554Steve Block disableSuddenTermination(); 1592bde8e466a4451c7319e3a072d118917957d6554Steve Block } 1602bde8e466a4451c7319e3a072d118917957d6554Steve Block} 1612bde8e466a4451c7319e3a072d118917957d6554Steve Block 1620bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdochvoid StorageAreaSync::syncTimerFired(Timer<StorageAreaSync>*) 1638e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 1648e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project ASSERT(isMainThread()); 1658e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 166dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block bool partialSync = false; 1678e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project { 1688e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project MutexLocker locker(m_syncLock); 1698e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 170dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block // Do not schedule another sync if we're still trying to complete the 171dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block // previous one. But, if we're shutting down, schedule it anyway. 172dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block if (m_syncInProgress && !m_finalSyncScheduled) { 173dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block ASSERT(!m_syncTimer.isActive()); 174dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block m_syncTimer.startOneShot(StorageSyncInterval); 175dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block return; 176dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block } 177dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block 1788e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (m_itemsCleared) { 1798e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_itemsPendingSync.clear(); 1808e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_clearItemsWhileSyncing = true; 1818e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_itemsCleared = false; 1828e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 1838e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 184dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block HashMap<String, String>::iterator changed_it = m_changedItems.begin(); 185dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block HashMap<String, String>::iterator changed_end = m_changedItems.end(); 186dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block for (int count = 0; changed_it != changed_end; ++count, ++changed_it) { 187dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block if (count >= MaxiumItemsToSync && !m_finalSyncScheduled) { 188dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block partialSync = true; 189dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block break; 190dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block } 191dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block m_itemsPendingSync.set(changed_it->first.crossThreadString(), changed_it->second.crossThreadString()); 192dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block } 193dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block 194dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block if (partialSync) { 195dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block // We can't do the fast path of simply clearing all items, so we'll need to manually 196dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block // remove them one by one. Done under lock since m_itemsPendingSync is modified by 197dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block // the background thread. 198dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block HashMap<String, String>::iterator pending_it = m_itemsPendingSync.begin(); 199dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block HashMap<String, String>::iterator pending_end = m_itemsPendingSync.end(); 200dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block for (; pending_it != pending_end; ++pending_it) 201dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block m_changedItems.remove(pending_it->first); 202dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block } 2038e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 2048e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (!m_syncScheduled) { 2058e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_syncScheduled = true; 2065f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian 2075f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian // The following is balanced by the call to enableSuddenTermination in the 2085f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian // performSync function. 2095f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian disableSuddenTermination(); 2105f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian 2110bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch m_syncManager->scheduleSync(this); 2128e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 2138e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 2148e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 215dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block if (partialSync) { 216dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block // If we didn't finish syncing, then we need to finish the job later. 217dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block ASSERT(!m_syncTimer.isActive()); 218dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block m_syncTimer.startOneShot(StorageSyncInterval); 219dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block } else { 220dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block // The following is balanced by the calls to disableSuddenTermination in the 221dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block // scheduleItemForSync, scheduleClear, and scheduleFinalSync functions. 222dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block enableSuddenTermination(); 2235f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian 224dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block m_changedItems.clear(); 225dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block } 2268e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 2278e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 228545e470e52f0ac6a3a072bf559c796b42c6066b6Ben Murdochvoid StorageAreaSync::openDatabase(OpenDatabaseParamType openingStrategy) 2298e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 2308e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project ASSERT(!isMainThread()); 2318e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project ASSERT(!m_database.isOpen()); 232545e470e52f0ac6a3a072bf559c796b42c6066b6Ben Murdoch ASSERT(!m_databaseOpenFailed); 2338e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 234643ca7872b450ea4efacab6188849e5aac2ba161Steve Block String databaseFilename = m_syncManager->fullDatabaseFilename(m_databaseIdentifier); 2350bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 236545e470e52f0ac6a3a072bf559c796b42c6066b6Ben Murdoch if (!fileExists(databaseFilename) && openingStrategy == SkipIfNonExistent) 237545e470e52f0ac6a3a072bf559c796b42c6066b6Ben Murdoch return; 238545e470e52f0ac6a3a072bf559c796b42c6066b6Ben Murdoch 2398e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (databaseFilename.isEmpty()) { 2408e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project LOG_ERROR("Filename for local storage database is empty - cannot open for persistent storage"); 2418e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project markImported(); 242545e470e52f0ac6a3a072bf559c796b42c6066b6Ben Murdoch m_databaseOpenFailed = true; 2438e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return; 2448e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 2458e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 2462bde8e466a4451c7319e3a072d118917957d6554Steve Block // A StorageTracker thread may have been scheduled to delete the db we're 2472bde8e466a4451c7319e3a072d118917957d6554Steve Block // reopening, so cancel possible deletion. 2482bde8e466a4451c7319e3a072d118917957d6554Steve Block StorageTracker::tracker().cancelDeletingOrigin(m_databaseIdentifier); 2492bde8e466a4451c7319e3a072d118917957d6554Steve Block 2508e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (!m_database.open(databaseFilename)) { 2518e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project LOG_ERROR("Failed to open database file %s for local storage", databaseFilename.utf8().data()); 2528e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project markImported(); 253545e470e52f0ac6a3a072bf559c796b42c6066b6Ben Murdoch m_databaseOpenFailed = true; 2548e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return; 2558e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 2568e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 2578e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (!m_database.executeCommand("CREATE TABLE IF NOT EXISTS ItemTable (key TEXT UNIQUE ON CONFLICT REPLACE, value TEXT NOT NULL ON CONFLICT FAIL)")) { 2588e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project LOG_ERROR("Failed to create table ItemTable for local storage"); 2598e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project markImported(); 260545e470e52f0ac6a3a072bf559c796b42c6066b6Ben Murdoch m_databaseOpenFailed = true; 261545e470e52f0ac6a3a072bf559c796b42c6066b6Ben Murdoch return; 262545e470e52f0ac6a3a072bf559c796b42c6066b6Ben Murdoch } 2632bde8e466a4451c7319e3a072d118917957d6554Steve Block 2642bde8e466a4451c7319e3a072d118917957d6554Steve Block StorageTracker::tracker().setOriginDetails(m_databaseIdentifier, databaseFilename); 265545e470e52f0ac6a3a072bf559c796b42c6066b6Ben Murdoch} 266545e470e52f0ac6a3a072bf559c796b42c6066b6Ben Murdoch 267545e470e52f0ac6a3a072bf559c796b42c6066b6Ben Murdochvoid StorageAreaSync::performImport() 268545e470e52f0ac6a3a072bf559c796b42c6066b6Ben Murdoch{ 269545e470e52f0ac6a3a072bf559c796b42c6066b6Ben Murdoch ASSERT(!isMainThread()); 270545e470e52f0ac6a3a072bf559c796b42c6066b6Ben Murdoch ASSERT(!m_database.isOpen()); 271545e470e52f0ac6a3a072bf559c796b42c6066b6Ben Murdoch 272545e470e52f0ac6a3a072bf559c796b42c6066b6Ben Murdoch openDatabase(SkipIfNonExistent); 273545e470e52f0ac6a3a072bf559c796b42c6066b6Ben Murdoch if (!m_database.isOpen()) { 274545e470e52f0ac6a3a072bf559c796b42c6066b6Ben Murdoch markImported(); 2758e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return; 2768e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 277231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block 2788e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project SQLiteStatement query(m_database, "SELECT key, value FROM ItemTable"); 2798e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (query.prepare() != SQLResultOk) { 2808e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project LOG_ERROR("Unable to select items from ItemTable for local storage"); 2818e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project markImported(); 2828e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return; 2838e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 284231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block 2858e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project HashMap<String, String> itemMap; 2868e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 2878e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project int result = query.step(); 2888e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project while (result == SQLResultRow) { 2898e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project itemMap.set(query.getColumnText(0), query.getColumnText(1)); 2908e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project result = query.step(); 2918e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 2928e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 2938e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (result != SQLResultDone) { 2948e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project LOG_ERROR("Error reading items from ItemTable for local storage"); 2958e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project markImported(); 2968e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return; 2978e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 2988e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 2998e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project HashMap<String, String>::iterator it = itemMap.begin(); 3008e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project HashMap<String, String>::iterator end = itemMap.end(); 301231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block 3028e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project for (; it != end; ++it) 3030bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch m_storageArea->importItem(it->first, it->second); 304231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block 305643ca7872b450ea4efacab6188849e5aac2ba161Steve Block markImported(); 3068e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 3078e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 3080bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdochvoid StorageAreaSync::markImported() 3098e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 3108e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project MutexLocker locker(m_importLock); 3118e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_importComplete = true; 3128e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_importCondition.signal(); 3138e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 3148e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 3150bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch// FIXME: In the future, we should allow use of StorageAreas while it's importing (when safe to do so). 3160bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch// Blocking everything until the import is complete is by far the simplest and safest thing to do, but 3170bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch// there is certainly room for safe optimization: Key/length will never be able to make use of such an 3180bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch// optimization (since the order of iteration can change as items are being added). Get can return any 3190bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch// item currently in the map. Get/remove can work whether or not it's in the map, but we'll need a list 3200bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch// of items the import should not overwrite. Clear can also work, but it'll need to kill the import 3210bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch// job first. 322643ca7872b450ea4efacab6188849e5aac2ba161Steve Blockvoid StorageAreaSync::blockUntilImportComplete() 3230bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch{ 3240bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch ASSERT(isMainThread()); 3250bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 326643ca7872b450ea4efacab6188849e5aac2ba161Steve Block // Fast path. We set m_storageArea to 0 only after m_importComplete being true. 327643ca7872b450ea4efacab6188849e5aac2ba161Steve Block if (!m_storageArea) 3280bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch return; 3290bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 3300bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch MutexLocker locker(m_importLock); 3310bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch while (!m_importComplete) 3320bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch m_importCondition.wait(m_importLock); 333643ca7872b450ea4efacab6188849e5aac2ba161Steve Block m_storageArea = 0; 3340bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch} 3350bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 3360bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdochvoid StorageAreaSync::sync(bool clearItems, const HashMap<String, String>& items) 3378e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 3388e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project ASSERT(!isMainThread()); 3398e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 34006ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen if (items.isEmpty() && !clearItems) 34106ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen return; 342545e470e52f0ac6a3a072bf559c796b42c6066b6Ben Murdoch if (m_databaseOpenFailed) 343545e470e52f0ac6a3a072bf559c796b42c6066b6Ben Murdoch return; 344545e470e52f0ac6a3a072bf559c796b42c6066b6Ben Murdoch if (!m_database.isOpen()) 345545e470e52f0ac6a3a072bf559c796b42c6066b6Ben Murdoch openDatabase(CreateIfNonExistent); 3468e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (!m_database.isOpen()) 3478e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return; 3488e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 3492bde8e466a4451c7319e3a072d118917957d6554Steve Block // Closing this db because it is about to be deleted by StorageTracker. 3502bde8e466a4451c7319e3a072d118917957d6554Steve Block // The delete will be cancelled if StorageAreaSync needs to reopen the db 3512bde8e466a4451c7319e3a072d118917957d6554Steve Block // to write new items created after the request to delete the db. 3522bde8e466a4451c7319e3a072d118917957d6554Steve Block if (m_syncCloseDatabase) { 3532bde8e466a4451c7319e3a072d118917957d6554Steve Block m_syncCloseDatabase = false; 3542bde8e466a4451c7319e3a072d118917957d6554Steve Block m_database.close(); 3552bde8e466a4451c7319e3a072d118917957d6554Steve Block return; 3562bde8e466a4451c7319e3a072d118917957d6554Steve Block } 3572bde8e466a4451c7319e3a072d118917957d6554Steve Block 3585f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian // If the clear flag is set, then we clear all items out before we write any new ones in. 3595f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian if (clearItems) { 3608e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project SQLiteStatement clear(m_database, "DELETE FROM ItemTable"); 3618e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (clear.prepare() != SQLResultOk) { 3628e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project LOG_ERROR("Failed to prepare clear statement - cannot write to local storage database"); 3638e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return; 3648e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 365231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block 3668e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project int result = clear.step(); 3678e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (result != SQLResultDone) { 3688e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project LOG_ERROR("Failed to clear all items in the local storage database - %i", result); 3698e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return; 3708e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 3718e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 3728e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 3738e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project SQLiteStatement insert(m_database, "INSERT INTO ItemTable VALUES (?, ?)"); 3748e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (insert.prepare() != SQLResultOk) { 3758e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project LOG_ERROR("Failed to prepare insert statement - cannot write to local storage database"); 3768e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return; 3778e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 3788e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 3798e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project SQLiteStatement remove(m_database, "DELETE FROM ItemTable WHERE key=?"); 3808e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (remove.prepare() != SQLResultOk) { 3818e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project LOG_ERROR("Failed to prepare delete statement - cannot write to local storage database"); 3828e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return; 3838e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 3848e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 3855f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian HashMap<String, String>::const_iterator end = items.end(); 3868e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 3875f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian for (HashMap<String, String>::const_iterator it = items.begin(); it != end; ++it) { 3885f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian // Based on the null-ness of the second argument, decide whether this is an insert or a delete. 389231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block SQLiteStatement& query = it->second.isNull() ? remove : insert; 3908e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 3918e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project query.bindText(1, it->first); 3928e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 393231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block // If the second argument is non-null, we're doing an insert, so bind it as the value. 3948e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (!it->second.isNull()) 3958e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project query.bindText(2, it->second); 3968e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 3978e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project int result = query.step(); 3988e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (result != SQLResultDone) { 3998e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project LOG_ERROR("Failed to update item in the local storage database - %i", result); 4008e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project break; 4018e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 4028e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 4038e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project query.reset(); 4048e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 4058e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 4068e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 4070bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdochvoid StorageAreaSync::performSync() 4085f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian{ 4095f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian ASSERT(!isMainThread()); 4105f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian 4115f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian bool clearItems; 4125f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian HashMap<String, String> items; 4135f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian { 4145f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian MutexLocker locker(m_syncLock); 4155f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian 4165f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian ASSERT(m_syncScheduled); 4175f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian 4185f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian clearItems = m_clearItemsWhileSyncing; 4195f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian m_itemsPendingSync.swap(items); 4205f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian 4215f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian m_clearItemsWhileSyncing = false; 4225f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian m_syncScheduled = false; 423dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block m_syncInProgress = true; 4245f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian } 4255f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian 4265f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian sync(clearItems, items); 4275f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian 428dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block { 429dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block MutexLocker locker(m_syncLock); 430dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block m_syncInProgress = false; 431dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block } 432dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block 4335f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian // The following is balanced by the call to disableSuddenTermination in the 4345f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian // syncTimerFired function. 4355f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian enableSuddenTermination(); 4365f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian} 4375f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian 43806ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsenvoid StorageAreaSync::deleteEmptyDatabase() 43906ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen{ 44006ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen ASSERT(!isMainThread()); 44106ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen if (!m_database.isOpen()) 44206ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen return; 44306ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen 44406ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen SQLiteStatement query(m_database, "SELECT COUNT(*) FROM ItemTable"); 44506ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen if (query.prepare() != SQLResultOk) { 44606ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen LOG_ERROR("Unable to count number of rows in ItemTable for local storage"); 44706ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen return; 44806ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen } 44906ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen 45006ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen int result = query.step(); 45106ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen if (result != SQLResultRow) { 45206ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen LOG_ERROR("No results when counting number of rows in ItemTable for local storage"); 45306ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen return; 45406ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen } 45506ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen 45606ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen int count = query.getColumnInt(0); 45706ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen if (!count) { 45806ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen query.finalize(); 45906ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen m_database.close(); 4602bde8e466a4451c7319e3a072d118917957d6554Steve Block if (StorageTracker::tracker().isActive()) 4612bde8e466a4451c7319e3a072d118917957d6554Steve Block StorageTracker::tracker().deleteOrigin(m_databaseIdentifier); 4622bde8e466a4451c7319e3a072d118917957d6554Steve Block else { 4632bde8e466a4451c7319e3a072d118917957d6554Steve Block String databaseFilename = m_syncManager->fullDatabaseFilename(m_databaseIdentifier); 4642bde8e466a4451c7319e3a072d118917957d6554Steve Block if (!SQLiteFileSystem::deleteDatabaseFile(databaseFilename)) 4652bde8e466a4451c7319e3a072d118917957d6554Steve Block LOG_ERROR("Failed to delete database file %s\n", databaseFilename.utf8().data()); 4662bde8e466a4451c7319e3a072d118917957d6554Steve Block } 46706ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen } 46806ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen} 46906ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen 4702bde8e466a4451c7319e3a072d118917957d6554Steve Blockvoid StorageAreaSync::scheduleSync() 4712bde8e466a4451c7319e3a072d118917957d6554Steve Block{ 4722bde8e466a4451c7319e3a072d118917957d6554Steve Block syncTimerFired(&m_syncTimer); 4732bde8e466a4451c7319e3a072d118917957d6554Steve Block} 4742bde8e466a4451c7319e3a072d118917957d6554Steve Block 4758e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} // namespace WebCore 476b679b2a6c810dd2f9e8d7072e542b884a4e7060fBen Murdoch 477b679b2a6c810dd2f9e8d7072e542b884a4e7060fBen Murdoch#endif // ENABLE(DOM_STORAGE) 478