[asterisk-commits] oej: branch oej/adb-codename-appleraisin r177355 - in /team/oej/adb-codename-...

SVN commits to the Asterisk project asterisk-commits at lists.digium.com
Thu Feb 19 07:49:06 CST 2009


Author: oej
Date: Thu Feb 19 07:49:06 2009
New Revision: 177355

URL: http://svn.digium.com/svn-view/asterisk?view=rev&rev=177355
Log:
Backporting a lot of stuff from appleraising-trunk, including new parts of realtime.

Modified:
    team/oej/adb-codename-appleraisin/include/asterisk/config.h
    team/oej/adb-codename-appleraisin/main/config.c
    team/oej/adb-codename-appleraisin/main/db.c

Modified: team/oej/adb-codename-appleraisin/include/asterisk/config.h
URL: http://svn.digium.com/svn-view/asterisk/team/oej/adb-codename-appleraisin/include/asterisk/config.h?view=diff&rev=177355&r1=177354&r2=177355
==============================================================================
--- team/oej/adb-codename-appleraisin/include/asterisk/config.h (original)
+++ team/oej/adb-codename-appleraisin/include/asterisk/config.h Thu Feb 19 07:49:06 2009
@@ -49,6 +49,9 @@
 typedef struct ast_variable *realtime_var_get(const char *database, const char *table, va_list ap);
 typedef struct ast_config *realtime_multi_get(const char *database, const char *table, va_list ap);
 typedef int realtime_update(const char *database, const char *table, const char *keyfield, const char *entity, va_list ap);
+typedef int realtime_update2(const char *database, const char *table, va_list ap);
+typedef int realtime_store(const char *database, const char *table, va_list ap);
+typedef int realtime_destroy(const char *database, const char *table, const char *keyfield, const char *entity, va_list ap);
 
 struct ast_config_engine {
 	char *name;
@@ -56,6 +59,10 @@
 	realtime_var_get *realtime_func;
 	realtime_multi_get *realtime_multi_func;
 	realtime_update *update_func;
+	realtime_update2 *update2_func;
+	realtime_store *store_func;
+	realtime_destroy *destroy_func;
+
 	struct ast_config_engine *next;
 };
 
@@ -161,6 +168,47 @@
  * \param family which family/config to be checked
 */
 int ast_check_realtime(const char *family);
+/*! 
+ * \brief Update realtime configuration 
+ * \param family which family/config to be updated
+ * This function is used to update a parameter in realtime configuration space.
+ * It includes the ability to lookup a row based upon multiple key criteria.
+ * As a result, this function includes two sentinel values, one to terminate
+ * lookup values and the other to terminate the listing of fields to update.
+ * \return Number of rows affected, or -1 on error.
+ *
+ * Note that you should use the constant SENTINEL to terminate arguments, in
+ * order to preserve cross-platform compatibility.
+ */
+int ast_update2_realtime(const char *family, ...) ;
+
+/*! 
+ * \brief Create realtime configuration 
+ * \param family which family/config to be created
+ * This function is used to create a parameter in realtime configuration space.
+ * \return Number of rows affected, or -1 on error.
+ * On the MySQL engine only, for reasons of backwards compatibility, the return
+ * value is the insert ID.  This value is nonportable and may be changed in a
+ * future version to match the other engines.
+ *
+ * Note that you should use the constant SENTINEL to terminate arguments, in
+ * order to preserve cross-platform compatibility.
+ */
+int ast_store_realtime(const char *family, ...) ;
+
+/*! 
+ * \brief Destroy realtime configuration 
+ * \param family which family/config to be destroyed
+ * \param keyfield which field to use as the key
+ * \param lookup which value to look for in the key field to match the entry.
+ * This function is used to destroy an entry in realtime configuration space.
+ * Additional params are used as keys.
+ * \return Number of rows affected, or -1 on error.
+ *
+ * Note that you should use the constant SENTINEL to terminate arguments, in
+ * order to preserve cross-platform compatibility.
+ */
+int ast_destroy_realtime(const char *family, const char *keyfield, const char *lookup, ...) ;
 
 /*! \brief Free variable list 
  * \param var the linked list of variables to free

Modified: team/oej/adb-codename-appleraisin/main/config.c
URL: http://svn.digium.com/svn-view/asterisk/team/oej/adb-codename-appleraisin/main/config.c?view=diff&rev=177355&r1=177354&r2=177355
==============================================================================
--- team/oej/adb-codename-appleraisin/main/config.c (original)
+++ team/oej/adb-codename-appleraisin/main/config.c Thu Feb 19 07:49:06 2009
@@ -1475,6 +1475,57 @@
 	return res;
 }
 
+int ast_update2_realtime(const char *family, ...)
+{
+	struct ast_config_engine *eng;
+	int res = -1;
+	char db[256];
+	char table[256];
+	va_list ap;
+
+	va_start(ap, family);
+	eng = find_engine(family, db, sizeof(db), table, sizeof(table));
+	if (eng && eng->update2_func) 
+		res = eng->update2_func(db, table, ap);
+	va_end(ap);
+
+	return res;
+}
+
+int ast_store_realtime(const char *family, ...)
+{
+	struct ast_config_engine *eng;
+	int res = -1;
+	char db[256];
+	char table[256];
+	va_list ap;
+
+	va_start(ap, family);
+	eng = find_engine(family, db, sizeof(db), table, sizeof(table));
+	if (eng && eng->store_func) 
+		res = eng->store_func(db, table, ap);
+	va_end(ap);
+
+	return res;
+}
+
+int ast_destroy_realtime(const char *family, const char *keyfield, const char *lookup, ...)
+{
+	struct ast_config_engine *eng;
+	int res = -1;
+	char db[256];
+	char table[256];
+	va_list ap;
+
+	va_start(ap, lookup);
+	eng = find_engine(family, db, sizeof(db), table, sizeof(table));
+	if (eng && eng->destroy_func) 
+		res = eng->destroy_func(db, table, keyfield, lookup, ap);
+	va_end(ap);
+
+	return res;
+}
+
 static int config_command(int fd, int argc, char **argv) 
 {
 	struct ast_config_engine *eng;

Modified: team/oej/adb-codename-appleraisin/main/db.c
URL: http://svn.digium.com/svn-view/asterisk/team/oej/adb-codename-appleraisin/main/db.c?view=diff&rev=177355&r1=177354&r2=177355
==============================================================================
--- team/oej/adb-codename-appleraisin/main/db.c (original)
+++ team/oej/adb-codename-appleraisin/main/db.c Thu Feb 19 07:49:06 2009
@@ -57,24 +57,114 @@
 #ifdef __CYGWIN__
 #define dbopen __dbopen
 #endif
+static int db_rt;			/*!< Flag for realtime system */
+static char *db_rt_rtfamily = "astdb";	/*!< Realtime name tag */
+static char *db_rt_value = "value";	/*!< Database field name for values */
+static char *db_rt_family = "family";   /*!< Database field name for family */
+static char *db_rt_key = "keyname";     /*!< Database field name for key */
+static char *db_rt_sysnamelabel = "systemname"; /*!< Database field name for system name */
+static const char *db_rt_sysname;       /*!< From asterisk.conf or "asterisk" */
+
 
 static DB *astdb;
-static int db_realtime;
-static char *db_realtime_family = "astdb";
-static char *db_realtime_value = "value";
-static char *db_realtime_name = "name";  /* family/key */
 
 AST_MUTEX_DEFINE_STATIC(dblock);
 
+
+/*! \brief Initialize either realtime support or Asterisk ast-db. 
+
+	Note: Since realtime support is loaded after astdb, we can not do this early, but has to do the
+	check on need. Now, there's a risk an internal module (not a loaded module) use astdb before 
+	realtime is checked, but that's something we propably have to live with until we solve it.
+
+	Make sure that realtime modules are loaded before dundi and the channels.
+*/
 static int dbinit(void) 
 {
-	if (!astdb && !(astdb = dbopen((char *)ast_config_AST_DB, O_CREAT | O_RDWR, 0664, DB_BTREE, NULL))) {
+	if (db_rt) {
+		return 0;
+	}
+	db_rt = ast_check_realtime(db_rt_rtfamily);
+
+ 	if (!astdb && !(astdb = dbopen((char *)ast_config_AST_DB, O_CREAT | O_RDWR, 0664, DB_BTREE, NULL))) {
 		ast_log(LOG_WARNING, "Unable to open Asterisk database '%s': %s\n", ast_config_AST_DB, strerror(errno));
 		return -1;
 	}
 	return 0;
 }
 
+/*! \brief Load a set of entries from astdb/realtime. This is for all operations that
+   	work on a whole "tree" or "family" 
+	\note the calling function needs to destroy the result set with ast_config_destroy(resultset) 
+*/
+static struct ast_variable *db_realtime_getall(const char *family, const char *key)
+{
+	struct ast_variable *data, *returnset = NULL;
+	const char *keyname = NULL, *familyname = NULL;
+	struct ast_config *variablelist = NULL;
+	const char *cat = NULL;
+	char buf[512];
+
+	ast_log(LOG_DEBUG, ">>>>>> getall family: %s Key %s \n", family, key);
+
+	if (ast_strlen_zero(family)) {
+		/* Load all entries in the astdb */
+		if (ast_strlen_zero(key)) {
+			/* No variables given */
+			variablelist = ast_load_realtime_multientry(db_rt_rtfamily, db_rt_sysnamelabel, db_rt_sysname, NULL);
+		} else {
+			/* Only key given */
+			variablelist = ast_load_realtime_multientry(db_rt_rtfamily, db_rt_sysnamelabel, db_rt_sysname, db_rt_key, key, NULL);
+		}
+	} else {
+		if (ast_strlen_zero(key)) {
+			variablelist = ast_load_realtime_multientry(db_rt_rtfamily, db_rt_sysnamelabel, db_rt_sysname, db_rt_family, family, NULL);
+		} else {
+			variablelist = ast_load_realtime_multientry(db_rt_rtfamily, db_rt_sysnamelabel, db_rt_sysname, db_rt_family, family, db_rt_key, key, NULL);
+		}
+	}
+	if (!variablelist) {
+		return NULL;
+	}
+	/* Now we need to start converting all this stuff. We have thre ast_variable sets per record in the result set */
+	while ((cat = ast_category_browse(variablelist, cat))) {
+		struct ast_variable *resultset, *cur;
+
+		cur = resultset = ast_variable_browse(variablelist, cat);
+	
+		/* skip the system name */
+		while (cur) {
+			ast_log(LOG_DEBUG, ">>>> Found name %s ...\n", cur->name);
+			if (!strcmp(cur->name, db_rt_family)) {
+				familyname = cur->value;
+			} else if (!strcmp(cur->name, db_rt_key)) {
+				keyname = cur->value;
+			} else if (!strcmp(cur->name, db_rt_value)) {
+				snprintf(buf, sizeof(buf), "/%s/%s", S_OR(familyname, ""), S_OR(keyname, ""));
+				data = ast_variable_new(buf, S_OR(cur->value, "astdb-realtime"));
+				familyname = keyname = NULL;
+				ast_log(LOG_DEBUG, "#### Found Variable %s with value %s \n", buf, cur->value);
+				/* Add this to the returnset */
+				data->next = returnset;
+				returnset = data;
+			} else {
+				if (ast_strlen_zero(cur->name)) {
+					ast_log(LOG_DEBUG, "#### Skipping  strange record \n");
+				} else {
+					ast_log(LOG_DEBUG, "#### Skipping  %s with value %s \n", cur->name, cur->value);
+				}
+			}
+			cur = cur->next;
+		}
+		//if (resultset)
+			//ast_variables_destroy(resultset);
+	}
+
+	/* Clean up the resultset */
+	ast_config_destroy(variablelist);
+	
+	return returnset;
+}
 
 static inline int keymatch(const char *key, const char *prefix)
 {
@@ -147,35 +237,51 @@
 	ast_mutex_unlock(&dblock);
 	return 0;
 }
-
 int ast_db_put(const char *family, const char *keys, char *value)
 {
-	char fullkey[256];
 	DBT key, data;
-	int res, fullkeylen;
-
-	if (!db_realtime) {
+	int res;
+
+	if (!db_rt) {
 		ast_mutex_lock(&dblock);
 		if (dbinit()) {
 			ast_mutex_unlock(&dblock);
 			return -1;
 		}
-	}
-
-	fullkeylen = snprintf(fullkey, sizeof(fullkey), "/%s/%s", family, keys);
-	if (db_realtime) {
-		res = ast_update_realtime(db_realtime_name, fullkey, db_realtime_value, value);
-	} else {
+		if (db_rt)
+			ast_mutex_unlock(&dblock);
+	}
+
+	if (db_rt) {
+		int rowsaffected ;
+		/* Now, the question here is if we're overwriting or adding 
+			First, let's try updating it.
+		*/
+		ast_log(LOG_DEBUG, ".... Trying ast_update_realtime\n");
+		/* Update_realtime with mysql returns the number of rows affected */
+		rowsaffected = ast_update2_realtime(db_rt_rtfamily, db_rt_family, family, db_rt_key, keys, db_rt_sysnamelabel, db_rt_sysname, NULL, db_rt_value, value, NULL);
+		res = rowsaffected > 0 ? 0 : 1;
+		if (res) {
+			ast_log(LOG_DEBUG, ".... Trying ast_store_realtime\n");
+			/* Update failed, let's try adding a new record */
+			res = ast_store_realtime(db_rt_rtfamily, db_rt_sysnamelabel, db_rt_sysname, db_rt_family, family, db_rt_key, keys, db_rt_value, value, NULL);
+			/* Ast_store_realtime with mysql returns 0 if ok, -1 if bad */
+
+		}
+	} else {
+		int fullkeylen;
+		char fullkey[256];
+		fullkeylen = snprintf(fullkey, sizeof(fullkey), "/%s/%s", family, keys);
 		memset(&key, 0, sizeof(key));
 		memset(&data, 0, sizeof(data));
 		key.data = fullkey;
 		key.size = fullkeylen + 1;
-		data.data = value;
+		data.data = (char *) value;
 		data.size = strlen(value) + 1;
 		res = astdb->put(astdb, &key, &data, 0);
 		astdb->sync(astdb, 0);
-		ast_mutex_unlock(&dblock);
-	} 
+	}
+	ast_mutex_unlock(&dblock);
 	if (res)
 		ast_log(LOG_WARNING, "Unable to put value '%s' for key '%s' in family '%s'\n", value, keys, family);
 	return res;
@@ -185,45 +291,54 @@
 {
 	char fullkey[256] = "";
 	DBT key, data;
-	int res=0, fullkeylen;
-	struct ast_variable *var;
-
-	if (!db_realtime) {
+	int res, fullkeylen;
+
+	if (!db_rt) {
 		ast_mutex_lock(&dblock);
 		if (dbinit()) {
 			ast_mutex_unlock(&dblock);
 			return -1;
 		}
-	}
+		if (db_rt) {
+			ast_mutex_unlock(&dblock);
+		}
+	}
+
+	if (db_rt) {
+		struct ast_variable *var, *res;
+		memset(value, 0, valuelen);
+
+		res = var = ast_load_realtime(db_rt_rtfamily, db_rt_sysnamelabel, db_rt_sysname, db_rt_family, family, db_rt_key, keys, NULL);
+		if (!var) {
+			return 1;
+		} 
+		/* We should only have one value here, so let's make this simple... */
+		while (res) {
+			if (!strcasecmp(res->name, db_rt_value)) {
+				ast_copy_string(value, res->value, (valuelen > strlen(res->value) ) ? strlen(res->value) +1: valuelen);
+				res = NULL;
+			} else {
+				res = res->next;
+			}
+		}
+		
+		ast_variables_destroy(var);
+		return 0;
+	} 
 	fullkeylen = snprintf(fullkey, sizeof(fullkey), "/%s/%s", family, keys);
-	if (db_realtime) {
-		var = ast_load_realtime(db_realtime_family, db_realtime_name, fullkey, NULL);
-		if (!var) {
-			res = 0;
-		} else {
-			/* We should only have one value here, so let's make this simple... */
-			ast_copy_string(value, var->value, (valuelen > strlen(var->value)) ? strlen(var->value) : valuelen);
-			
-			ast_variables_destroy(var);
-			res = 1;
-		}
-		return res;
-	} 
-
 	memset(&key, 0, sizeof(key));
 	memset(&data, 0, sizeof(data));
 	memset(value, 0, valuelen);
 	key.data = fullkey;
 	key.size = fullkeylen + 1;
-
+	
 	res = astdb->get(astdb, &key, &data, 0);
 	
 	ast_mutex_unlock(&dblock);
 
 	/* Be sure to NULL terminate our data either way */
 	if (res) {
-		if (option_debug)
-			ast_log(LOG_DEBUG, "Unable to find key '%s' in family '%s'\n", keys, family);
+		ast_log(LOG_DEBUG, "Unable to find key '%s' in family '%s'\n", keys, family);
 	} else {
 #if 0
 		printf("Got value of size %d\n", data.size);
@@ -245,26 +360,37 @@
 	DBT key;
 	int res, fullkeylen;
 
-	ast_mutex_lock(&dblock);
-	if (!db_realtime && dbinit()) {
+	if (!db_rt) {
+		ast_mutex_lock(&dblock);
+		if (dbinit()) {
+			ast_mutex_unlock(&dblock);
+			return -1;
+		}
+		if (db_rt)
+			ast_mutex_unlock(&dblock);
+	}
+	
+	if (db_rt) {
+		int rowcount = ast_destroy_realtime(db_rt_rtfamily, db_rt_sysnamelabel, db_rt_sysname, db_rt_family, family, db_rt_key, keys, NULL);
+		res = rowcount > 0 ? 0 : 1;
+	} else {
+		fullkeylen = snprintf(fullkey, sizeof(fullkey), "/%s/%s", family, keys);
+		memset(&key, 0, sizeof(key));
+		key.data = fullkey;
+		key.size = fullkeylen + 1;
+	
+		res = astdb->del(astdb, &key, 0);
+		astdb->sync(astdb, 0);
 		ast_mutex_unlock(&dblock);
-		return -1;
-	}
-	
-	fullkeylen = snprintf(fullkey, sizeof(fullkey), "/%s/%s", family, keys);
-	memset(&key, 0, sizeof(key));
-	key.data = fullkey;
-	key.size = fullkeylen + 1;
-	
-	res = astdb->del(astdb, &key, 0);
-	astdb->sync(astdb, 0);
-	
-	ast_mutex_unlock(&dblock);
-
-	if (res && option_debug)
+	}
+
+	if (res) {
 		ast_log(LOG_DEBUG, "Unable to find key '%s' in family '%s'\n", keys, family);
+	}
 	return res;
 }
+
+
 
 static int database_put(int fd, int argc, char *argv[])
 {
@@ -325,6 +451,28 @@
 		ast_cli(fd, "Database entries removed.\n");
 	}
 	return RESULT_SUCCESS;
+}
+
+static void handle_cli_database_show_realtime(int fd, const char *family, const char *key)
+{
+	struct ast_variable *resultset;
+	struct ast_variable *cur;
+	int counter = 0;
+
+	dbinit();
+	if (!db_rt) {
+		ast_cli(fd, "Error: Can't connect to astdb/realtime\n");
+		return;
+	}
+
+	cur = resultset = db_realtime_getall(family, key);
+	while (cur) {
+		ast_cli(fd, "%-40s: %-25s\n", cur->name, S_OR(cur->value, ""));
+		cur = cur->next;
+		counter++;
+	}
+	ast_cli(fd, "%d results found.\n", counter);
+	ast_variables_destroy(resultset);
 }
 
 static int database_show(int fd, int argc, char *argv[])
@@ -347,11 +495,20 @@
 	} else {
 		return RESULT_SHOWUSAGE;
 	}
-	ast_mutex_lock(&dblock);
-	if (!db_realtime && dbinit()) {
-		ast_mutex_unlock(&dblock);
-		ast_cli(fd, "Database unavailable\n");
-		return RESULT_SUCCESS;	
+
+	if (!db_rt) {
+		ast_mutex_lock(&dblock);
+		if (dbinit()) {
+			ast_mutex_unlock(&dblock);
+			ast_cli(fd, "Database unavailable\n");
+			return RESULT_SUCCESS;	
+		}
+		if (db_rt)
+			ast_mutex_unlock(&dblock);
+	}
+	if (db_rt) {
+		handle_cli_database_show_realtime(fd, argc >= 3 ? argv[2] : "", argc == 4 ? argv[3] : "");
+		return RESULT_SUCCESS;
 	}
 	memset(&key, 0, sizeof(key));
 	memset(&data, 0, sizeof(data));
@@ -391,10 +548,18 @@
 	} else {
 		return RESULT_SHOWUSAGE;
 	}
-	ast_mutex_lock(&dblock);
-	if (!db_realtime && dbinit()) {
-		ast_mutex_unlock(&dblock);
-		ast_cli(fd, "Database unavailable\n");
+	if (!db_rt) {
+		ast_mutex_lock(&dblock);
+		if (dbinit()) {
+			ast_mutex_unlock(&dblock);
+			ast_cli(fd, "Database unavailable\n");
+			return RESULT_SUCCESS;	
+		}
+		if (db_rt)
+			ast_mutex_unlock(&dblock);
+	}
+	if (db_rt) {
+		handle_cli_database_show_realtime(fd, "", argv[2]);
 		return RESULT_SUCCESS;	
 	}
 	memset(&key, 0, sizeof(key));
@@ -444,7 +609,7 @@
 		prefix[0] = '\0';
 	}
 	ast_mutex_lock(&dblock);
-	if (!db_realtime && dbinit()) {
+	if (!db_rt && dbinit()) {
 		ast_mutex_unlock(&dblock);
 		ast_log(LOG_WARNING, "Database unavailable\n");
 		return NULL;	
@@ -613,8 +778,8 @@
 int astdb_init(void)
 {
 	/* Check if we have realtime astdb enabled */
-	db_realtime = ast_check_realtime("astdb");
-	if (!db_realtime) {
+	db_rt = ast_check_realtime("astdb");
+	if (!db_rt) {
 		dbinit();
 	} else {
 		ast_log(LOG_DEBUG, "***** Kör ASTDB i realtime mode! ******************\n");




More information about the asterisk-commits mailing list