[asterisk-commits] twilson: branch twilson/res_config_sqlite3 r334292 - /team/twilson/res_config...

SVN commits to the Asterisk project asterisk-commits at lists.digium.com
Thu Sep 1 23:33:48 CDT 2011


Author: twilson
Date: Thu Sep  1 23:33:44 2011
New Revision: 334292

URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=334292
Log:
Properly handle reloads

Modified:
    team/twilson/res_config_sqlite3/res/res_config_sqlite3.c

Modified: team/twilson/res_config_sqlite3/res/res_config_sqlite3.c
URL: http://svnview.digium.com/svn/asterisk/team/twilson/res_config_sqlite3/res/res_config_sqlite3.c?view=diff&rev=334292&r1=334291&r2=334292
==============================================================================
--- team/twilson/res_config_sqlite3/res/res_config_sqlite3.c (original)
+++ team/twilson/res_config_sqlite3/res/res_config_sqlite3.c Thu Sep  1 23:33:44 2011
@@ -113,9 +113,12 @@
 {
 	struct realtime_sqlite3_db *db = obj;
 
+	ast_debug(1, "Destroying db: %s\n", db->name);
 	ast_string_field_free_memory(db);
 	if (db->handle) {
+		ao2_lock(db);
 		sqlite3_close(db->handle);
+		ao2_unlock(db);
 	}
 }
 
@@ -139,7 +142,7 @@
 
 static void mark_all_databases_dirty(void)
 {
-	ao2_callback(databases, OBJ_MULTIPLE | OBJ_NODATA | OBJ_UNLINK, mark_dirty_cb, NULL);
+	ao2_callback(databases, OBJ_MULTIPLE | OBJ_NODATA, mark_dirty_cb, NULL);
 }
 
 static int is_dirty_cb(void *obj, void *arg, int flags)
@@ -171,27 +174,47 @@
 	ast_debug(3, "DB: %s SQL: %s\n", db->name, sql);
 }
 
-static struct realtime_sqlite3_db *new_realtime_sqlite3_db(struct ast_config *config, const char *cat)
+static int create_or_update_db(struct ast_config *config, const char *cat)
 {
 	struct ast_variable *var;
 	struct realtime_sqlite3_db *db;
-
-	if (!(db = ao2_alloc(sizeof(*db), db_destructor))) {
-		return NULL;
-	}
-
-	if (ast_string_field_init(db, 64)) {
+	int new = 0, reopen = 0;
+
+	if (!(db = find_database(cat))) {
+		if (!(db = ao2_alloc(sizeof(*db), db_destructor))) {
+			return -1;
+		}
+		new = 1;
+	}
+
+	/* At this point db has a refcount of 1 (alloc'd) if new or 2 (linked and found) if !new
+	 * It is very important than any error exit unlinks !new entries. We could just throw
+	 * away the find_database ref above and rely on the link, but we can't be guaranteed
+	 * that some code sometime won't be added that unlinks us from another thread, etc. */
+
+	ao2_lock(db);
+
+	if (new && ast_string_field_init(db, 64)) {
+		ao2_unlock(db);
 		unref_db(&db);
-		return NULL;
+		return -1;
 	}
 
 	/* Set defaults */
 	db->requirements = REALTIME_SQLITE3_REQ_WARN;
 	db->batch = 100;
+	db->debug = 0;
+	db->dirty = 0;
 	ast_string_field_set(db, name, cat);
 
 	for (var = ast_variable_browse(config, cat); var; var = var->next) {
 		if (!strcasecmp(var->name, "dbfile")) {
+			if (!new && strcmp(db->filename, var->value)) {
+				/* We are updating the db with this name to a new location */
+				ast_debug(1, "DB %s moving from %s to %s\n", db->name, db->filename, var->value);
+				sqlite3_close(db->handle);
+				reopen = 1;
+			}
 			ast_string_field_set(db, filename, var->value);
 		} else if (!strcasecmp(var->name, "requirements")) {
 			db->requirements = str_to_requirements(var->value);
@@ -204,25 +227,35 @@
 
 	if (ast_strlen_zero(db->filename)) {
 		ast_log(LOG_WARNING, "Must specify dbfile in res_config_sqlite3.conf\n");
+		ao2_unlock(db);
 		unref_db(&db);
-		return NULL;
-	}
-
-	if (sqlite3_open(db->filename, &db->handle) != SQLITE_OK) {
+		if (!new) {
+			ao2_unlink(databases, db);
+		}
+		return -1;
+	}
+
+	if ((new || reopen) && sqlite3_open(db->filename, &db->handle) != SQLITE_OK) {
 		ast_log(LOG_WARNING, "Could not open %s: %s\n", db->filename, sqlite3_errmsg(db->handle));
+		ao2_unlock(db);
 		unref_db(&db);
-		return NULL;
+		if (!new) {
+			ao2_unlink(databases, db);
+		}
+		return -1;
 	}
 
 	if (db->debug) {
 		sqlite3_trace(db->handle, trace_cb, db);
 	}
 
-	return db;
-}
-
-static int update_realtime_sqlite3_db(struct ast_config *config, const char *cat)
-{
+	if (new) {
+		ao2_link(databases, db);
+	}
+
+	ao2_unlock(db);
+	unref_db(&db);
+
 	return 0;
 }
 
@@ -858,22 +891,14 @@
 			config == CONFIG_STATUS_FILEMISSING ? "Missing" : "Invalid", config_filename);
 	} else {
 		const char *cat;
-		struct realtime_sqlite3_db *db;
 
 		mark_all_databases_dirty();
 		for (cat = ast_category_browse(config, NULL); cat; cat = ast_category_browse(config, cat)) {
 			if (!strcasecmp(cat, "general")) {
 				continue;
 			}
-			if (!(db = find_database(cat))) {
-				if (!(db = new_realtime_sqlite3_db(config, cat))) {
-					continue;
-				}
-				ao2_link(databases, db);
-				unref_db(&db);
-			} else {
-				update_realtime_sqlite3_db(config, cat);
-				unref_db(&db);
+			if (create_or_update_db(config, cat)) {
+				continue;
 			}
 		}
 		unlink_dirty_databases();




More information about the asterisk-commits mailing list