Commit fc0c2cab authored by Jamie McCracken's avatar Jamie McCracken

various fixes

svn path=/trunk/; revision=993
parent 6fd49b4a
2007-11-03 Jamie McCracken <jamiemcc at gnome org>
* made corruption scan active only if trackerd was not cleanly shutdown
* also repair qdbm index files
* mutex safeguards around cache
* allow readonly mode for trackerd when another process is present but on another machine (NFS)
* bomb out trackerd if not primary owner of tracker dbus name
* made use of sqlite3_free where needed to by sqlite 3.5
2007-10-31 Saleem Abdulrasool <compnerd@compnerd.org>
Patch from Bruce Cowan <bugs@bcowan.fastmail.co.uk>
Fix spelling error 'occured' -> 'occurred'. Bug #481651.
......
......@@ -272,6 +272,7 @@ update_word_table (GHashTable *table, const char *word, WordDetails *word_detail
void
tracker_cache_add (const gchar *word, guint32 service_id, gint service_type, gint score, gboolean is_new)
{
static GStaticMutex mutex = G_STATIC_MUTEX_INIT;
WordDetails word_details;
word_details.id = service_id;
......@@ -279,6 +280,7 @@ tracker_cache_add (const gchar *word, guint32 service_id, gint service_type, gin
if (is_new) {
/* no need to mutex new stuff as only one thread is processing them */
if (!is_email (service_type)) {
if (update_word_table (tracker->file_word_table, word, &word_details)) tracker->word_count++;
} else {
......@@ -286,7 +288,12 @@ tracker_cache_add (const gchar *word, guint32 service_id, gint service_type, gin
}
} else {
/* we need to mutex this to prevent corruption on multi cpu machines as both index process thread and user request thread (when setting tags/metadata) can call this */
g_static_mutex_lock (&mutex);
if (update_word_table (tracker->file_update_word_table, word, &word_details)) tracker->word_update_count++;
g_static_mutex_unlock (&mutex);
}
}
......
......@@ -1043,13 +1043,10 @@ tracker_db_connect (void)
tracker_db_exec_no_reply (db_con, "PRAGMA cache_size = 16");
}
/* create user defined utf-8 collation sequence */
if (SQLITE_OK != sqlite3_create_collation (db_con->db, "UTF8", SQLITE_UTF8, 0, &sqlite3_utf8_collation)) {
tracker_error ("ERROR: collation sequence failed due to %s", sqlite3_errmsg (db_con->db));
}
/* create user defined functions that can be used in sql */
if (SQLITE_OK != sqlite3_create_function (db_con->db, "FormatDate", 1, SQLITE_ANY, NULL, &sqlite3_date_to_str, NULL, NULL)) {
......@@ -1091,6 +1088,8 @@ tracker_db_connect (void)
tracker_db_attach_db (db_con, "common");
tracker_db_attach_db (db_con, "cache");
db_con->cache = db_con;
db_con->common = db_con;
db_con->thread = NULL;
......@@ -1606,7 +1605,7 @@ tracker_db_exec_no_reply (DBConnection *db_con, const char *query)
busy_count++;
if (msg) {
g_free (msg);
sqlite3_free (msg);
msg = NULL;
}
......@@ -1631,7 +1630,7 @@ tracker_db_exec_no_reply (DBConnection *db_con, const char *query)
if (msg) {
tracker_error ("WARNING: sql query %s failed because %s", query, msg);
g_free (msg);
sqlite3_free (msg);
} else {
tracker_error ("WARNING: sql query %s failed with code %d", query, rc);
}
......@@ -1682,7 +1681,7 @@ exec_sql (DBConnection *db_con, const char *query, gboolean ignore_nulls)
}
if (msg) {
g_free (msg);
sqlite3_free (msg);
msg = NULL;
}
......@@ -1706,14 +1705,14 @@ exec_sql (DBConnection *db_con, const char *query, gboolean ignore_nulls)
if (i != SQLITE_OK) {
unlock_db ();
tracker_error ("ERROR: query %s failed with error: %s", query, msg);
g_free (msg);
sqlite3_free (msg);
return NULL;
}
unlock_db ();
if (msg) {
g_free (msg);
sqlite3_free (msg);
}
if (!array || rows == 0 || cols == 0) {
......@@ -2681,7 +2680,6 @@ tracker_db_get_indexable_content_words (DBConnection *db_con, guint32 id, GHashT
static void
save_full_text_bytes (DBConnection *blob_db_con, const char *str_file_id, GByteArray *byte_array)
{
char *value;
sqlite3_stmt *stmt;
int busy_count;
int rc;
......@@ -2706,10 +2704,6 @@ save_full_text_bytes (DBConnection *blob_db_con, const char *str_file_id, GByteA
while (TRUE) {
if (!lock_db ()) {
if (value) {
g_free (value);
}
unlock_connection (blob_db_con);
......@@ -6319,9 +6313,9 @@ char *
tracker_db_get_option_string (DBConnection *db_con, const char *option)
{
char *value;
char *value = "";
gchar ***res = tracker_exec_proc (db_con, "GetOption", 1, option);
gchar ***res = tracker_exec_proc (db_con->common, "GetOption", 1, option);
if (res) {
if (res[0] && res[0][0]) {
......@@ -6337,7 +6331,7 @@ tracker_db_get_option_string (DBConnection *db_con, const char *option)
void
tracker_db_set_option_string (DBConnection *db_con, const char *option, const char *value)
{
tracker_exec_proc (db_con, "SetOption", 2, value, option);
tracker_exec_proc (db_con->common, "SetOption", 2, value, option);
}
......@@ -6345,9 +6339,9 @@ int
tracker_db_get_option_int (DBConnection *db_con, const char *option)
{
int value;
int value = 0;
gchar ***res = tracker_exec_proc (db_con, "GetOption", 1, option);
gchar ***res = tracker_exec_proc (db_con->common, "GetOption", 1, option);
if (res) {
if (res[0] && res[0][0]) {
......@@ -6365,7 +6359,7 @@ tracker_db_set_option_int (DBConnection *db_con, const char *option, int value)
{
char *str_value = tracker_int_to_str (value);
tracker_exec_proc (db_con, "SetOption", 2, str_value, option);
tracker_exec_proc (db_con->common, "SetOption", 2, str_value, option);
g_free (str_value);
}
......@@ -6392,3 +6386,24 @@ tracker_db_regulate_transactions (DBConnection *db_con, int interval)
}
gboolean
tracker_db_integrity_check (DBConnection *db_con)
{
gboolean integrity_check = TRUE;
char ***res = tracker_exec_sql (db_con, "pragma integrity_check;");
if (!res) {
integrity_check = FALSE;
} else {
char **row = tracker_db_get_row (res, 0);
if (row && row[0]) {
integrity_check = (strcasecmp (row[0], "ok") == 0);
}
}
return integrity_check;
}
......@@ -228,4 +228,6 @@ void tracker_db_set_option_string (DBConnection *db_con, const char *option, co
int tracker_db_get_option_int (DBConnection *db_con, const char *option);
void tracker_db_set_option_int (DBConnection *db_con, const char *option, int value);
gboolean tracker_db_integrity_check (DBConnection *db_con);
#endif
......@@ -18,6 +18,7 @@
*/
#include <string.h>
#include <stdlib.h>
#include "tracker-dbus.h"
#include "tracker-utils.h"
......@@ -42,42 +43,45 @@ tracker_dbus_init (void)
{
DBusError error;
DBusConnection *connection;
int ret;
dbus_error_init (&error);
connection = dbus_bus_get (DBUS_BUS_SESSION, &error);
if ((connection == NULL) || dbus_error_is_set (&error)) {
tracker_error ("ERROR: tracker_dbus_init() could not get the session bus");
connection = NULL;
goto out;
}
if (dbus_error_is_set (&error)) {
tracker_error ("DBUS ERROR: %s occurred with message %s", error.name, error.message);
dbus_error_free (&error);
}
dbus_connection_setup_with_g_main (connection, NULL);
tracker_error ("ERROR: could not get the dbus session bus - exiting");
exit (EXIT_FAILURE);
if (!dbus_connection_register_object_path (connection, TRACKER_OBJECT, &tracker_vtable, NULL)) {
tracker_error ("ERROR: could not register D-BUS handlers");
connection = NULL;
goto out;
}
dbus_connection_setup_with_g_main (connection, NULL);
dbus_error_init (&error);
dbus_bus_request_name (connection, TRACKER_SERVICE, 0, &error);
ret = dbus_bus_request_name (connection, TRACKER_SERVICE, DBUS_NAME_FLAG_DO_NOT_QUEUE, &error);
if (dbus_error_is_set (&error)) {
tracker_error ("ERROR: could not acquire service name due to '%s'", error.message);
connection = NULL;
goto out;
exit (EXIT_FAILURE);
}
out:
if (dbus_error_is_set (&error)) {
tracker_error ("DBUS ERROR: %s occurred with message %s", error.name, error.message);
dbus_error_free (&error);
if (ret != DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER) {
tracker_error ("ERROR: trackerd already running on your session dbus - exiting...");
exit (EXIT_FAILURE);
}
if (!dbus_connection_register_object_path (connection, TRACKER_OBJECT, &tracker_vtable, NULL)) {
tracker_error ("ERROR: could not register D-BUS handlers");
connection = NULL;
}
if (connection != NULL) {
dbus_connection_set_exit_on_disconnect (connection, FALSE);
}
......
......@@ -186,6 +186,19 @@ get_preferred_bucket_count (Indexer *indexer)
}
gboolean
tracker_indexer_repair (const char *name)
{
gboolean result = TRUE;
char *index_name = g_build_filename (tracker->data_dir, name, NULL);
result = dprepair (index_name);
g_free (index_name);
return result;
}
static inline DEPOT *
open_index (const gchar *name)
{
......
......@@ -101,6 +101,7 @@ void tracker_index_free_hit_list (GSList *hit_list);
Indexer * tracker_indexer_open (const gchar *name);
void tracker_indexer_close (Indexer *indexer);
gboolean tracker_indexer_repair (const char *name);
void tracker_indexer_free (Indexer *indexer, gboolean remove_file);
gboolean tracker_indexer_has_merge_index (Indexer *indexer, gboolean update);
......
......@@ -199,6 +199,8 @@ typedef enum {
typedef struct {
gboolean readonly;
TrackerStatus status;
int pid;
......
......@@ -394,11 +394,15 @@ tracker_do_cleanup (const gchar *sig_msg)
tracker_email_end_email_watching ();
/* reset integrity status as threads have closed cleanly */
tracker_db_set_option_int (main_thread_db_con, "IntegrityCheck", 0);
tracker_db_close (main_thread_db_con);
/* This must be called after all other db functions */
tracker_db_finalize ();
if (tracker->reindex) {
tracker_remove_dirs (tracker->data_dir);
g_mkdir_with_parents (tracker->data_dir, 00755);
......@@ -2564,6 +2568,8 @@ main (gint argc, gchar *argv[])
g_free (str);
/* prevent muliple instances */
tracker->readonly = FALSE;
lfp = g_open (lock_file, O_RDWR|O_CREAT, 0640);
g_free (lock_file);
......@@ -2573,8 +2579,8 @@ main (gint argc, gchar *argv[])
}
if (lockf (lfp, F_TLOCK, 0) <0) {
g_warning ("Tracker daemon is already running - exiting");
exit (1);
g_warning ("Tracker daemon is already running - attempting to run in readonly mode");
tracker->readonly = TRUE;
}
/* Set child's niceness to 19 */
......@@ -2675,7 +2681,7 @@ main (gint argc, gchar *argv[])
}
/* create database if needed */
if (need_index) {
if (!tracker->readonly && need_index) {
create_index (need_data);
......@@ -2688,32 +2694,28 @@ main (gint argc, gchar *argv[])
db_con->thread = "main";
/* check db integrity */
gboolean integrity_check = TRUE;
char ***res = tracker_exec_sql (db_con, "pragma integrity_check;");
/* check db integrity if not previously shut down cleanly */
if (!tracker->readonly && !need_index && tracker_db_get_option_int (db_con, "IntegrityCheck") == 1) {
if (!res) {
integrity_check = FALSE;
} else {
tracker_log ("performing integrity check as trackerd was not shutdown cleanly");
char **row = tracker_db_get_row (res, 0);
if (!tracker_db_integrity_check (db_con) || !tracker_indexer_repair ("file-index.db") || !tracker_indexer_repair ("email-index.db")) {
tracker_error ("db or index corruption detected - prepare for reindex...");
tracker_db_close (db_con);
if (row && row[0]) {
integrity_check = (strcasecmp (row[0], "ok") == 0);
}
}
if (!integrity_check) {
tracker_error ("db corruption detected - prepare for reindex...");
tracker_db_close (db_con);
tracker_remove_dirs (tracker->data_dir);
g_mkdir_with_parents (tracker->data_dir, 00755);
create_index (need_data);
db_con = tracker_db_connect ();
db_con->thread = "main";
tracker_remove_dirs (tracker->data_dir);
g_mkdir_with_parents (tracker->data_dir, 00755);
create_index (need_data);
db_con = tracker_db_connect ();
db_con->thread = "main";
}
}
}
if (!tracker->readonly) {
tracker_db_set_option_int (db_con, "IntegrityCheck", 1);
}
if (tracker->first_time_index) {
tracker_db_set_option_int (db_con, "InitialIndex", 1);
......@@ -2744,7 +2746,11 @@ main (gint argc, gchar *argv[])
tracker_db_get_static_data (db_con);
tracker->file_metadata_queue = g_async_queue_new ();
tracker->file_process_queue = g_async_queue_new ();
if (!tracker->readonly) {
tracker->file_process_queue = g_async_queue_new ();
}
tracker->user_request_queue = g_async_queue_new ();
tracker->loop = g_main_loop_new (NULL, TRUE);
......@@ -2758,13 +2764,16 @@ main (gint argc, gchar *argv[])
add_local_dbus_connection_monitoring (tracker->dbus_con);
if (!tracker_start_watching ()) {
tracker_error ("ERROR: file monitoring failed to start");
tracker_do_cleanup ("File watching failure");
exit (1);
}
if (!tracker->readonly) {
tracker->file_process_thread = g_thread_create ((GThreadFunc) process_files_thread, NULL, FALSE, NULL);
if (!tracker_start_watching ()) {
tracker_error ("ERROR: file monitoring failed to start");
tracker_do_cleanup ("File watching failure");
exit (1);
}
tracker->file_process_thread = g_thread_create ((GThreadFunc) process_files_thread, NULL, FALSE, NULL);
}
g_main_loop_run (tracker->loop);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment