[asterisk-commits] twilson: branch twilson/sqlite_astdb r323320 - /team/twilson/sqlite_astdb/main/

SVN commits to the Asterisk project asterisk-commits at lists.digium.com
Mon Jun 13 22:06:13 CDT 2011


Author: twilson
Date: Mon Jun 13 22:06:11 2011
New Revision: 323320

URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=323320
Log:
Add database conversion routine for old Berkeley databases

Also fix some issues with the syncing

Modified:
    team/twilson/sqlite_astdb/main/db.c

Modified: team/twilson/sqlite_astdb/main/db.c
URL: http://svnview.digium.com/svn/asterisk/team/twilson/sqlite_astdb/main/db.c?view=diff&rev=323320&r1=323319&r2=323320
==============================================================================
--- team/twilson/sqlite_astdb/main/db.c (original)
+++ team/twilson/sqlite_astdb/main/db.c Mon Jun 13 22:06:11 2011
@@ -20,11 +20,11 @@
  *
  * \brief ASTdb Management
  *
- * \author Mark Spencer <markster at digium.com> 
+ * \author Mark Spencer <markster at digium.com>
  *
  * \note DB3 is licensed under Sleepycat Public License and is thus incompatible
- * with GPL.  To avoid having to make another exception (and complicate 
- * licensing even further) we elect to use DB1 which is BSD licensed 
+ * with GPL.  To avoid having to make another exception (and complicate
+ * licensing even further) we elect to use DB1 which is BSD licensed
  */
 
 #include "asterisk.h"
@@ -34,6 +34,9 @@
 #include "asterisk/_private.h"
 #include "asterisk/paths.h"	/* use ast_config_AST_DB */
 #include <sys/time.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
 #include <signal.h>
 #include <dirent.h>
 
@@ -46,6 +49,7 @@
 #include "asterisk/utils.h"
 #include "asterisk/manager.h"
 #include <sqlite3.h>
+#include "db1-ast/include/db.h"
 
 /*** DOCUMENTATION
 	<manager name="DBGet" language="en_US">
@@ -134,6 +138,8 @@
 
 static int init_statements(void)
 {
+	/* Don't initialize create_astdb_statment here as the astdb table needs to exist
+	 * brefore these statments can be initialized */
 	return init_stmt(&get_stmt, get_stmt_sql, sizeof(get_stmt_sql))
 	|| init_stmt(&del_stmt, del_stmt_sql, sizeof(del_stmt_sql))
 	|| init_stmt(&deltree_stmt, deltree_stmt_sql, sizeof(deltree_stmt_sql))
@@ -144,14 +150,81 @@
 	|| init_stmt(&put_stmt, put_stmt_sql, sizeof(put_stmt_sql));
 }
 
+static int db_put_raw(const char *key, size_t keylen, const char *value, size_t valuelen)
+{
+	int res = 0;
+
+	ast_mutex_lock(&dblock);
+	if (sqlite3_bind_text(put_stmt, 1, key, keylen, SQLITE_STATIC) != SQLITE_OK) {
+		ast_log(LOG_WARNING, "Couldn't bind key to stmt: %s\n", sqlite3_errmsg(astdb));
+		res = -1;
+	} else if (sqlite3_bind_text(put_stmt, 2, value, valuelen, SQLITE_STATIC) != SQLITE_OK) {
+		ast_log(LOG_WARNING, "Couldn't bind value to stmt: %s\n", sqlite3_errmsg(astdb));
+		res = -1;
+	} else if (sqlite3_step(put_stmt) != SQLITE_DONE) {
+		ast_log(LOG_WARNING, "Couldn't execute statment: %s\n", sqlite3_errmsg(astdb));
+		res = -1;
+	}
+	sqlite3_reset(put_stmt);
+	db_sync();
+	ast_mutex_unlock(&dblock);
+
+	return res;
+}
+
+static int convert_bdb_to_sqlite3(const char *sql3_dbname)
+{
+	DB *bdb;
+	DBT key = { 0, }, value = { 0, };
+	int res;
+
+	if (!(bdb = dbopen(ast_config_AST_DB, O_RDONLY, AST_FILE_MODE, DB_BTREE, NULL))) {
+		ast_log(LOG_WARNING, "Unable to open Asterisk database '%s': %s\n", ast_config_AST_DB, strerror(errno));
+		return -1;
+	}
+
+	for (res = bdb->seq(bdb, &key, &value, R_FIRST);
+			!res; res = bdb->seq(bdb, &key, &value, R_NEXT)) {
+		db_put_raw((const char *) key.data, key.size, (const char *) value.data, value.size);
+	}
+
+	bdb->close(bdb);
+
+	return 0;
+}
+
+static int db_create_astdb(void)
+{
+	int res = 0;
+
+	if (!create_astdb_stmt) {
+		init_stmt(&create_astdb_stmt, create_astdb_stmt_sql, sizeof(create_astdb_stmt_sql));
+	}
+
+	ast_mutex_lock(&dblock);
+	if (sqlite3_step(create_astdb_stmt) != SQLITE_DONE) {
+		ast_log(LOG_WARNING, "Couldn't create astdb table: %s\n", sqlite3_errmsg(astdb));
+		res = -1;
+	}
+	sqlite3_reset(create_astdb_stmt);
+	db_sync();
+	ast_mutex_unlock(&dblock);
+
+	return res;
+}
+
 static int db_open(void)
 {
 	char *dbname;
+	struct stat st;
+	int convert;
 	if (!(dbname = alloca(strlen(ast_config_AST_DB) + sizeof(".sqlite3")))) {
 		return -1;
 	}
 	strcpy(dbname, ast_config_AST_DB);
 	strcat(dbname, ".sqlite3");
+
+	convert = stat(dbname, &st) && !stat(ast_config_AST_DB, &st);
 
 	ast_mutex_lock(&dblock);
 	if (sqlite3_open_v2(dbname, &astdb, SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE | SQLITE_OPEN_NOMUTEX, NULL) != SQLITE_OK) {
@@ -162,30 +235,21 @@
 	}
 	ast_mutex_unlock(&dblock);
 
+	if (convert) {
+		/* We didn't have an sqlite3 version of the database, but we had a BDB version */
+		ast_log(LOG_WARNING, "Converting old astdb to sqlite3!\n");
+		if (db_create_astdb() || init_statements()) {
+			return -1;
+		}
+		if (!convert_bdb_to_sqlite3(dbname)) {
+			ast_log(LOG_WARNING, "Database conversion succeeded!\n");
+		}
+	}
+
 	return 0;
 }
 
-static int db_create_astdb(void)
-{
-	int res = 0;
-
-	if (!create_astdb_stmt) {
-		init_stmt(&create_astdb_stmt, create_astdb_stmt_sql, sizeof(create_astdb_stmt_sql));
-	}
-
-	ast_mutex_lock(&dblock);
-	if (sqlite3_step(create_astdb_stmt) != SQLITE_DONE) {
-		ast_log(LOG_WARNING, "Couldn't create astdb table: %s\n", sqlite3_errmsg(astdb));
-		res = -1;
-	}
-	sqlite3_reset(create_astdb_stmt);
-	db_sync();
-	ast_mutex_unlock(&dblock);
-
-	return res;
-}
-
-static int db_init(void) 
+static int db_init(void)
 {
 	if (astdb) {
 		return 0;
@@ -235,7 +299,6 @@
 {
 	char fullkey[MAX_DB_FIELD];
 	size_t fullkey_len;
-	int res = 0;
 
 	if (strlen(family) + strlen(key) + 2 > sizeof(fullkey) - 1) {
 		ast_log(LOG_WARNING, "Family and key length must be less than %zu bytes\n", sizeof(fullkey) - 3);
@@ -244,21 +307,7 @@
 
 	fullkey_len = snprintf(fullkey, sizeof(fullkey), "/%s/%s", family, key);
 
-	ast_mutex_lock(&dblock);
-	if (sqlite3_bind_text(put_stmt, 1, fullkey, fullkey_len, SQLITE_STATIC) != SQLITE_OK) {
-		ast_log(LOG_WARNING, "Couldn't bind key to stmt: %s\n", sqlite3_errmsg(astdb));
-		res = -1;
-	} else if (sqlite3_bind_text(put_stmt, 2, value, -1, SQLITE_STATIC) != SQLITE_OK) {
-		ast_log(LOG_WARNING, "Couldn't bind value to stmt: %s\n", sqlite3_errmsg(astdb));
-		res = -1;
-	} else if (sqlite3_step(put_stmt) != SQLITE_DONE) {
-		ast_log(LOG_WARNING, "Couldn't execute statment: %s\n", sqlite3_errmsg(astdb));
-		res = -1;
-	}
-	sqlite3_reset(put_stmt);
-	ast_mutex_unlock(&dblock);
-
-	return res; 
+	return db_put_raw(fullkey, fullkey_len, value, strlen(value) + 1);
 }
 
 int ast_db_get(const char *family, const char *key, char *value, int valuelen)
@@ -316,6 +365,7 @@
 		res = -1;
 	}
 	sqlite3_reset(del_stmt);
+	db_sync();
 	ast_mutex_unlock(&dblock);
 
 	return res;
@@ -351,6 +401,7 @@
 	}
 	res = sqlite3_changes(astdb);
 	sqlite3_reset(stmt);
+	db_sync();
 	ast_mutex_unlock(&dblock);
 
 	return res;
@@ -538,6 +589,7 @@
 {
 	char prefix[MAX_DB_FIELD];
 	int counter = 0;
+	sqlite3_stmt *stmt = gettree_stmt;
 
 	switch (cmd) {
 	case CLI_INIT:
@@ -560,24 +612,35 @@
 	} else if (a->argc == 2) {
 		/* Neither */
 		prefix[0] = '\0';
+		stmt = gettree_all_stmt;
+
 	} else {
 		return CLI_SHOWUSAGE;
 	}
 
 	ast_mutex_lock(&dblock);
-	while (sqlite3_step(gettree_stmt) == SQLITE_ROW) {
+	if (!ast_strlen_zero(prefix) && (sqlite3_bind_text(stmt, 1, prefix, -1, SQLITE_STATIC) != SQLITE_OK)) {
+		ast_log(LOG_WARNING, "Could bind %s to stmt: %s\n", prefix, sqlite3_errmsg(astdb));
+		sqlite3_reset(stmt);
+		ast_mutex_unlock(&dblock);
+		return NULL;
+	}
+
+	while (sqlite3_step(stmt) == SQLITE_ROW) {
 		const char *key_s, *value_s;
-		if (!(key_s = (const char *) sqlite3_column_text(gettree_stmt, 0))) {
-			break;
-		}
-		if (!(value_s = (const char *) sqlite3_column_text(gettree_stmt, 1))) {
-			break;
+		if (!(key_s = (const char *) sqlite3_column_text(stmt, 0))) {
+			ast_log(LOG_WARNING, "Skipping invalid key!\n");
+			continue;
+		}
+		if (!(value_s = (const char *) sqlite3_column_text(stmt, 1))) {
+			ast_log(LOG_WARNING, "Skipping invalid value!\n");
+			continue;
 		}
 		++counter;
 		ast_cli(a->fd, "%-50s: %-25s\n", key_s, value_s);
 	}
 
-	sqlite3_reset(gettree_stmt);
+	sqlite3_reset(stmt);
 	ast_mutex_unlock(&dblock);
 
 	ast_cli(a->fd, "%d results found.\n", counter);
@@ -753,7 +816,7 @@
 		astman_send_error(s, m, "Database entry not found");
 	else
 		astman_send_ack(s, m, "Key tree deleted successfully");
-	
+
 	return 0;
 }
 
@@ -785,13 +848,14 @@
 	for (;;) {
 		/* We're ok with spurious wakeups, so we don't worry about a predicate */
 		ast_cond_wait(&dbcond, &dblock);
+		ast_debug(10, "Committing astdb transaction\n");
 		if (ast_db_commit_transaction()) {
 			ast_db_rollback_transaction();
 		}
+		ast_db_begin_transaction();
 		ast_mutex_unlock(&dblock);
 		sleep(1);
 		ast_mutex_lock(&dblock);
-		ast_db_begin_transaction();
 	}
 
 	return NULL;
@@ -799,17 +863,18 @@
 
 int astdb_init(void)
 {
-	pthread_t dont_care;
-
-	ast_cond_init(&dbcond, NULL);
-	if (ast_pthread_create_background(&dont_care, NULL, db_sync_thread, NULL)) {
-		return -1;
-	}
+	pthread_t syncthread;
 
 	sqlite3_config(SQLITE_CONFIG_SINGLETHREAD);
 	if (db_init()) {
 		return -1;
 	}
+
+	ast_cond_init(&dbcond, NULL);
+	if (ast_pthread_create_background(&syncthread, NULL, db_sync_thread, NULL)) {
+		return -1;
+	}
+
 	ast_cli_register_multiple(cli_database, ARRAY_LEN(cli_database));
 	ast_manager_register_xml("DBGet", EVENT_FLAG_SYSTEM | EVENT_FLAG_REPORTING, manager_dbget);
 	ast_manager_register_xml("DBPut", EVENT_FLAG_SYSTEM, manager_dbput);




More information about the asterisk-commits mailing list