Merge authors: Siegfried Gevatter (rainct) ------------------------------------------------------------ revno: 372 [merge] committer: Siegfried-Angel Gevatter Pujals <siegfr...@gevatter.com> branch nick: zeitgeist timestamp: Wed 2012-01-25 14:24:34 +0100 message: Automatically recover from corrupt database and be more clear on some other errors. modified: doc/zeitgeist-daemon.1 src/errors.vala src/sql-schema.vala src/sql.vala src/utils.vala src/zeitgeist-daemon.vala
-- lp:zeitgeist https://code.launchpad.net/~zeitgeist/zeitgeist/bluebird Your team Zeitgeist Framework Team is subscribed to branch lp:zeitgeist. To unsubscribe from this branch go to https://code.launchpad.net/~zeitgeist/zeitgeist/bluebird/+edit-subscription
=== modified file 'doc/zeitgeist-daemon.1' --- doc/zeitgeist-daemon.1 2012-01-02 19:31:15 +0000 +++ doc/zeitgeist-daemon.1 2012-01-25 13:24:34 +0000 @@ -87,6 +87,12 @@ .TP .B 10 There is already a running Zeitgeist instance. +.TP +.B 21 +Could not access the database file. +.TP +.B 22 +The database file is locked. .SH SEE ALSO \fBzeitgeist-datahub\fR, \fBgnome-activity-journal\fR === modified file 'src/errors.vala' --- src/errors.vala 2011-10-20 13:32:51 +0000 +++ src/errors.vala 2012-01-25 10:36:27 +0000 @@ -23,10 +23,15 @@ [DBus (name = "org.gnome.zeitgeist.EngineError")] public errordomain EngineError { + BACKUP_FAILED, + DATABASE_BUSY, + DATABASE_CANTOPEN, + DATABASE_CORRUPT, DATABASE_ERROR, + DATABASE_RETIRE_FAILED, INVALID_ARGUMENT, INVALID_KEY, - BACKUP_FAILED, + EXISTING_INSTANCE, } // vala doesn't include proper headers, this fixes it === modified file 'src/sql-schema.vala' --- src/sql-schema.vala 2012-01-25 12:28:24 +0000 +++ src/sql-schema.vala 2012-01-25 13:24:34 +0000 @@ -417,8 +417,8 @@ } /** - * Execute the given SQL. If the query doesn't succeed, log a - * critical warning (potentially aborting the program). + * Execute the given SQL. If the query doesn't succeed, throw + * an error. * * @param database the database on which to run the query * @param sql the SQL query to run @@ -429,10 +429,17 @@ int rc = database.exec (sql); if (rc != Sqlite.OK) { - const string fmt_str = "Can't create database: %d, %s\n\n" + - "Unable to execute SQL:\n%s"; - var err_msg = fmt_str.printf (rc, database.errmsg (), sql); - throw new EngineError.DATABASE_ERROR (err_msg); + if (rc == Sqlite.CORRUPT) + { + throw new EngineError.DATABASE_CORRUPT (database.errmsg ()); + } + else + { + const string fmt_str = "Can't create database: %d, %s\n\n" + + "Unable to execute SQL:\n%s"; + var err_msg = fmt_str.printf (rc, database.errmsg (), sql); + throw new EngineError.DATABASE_ERROR (err_msg); + } } } === modified file 'src/sql.vala' --- src/sql.vala 2012-01-02 19:30:51 +0000 +++ src/sql.vala 2012-01-25 13:24:34 +0000 @@ -67,13 +67,7 @@ public ZeitgeistDatabase () throws EngineError { - message ("Opening DB from %s", Utils.get_database_file_path ()); - int rc = Sqlite.Database.open_v2 ( - Utils.get_database_file_path (), - out database); - assert_query_success (rc, "Can't open database"); - - DatabaseSchema.ensure_schema (database); + open_database (true); prepare_queries (); @@ -82,6 +76,74 @@ database.update_hook (update_callback); } + private void open_database (bool retry) + throws EngineError + { + int rc = Sqlite.Database.open_v2 ( + Utils.get_database_file_path (), + out database); + + if (rc == Sqlite.OK) + { + try + { + // Error (like a malformed database) may not be exposed + // until we try to operate on the database. + DatabaseSchema.ensure_schema (database); + } + catch (EngineError err) + { + if (err is EngineError.DATABASE_CORRUPT && retry) + rc = Sqlite.CORRUPT; + else if (err is EngineError.DATABASE_CANTOPEN) + rc = Sqlite.CANTOPEN; + else if (err is EngineError.DATABASE_BUSY) + rc = Sqlite.BUSY; + else + throw err; + } + } + + if (rc != Sqlite.OK) + { + if (rc == Sqlite.CORRUPT && retry) + { + // The database disk image is malformed + warning ("It looks like your database is corrupt. " + + "It will be renamed and a new one will be created."); + try + { + Utils.retire_database (); + } + catch (Error err) + { + string message = + "Could not rename database: %s".printf ( + err.message); + throw new EngineError.DATABASE_RETIRE_FAILED (message); + } + open_database (false); + } + else if (rc == Sqlite.PERM || rc == Sqlite.CANTOPEN) + { + // Access permission denied / Unable to open database file + throw new EngineError.DATABASE_CANTOPEN ( + database.errmsg ()); + } + else if (rc == Sqlite.BUSY) + { + // The database file is locked + throw new EngineError.DATABASE_BUSY (database.errmsg ()); + } + else + { + string message = "Can't open database: %d, %s".printf(rc, + database.errmsg ()); + throw new EngineError.DATABASE_ERROR (message); + } + } + } + public uint32 get_last_id () throws EngineError { int last_id = -1; === modified file 'src/utils.vala' --- src/utils.vala 2011-10-31 15:28:09 +0000 +++ src/utils.vala 2011-12-31 15:57:15 +0000 @@ -31,7 +31,8 @@ private static string DATABASE_FILE_BACKUP_PATH; private static string LOCAL_EXTENSIONS_PATH; - public const string ZEITGEIST_DATA_FOLDER = "zeitgeist"; + public const string DATA_FOLDER = "zeitgeist"; + public const string DATABASE_BASENAME = "activity.sqlite"; public const string USER_EXTENSION_PATH = ""; // D-Bus @@ -48,7 +49,7 @@ DATA_PATH = Environment.get_variable ("ZEITGEIST_DATA_PATH") ?? Path.build_filename (Environment.get_user_data_dir (), - ZEITGEIST_DATA_FOLDER); + DATA_FOLDER); if (!FileUtils.test (DATA_PATH, FileTest.IS_DIR)) { @@ -66,7 +67,7 @@ DATABASE_FILE_PATH = Environment.get_variable ("ZEITGEIST_DATABASE_PATH") ?? - Path.build_filename (get_data_path (), "activity.sqlite"); + Path.build_filename (get_data_path (), DATABASE_BASENAME); debug ("DATABASE_FILE_PATH = %s", DATABASE_FILE_PATH); @@ -80,13 +81,20 @@ DATABASE_FILE_BACKUP_PATH = Environment.get_variable ("ZEITGEIST_DATABASE_BACKUP_PATH") ?? - Path.build_filename (get_data_path (), "activity.sqlite.bck"); + Path.build_filename (get_data_path (), + DATABASE_BASENAME + ".bck"); debug ("DATABASE_FILE_BACKUP_PATH = %s", DATABASE_FILE_BACKUP_PATH); return DATABASE_FILE_BACKUP_PATH; } + public string get_database_file_retire_name () + { + return DATABASE_BASENAME + ".%s.bck".printf ( + new DateTime.now_local ().format ("%Y%m%d-%H%M%S")); + } + public unowned string get_local_extensions_path () { if (LOCAL_EXTENSIONS_PATH != null) return LOCAL_EXTENSIONS_PATH; @@ -113,6 +121,12 @@ original.copy (destination, FileCopyFlags.OVERWRITE, null, null); } + + public void retire_database () throws Error + { + File dbfile = File.new_for_path (get_database_file_path ()); + dbfile.set_display_name (get_database_file_retire_name ()); + } } } === modified file 'src/zeitgeist-daemon.vala' --- src/zeitgeist-daemon.vala 2012-01-02 19:30:51 +0000 +++ src/zeitgeist-daemon.vala 2012-01-25 13:24:34 +0000 @@ -329,6 +329,7 @@ } static void run () + throws Error { DBusConnection connection; bool name_owned; @@ -342,8 +343,7 @@ } catch (IOError err) { - critical ("%s", err.message); - return; + throw err; } if (name_owned) { @@ -353,9 +353,10 @@ } else { - critical ("An existing instance was found. Please use " + + warning ("An existing instance was found. Please use " + "--replace to stop it and start a new instance."); - Posix.exit (10); + throw new EngineError.EXISTING_INSTANCE ( + "Zeitgeist is running already."); } } @@ -370,8 +371,19 @@ } catch (Error err) { - critical ("%s", err.message); - return; + if (err is EngineError.DATABASE_CANTOPEN) + { + warning ("Could not access the database file.\n" + + "Please check the permissions of file %s.", + Utils.get_database_file_path ()); + } + else if (err is EngineError.DATABASE_BUSY) + { + warning ("It looks like another Zeitgeist instance " + + "is already running (the database is locked). " + + "If you want to start a new instance, use --replace."); + } + throw err; } uint owner_id = Bus.own_name_on_connection (connection, @@ -474,7 +486,15 @@ } catch (Error err) { + if (err is EngineError.EXISTING_INSTANCE) + return 10; + if (err is EngineError.DATABASE_CANTOPEN) + return 21; + if (err is EngineError.DATABASE_BUSY) + return 22; + warning ("%s", err.message); + return 1; } return 0;
_______________________________________________ Mailing list: https://launchpad.net/~zeitgeist Post to : zeitgeist@lists.launchpad.net Unsubscribe : https://launchpad.net/~zeitgeist More help : https://help.launchpad.net/ListHelp