Siegfried Gevatter has proposed merging lp:~zeitgeist/zeitgeist/dbfails into lp:zeitgeist.
Requested reviews: Zeitgeist Framework Team (zeitgeist) Related bugs: Bug #743857 in Zeitgeist Framework: "zeitgeist-daemon crashed with DatabaseError in execute(): database disk image is malformed" https://bugs.launchpad.net/zeitgeist/+bug/743857 For more details, see: https://code.launchpad.net/~zeitgeist/zeitgeist/dbfails/+merge/87195 -- https://code.launchpad.net/~zeitgeist/zeitgeist/dbfails/+merge/87195 Your team Zeitgeist Framework Team is requested to review the proposed merge of lp:~zeitgeist/zeitgeist/dbfails into lp:zeitgeist.
=== modified file 'doc/zeitgeist-daemon.1' --- doc/zeitgeist-daemon.1 2011-11-01 19:38:11 +0000 +++ doc/zeitgeist-daemon.1 2011-12-31 15:59:23 +0000 @@ -81,6 +81,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 2011-12-31 15:59:23 +0000 @@ -23,10 +23,14 @@ [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, } // vala doesn't include proper headers, this fixes it === modified file 'src/sql-schema.vala' --- src/sql-schema.vala 2011-10-31 15:28:09 +0000 +++ src/sql-schema.vala 2011-12-31 15:59:23 +0000 @@ -413,8 +413,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 @@ -425,10 +425,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 2011-12-28 23:36:27 +0000 +++ src/sql.vala 2011-12-31 15:59:23 +0000 @@ -67,12 +67,7 @@ public ZeitgeistDatabase () throws EngineError { - 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 (); @@ -81,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:59:23 +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 2011-10-20 14:20:17 +0000 +++ src/zeitgeist-daemon.vala 2011-12-31 15:59:23 +0000 @@ -370,8 +370,25 @@ } 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 ()); + Posix.exit(21); + } + 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."); + Posix.exit(22); + } + else + { + critical ("%s", err.message); + return; + } } uint owner_id = Bus.own_name_on_connection (connection, @@ -442,6 +459,7 @@ catch (Error err) { 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