Fix bug 438369 - Create database backup before performing a database upgrade. r=mschroeder
authorPhilipp Kewisch <mozilla@kewis.ch>
Fri, 05 Aug 2011 20:55:23 +0200
changeset 8358 952e2f8e45ca646eee493a67dd277019e1ba54d8
parent 8357 29ea4eb2c6fbb292cc6b1d1a826c382053d3caa8
child 8359 6ade8a6feeec364dee50923cd6ca85339f2fea4b
push idunknown
push userunknown
push dateunknown
reviewersmschroeder
bugs438369
Fix bug 438369 - Create database backup before performing a database upgrade. r=mschroeder
calendar/providers/storage/calStorageUpgrade.jsm
--- a/calendar/providers/storage/calStorageUpgrade.jsm
+++ b/calendar/providers/storage/calStorageUpgrade.jsm
@@ -93,24 +93,25 @@
  *     version (setDbVersionAndCommit also commits the transaction)
  * - If something fails, throw reportErrorAndRollback(db, e) to report the
  *     failure and roll back the transaction.
  *
  * If this documentation isn't sufficient to make upgrading understandable,
  * please file a bug.
  */
 
+Components.utils.import("resource:///modules/Services.jsm");
 Components.utils.import("resource://calendar/modules/calUtils.jsm");
 Components.utils.import("resource://calendar/modules/calStorageHelpers.jsm");
 
 // The current database version. Be sure to increment this when you create a new
 // updater.
 var DB_SCHEMA_VERSION = 19;
 
-var EXPORTED_SYMBOLS = ["DB_SCHEMA_VERSION", "getSql", "getAllSql", "getSqlTable", "upgradeDB"];
+var EXPORTED_SYMBOLS = ["DB_SCHEMA_VERSION", "getSql", "getAllSql", "getSqlTable", "upgradeDB", "backupDB"];
 
 /**
  * Gets the SQL for the given table data and table name. This can be both a real
  * table or the name of an index. Indexes must contain the idx_ prefix.
  *
  * @param tblName       The name of the table or index to retrieve sql for
  * @param tblData       The table data object, as returned from the upgrade_v*
  *                        functions. If null, then the latest table data is
@@ -201,16 +202,39 @@ function getVersion(db) {
             selectSchemaVersion.reset();
         }
     }
 
     throw "cal_calendar_schema_version SELECT returned no results";
 }
 
 /**
+ * Backup the database and notify the user via error console of the process
+ */
+function backupDB(db, currentVersion) {
+    cal.LOG("Storage: Backing up current database...");
+    try {
+        // Prepare filenames and path
+        let backupFilename = "local.v" + currentVersion + ".sqlite";
+        let backupPath = cal.getCalendarDirectory();
+        backupPath.append("backup");
+        if (!backupPath.exists()) {
+            backupPath.create(CI.nsIFile.DIRECTORY_TYPE, parseInt("0755", 8));
+        }
+
+        // Create a backup file and notify the user via WARN, since LOG will not
+        // be visible unless a pref is set.
+        let file = Services.storage.backupDatabaseFile(db.databaseFile, backupFilename, backupPath);
+        cal.WARN("Storage: Upgrading to v" + DB_SCHEMA_VERSION + ", a backup was written to: " + file.path);
+    } catch (e) {
+        cal.ERROR("Storage: Error creating backup file: " + e);
+    }
+}
+
+/**
  * Upgrade the passed database.
  *
  * @param db        The database to bring up to date.
  */
 function upgradeDB(db) {
     cal.ASSERT(db, "Database has not been opened!", true);
     if (!db.tableExists("cal_calendar_schema_version")) {
         cal.LOG("Storage: Creating tables from scratch");
@@ -219,16 +243,20 @@ function upgradeDB(db) {
             executeSimpleSQL(db, getAllSql());
             setDbVersionAndCommit(db, DB_SCHEMA_VERSION);
         } catch (e) {
             reportErrorAndRollback(db, e);
         }
     } else {
         let version = getVersion(db);
         if (version < DB_SCHEMA_VERSION) {
+            // First, create a backup
+            backupDB(db, version);
+
+            // Then start the latest upgrader
             cal.LOG("Storage: Preparing to upgrade v" + version +
                     " to v" + DB_SCHEMA_VERSION);
             upgrade["v" + DB_SCHEMA_VERSION](db, version);
         } else if (version > DB_SCHEMA_VERSION) {
             throw Components.interfaces.calIErrors.STORAGE_UNKNOWN_SCHEMA_ERROR;
         }
     }