Bug 457110 - Support in-memory DB for the downloads manager back-end, r=sdwilsh

This commit is contained in:
Ehsan Akhgari 2008-10-15 10:54:52 +03:30
parent f381c7312c
commit 4c6e8ba514
3 changed files with 196 additions and 18 deletions

View File

@ -26,6 +26,7 @@
* Srirang G Doddihal <brahmana@doddihal.com>
* Edward Lee <edward.lee@engineering.uiuc.edu>
* Graeme McCutcheon <graememcc_firefox@graeme-online.co.uk>
* Ehsan Akhgari <ehsan.akhgari@gmail.com>
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
@ -276,16 +277,63 @@ nsDownloadManager::ResumeOnWakeCallback(nsITimer *aTimer, void *aClosure)
(void)dlMgr->ResumeAllDownloads(PR_FALSE);
}
already_AddRefed<mozIStorageConnection>
nsDownloadManager::GetFileDBConnection(nsIFile *dbFile) const
{
NS_ASSERTION(dbFile, "GetFileDBConnection called with an invalid nsIFile");
nsCOMPtr<mozIStorageService> storage =
do_GetService(MOZ_STORAGE_SERVICE_CONTRACTID);
NS_ENSURE_TRUE(storage, nsnull);
nsCOMPtr<mozIStorageConnection> conn;
nsresult rv = storage->OpenDatabase(dbFile, getter_AddRefs(conn));
if (rv == NS_ERROR_FILE_CORRUPTED) {
// delete and try again, since we don't care so much about losing a user's
// download history
rv = dbFile->Remove(PR_FALSE);
NS_ENSURE_SUCCESS(rv, nsnull);
rv = storage->OpenDatabase(dbFile, getter_AddRefs(conn));
}
NS_ENSURE_SUCCESS(rv, nsnull);
return conn.forget();
}
already_AddRefed<mozIStorageConnection>
nsDownloadManager::GetMemoryDBConnection() const
{
nsCOMPtr<mozIStorageService> storage =
do_GetService(MOZ_STORAGE_SERVICE_CONTRACTID);
NS_ENSURE_TRUE(storage, nsnull);
nsCOMPtr<mozIStorageConnection> conn;
nsresult rv = storage->OpenSpecialDatabase("memory", getter_AddRefs(conn));
NS_ENSURE_SUCCESS(rv, nsnull);
return conn.forget();
}
nsresult
nsDownloadManager::InitDB(PRBool *aDoImport)
nsDownloadManager::InitMemoryDB()
{
mDBConn = GetMemoryDBConnection();
if (!mDBConn)
return NS_ERROR_NOT_AVAILABLE;
nsresult rv = CreateTable();
NS_ENSURE_SUCCESS(rv, rv);
mDBType = DATABASE_MEMORY;
return NS_OK;
}
nsresult
nsDownloadManager::InitFileDB(PRBool *aDoImport)
{
nsresult rv;
*aDoImport = PR_FALSE;
nsCOMPtr<mozIStorageService> storage =
do_GetService(MOZ_STORAGE_SERVICE_CONTRACTID, &rv);
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsIFile> dbFile;
rv = NS_GetSpecialDirectory(NS_APP_USER_PROFILE_50_DIR,
getter_AddRefs(dbFile));
@ -293,15 +341,8 @@ nsDownloadManager::InitDB(PRBool *aDoImport)
rv = dbFile->Append(DM_DB_NAME);
NS_ENSURE_SUCCESS(rv, rv);
rv = storage->OpenDatabase(dbFile, getter_AddRefs(mDBConn));
if (rv == NS_ERROR_FILE_CORRUPTED) {
// delete and try again, since we don't care so much about losing a users
// download history
rv = dbFile->Remove(PR_FALSE);
NS_ENSURE_SUCCESS(rv, rv);
rv = storage->OpenDatabase(dbFile, getter_AddRefs(mDBConn));
}
NS_ENSURE_SUCCESS(rv, rv);
mDBConn = GetFileDBConnection(dbFile);
NS_ENSURE_TRUE(mDBConn, NS_ERROR_NOT_AVAILABLE);
PRBool tableExists;
rv = mDBConn->TableExists(NS_LITERAL_CSTRING("moz_downloads"), &tableExists);
@ -310,9 +351,12 @@ nsDownloadManager::InitDB(PRBool *aDoImport)
*aDoImport = PR_TRUE;
rv = CreateTable();
NS_ENSURE_SUCCESS(rv, rv);
mDBType = DATABASE_DISK;
return NS_OK;
}
mDBType = DATABASE_DISK;
// Checking the database schema now
PRInt32 schemaVersion;
rv = mDBConn->GetSchemaVersion(&schemaVersion);
@ -526,6 +570,9 @@ nsDownloadManager::InitDB(PRBool *aDoImport)
// if the statement fails, that means all the columns were not there.
// First we backup the database
nsCOMPtr<mozIStorageService> storage =
do_GetService(MOZ_STORAGE_SERVICE_CONTRACTID);
NS_ENSURE_TRUE(storage, NS_ERROR_NOT_AVAILABLE);
nsCOMPtr<nsIFile> backup;
rv = storage->BackupDatabaseFile(dbFile, DM_DB_CORRUPT_FILENAME, nsnull,
getter_AddRefs(backup));
@ -894,8 +941,20 @@ nsDownloadManager::Init()
mObserverService = do_GetService("@mozilla.org/observer-service;1", &rv);
NS_ENSURE_SUCCESS(rv, rv);
PRBool doImport;
rv = InitDB(&doImport);
PRBool doImport = PR_FALSE;
switch (mDBType) {
case DATABASE_MEMORY:
rv = InitMemoryDB();
break;
case DATABASE_DISK:
rv = InitFileDB(&doImport);
break;
default:
NS_ASSERTION(0, "Unexpected value encountered for nsDownloadManager::mDBType");
break;
}
NS_ENSURE_SUCCESS(rv, rv);
if (doImport)
@ -1783,6 +1842,20 @@ nsDownloadManager::NotifyListenersOnStateChange(nsIWebProgress *aProgress,
aDownload);
}
nsresult
nsDownloadManager::SwitchDatabaseTypeTo(enum nsDownloadManager::DatabaseType aType)
{
if (aType == mDBType)
return NS_OK; // no-op
mDBType = aType;
(void)PauseAllDownloads(PR_TRUE);
(void)RemoveAllDownloads();
return Init();
}
////////////////////////////////////////////////////////////////////////////////
//// nsINavHistoryObserver
@ -1930,6 +2003,12 @@ nsDownloadManager::Observe(nsISupports *aSubject,
// We can now resume all downloads that are supposed to auto-resume.
(void)ResumeAllDownloads(PR_FALSE);
}
else if (strcmp(aTopic, "dlmgr-switchdb") == 0) {
if (NS_LITERAL_STRING("memory").Equals(aData))
return SwitchDatabaseTypeTo(DATABASE_MEMORY);
else if (NS_LITERAL_STRING("disk").Equals(aData))
return SwitchDatabaseTypeTo(DATABASE_DISK);
}
else if (strcmp(aTopic, "alertclickcallback") == 0) {
nsCOMPtr<nsIDownloadManagerUI> dmui =
do_GetService("@mozilla.org/download-manager-ui;1", &rv);

View File

@ -25,6 +25,7 @@
* Shawn Wilsher <me@shawnwilsher.com>
* Srirang G Doddihal <brahmana@doddihal.com>
* Edward Lee <edward.lee@engineering.uiuc.edu>
* Ehsan Akhgari <ehsan.akhgari@gmail.com>
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
@ -93,10 +94,23 @@ public:
static nsDownloadManager *GetSingleton();
virtual ~nsDownloadManager();
nsDownloadManager() {};
nsDownloadManager() :
mDBType(DATABASE_DISK)
{
}
protected:
nsresult InitDB(PRBool *aDoImport);
enum DatabaseType
{
DATABASE_DISK = 0, // default
DATABASE_MEMORY
};
nsresult InitFileDB(PRBool *aDoImport);
nsresult InitMemoryDB();
already_AddRefed<mozIStorageConnection> GetFileDBConnection(nsIFile *dbFile) const;
already_AddRefed<mozIStorageConnection> GetMemoryDBConnection() const;
nsresult SwitchDatabaseTypeTo(enum DatabaseType aType);
nsresult CreateTable();
nsresult ImportDownloadHistory();
@ -254,6 +268,8 @@ private:
nsCOMPtr<mozIStorageStatement> mGetIdsForURIStatement;
nsAutoPtr<mozStorageTransaction> mHistoryTransaction;
enum DatabaseType mDBType;
static nsDownloadManager *gDownloadManagerService;
friend class nsDownload;

View File

@ -0,0 +1,83 @@
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is Download Manager Test Code.
*
* The Initial Developer of the Original Code is
* Ehsan Akhgari <ehsan.akhgari@gmail.com>.
* Portions created by the Initial Developer are Copyright (C) 2008
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
// This tests the switching of the download manager database types between disk
// and memory based databases. This feature was added in bug 457110.
const nsIDownloadManager = Ci.nsIDownloadManager;
const dm = Cc["@mozilla.org/download-manager;1"].getService(nsIDownloadManager);
function run_test() {
let observer = dm.QueryInterface(Ci.nsIObserver);
// make sure the initial disk-based DB is initialized correctly
let connDisk = dm.DBConnection;
do_check_true(connDisk.connectionReady);
do_check_neq(connDisk.databaseFile, null);
// switch to a disk DB -- should be a no-op
observer.observe(null, "dlmgr-switchdb", "disk");
// make sure that the database has not changed
do_check_true(dm.DBConnection.connectionReady);
do_check_neq(dm.DBConnection.databaseFile, null);
do_check_true(connDisk.databaseFile.equals(dm.DBConnection.databaseFile));
connDisk = dm.DBConnection;
// switch to a memory DB
observer.observe(null, "dlmgr-switchdb", "memory");
// make sure the DB is has been switched correctly
let connMemory = dm.DBConnection;
do_check_true(connMemory.connectionReady);
do_check_eq(connMemory.databaseFile, null);
// switch to a memory DB -- should be a no-op
observer.observe(null, "dlmgr-switchdb", "memory");
// make sure that the database is still memory based
connMemory = dm.DBConnection;
do_check_true(connMemory.connectionReady);
do_check_eq(connMemory.databaseFile, null);
// switch back to the disk DB
observer.observe(null, "dlmgr-switchdb", "disk");
// make sure that the disk database is initialized correctly
do_check_true(dm.DBConnection.connectionReady);
do_check_neq(dm.DBConnection.databaseFile, null);
do_check_true(connDisk.databaseFile.equals(dm.DBConnection.databaseFile));
}