| 
									
										
										
										
											2003-01-30 15:03:20 +00:00
										 |  |  | /*
 | 
					
						
							| 
									
										
										
										
											2005-09-14 20:46:50 +00:00
										 |  |  |  * Asterisk -- An open source telephony toolkit. | 
					
						
							| 
									
										
										
										
											2003-01-30 15:03:20 +00:00
										 |  |  |  * | 
					
						
							| 
									
										
										
										
											2005-09-14 20:46:50 +00:00
										 |  |  |  * Copyright (C) 1999 - 2005, Digium, Inc. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * Mark Spencer <markster@digium.com> | 
					
						
							| 
									
										
										
										
											2003-01-30 15:03:20 +00:00
										 |  |  |  * | 
					
						
							| 
									
										
										
										
											2005-09-14 20:46:50 +00:00
										 |  |  |  * See http://www.asterisk.org for more information about
 | 
					
						
							|  |  |  |  * the Asterisk project. Please do not directly contact | 
					
						
							|  |  |  |  * any of the maintainers of this project for assistance; | 
					
						
							|  |  |  |  * the project provides a web site, mailing lists and IRC | 
					
						
							|  |  |  |  * channels for your use. | 
					
						
							| 
									
										
										
										
											2003-01-30 15:03:20 +00:00
										 |  |  |  * | 
					
						
							|  |  |  |  * This program is free software, distributed under the terms of | 
					
						
							| 
									
										
										
										
											2005-09-14 20:46:50 +00:00
										 |  |  |  * the GNU General Public License Version 2. See the LICENSE file | 
					
						
							|  |  |  |  * at the top of the source tree. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-10-24 20:12:06 +00:00
										 |  |  | /*! \file
 | 
					
						
							| 
									
										
										
										
											2005-09-14 20:46:50 +00:00
										 |  |  |  * | 
					
						
							| 
									
										
										
										
											2005-10-24 20:12:06 +00:00
										 |  |  |  * \brief ASTdb Management | 
					
						
							| 
									
										
										
										
											2005-09-14 20:46:50 +00:00
										 |  |  |  * | 
					
						
							| 
									
										
										
										
											2011-07-06 20:58:12 +00:00
										 |  |  |  * \author Mark Spencer <markster@digium.com> | 
					
						
							| 
									
										
										
										
											2005-12-30 21:18:06 +00:00
										 |  |  |  * | 
					
						
							|  |  |  |  * \note DB3 is licensed under Sleepycat Public License and is thus incompatible | 
					
						
							| 
									
										
										
										
											2011-07-06 20:58:12 +00:00
										 |  |  |  * with GPL.  To avoid having to make another exception (and complicate | 
					
						
							|  |  |  |  * licensing even further) we elect to use DB1 which is BSD licensed | 
					
						
							| 
									
										
										
										
											2003-01-30 15:03:20 +00:00
										 |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-06-15 16:20:16 +00:00
										 |  |  | /*** MODULEINFO
 | 
					
						
							|  |  |  | 	<support_level>core</support_level> | 
					
						
							|  |  |  |  ***/ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-06-07 18:54:56 +00:00
										 |  |  | #include "asterisk.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-11-20 22:18:21 +00:00
										 |  |  | #include "asterisk/_private.h"
 | 
					
						
							| 
									
										
										
										
											2007-11-20 23:16:15 +00:00
										 |  |  | #include "asterisk/paths.h"	/* use ast_config_AST_DB */
 | 
					
						
							| 
									
										
										
										
											2003-01-30 15:03:20 +00:00
										 |  |  | #include <sys/time.h>
 | 
					
						
							| 
									
										
										
										
											2011-07-06 20:58:12 +00:00
										 |  |  | #include <sys/types.h>
 | 
					
						
							|  |  |  | #include <sys/stat.h>
 | 
					
						
							|  |  |  | #include <unistd.h>
 | 
					
						
							| 
									
										
										
										
											2003-01-30 15:03:20 +00:00
										 |  |  | #include <signal.h>
 | 
					
						
							|  |  |  | #include <dirent.h>
 | 
					
						
							| 
									
										
										
										
											2011-07-06 20:58:12 +00:00
										 |  |  | #include <sqlite3.h>
 | 
					
						
							| 
									
										
										
										
											2005-04-22 13:11:34 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-04-21 06:02:45 +00:00
										 |  |  | #include "asterisk/channel.h"
 | 
					
						
							|  |  |  | #include "asterisk/file.h"
 | 
					
						
							|  |  |  | #include "asterisk/app.h"
 | 
					
						
							|  |  |  | #include "asterisk/dsp.h"
 | 
					
						
							|  |  |  | #include "asterisk/astdb.h"
 | 
					
						
							|  |  |  | #include "asterisk/cli.h"
 | 
					
						
							|  |  |  | #include "asterisk/utils.h"
 | 
					
						
							|  |  |  | #include "asterisk/manager.h"
 | 
					
						
							| 
									
										
										
										
											2003-01-30 15:03:20 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-05-22 17:52:35 +00:00
										 |  |  | /*** DOCUMENTATION
 | 
					
						
							|  |  |  | 	<manager name="DBGet" language="en_US"> | 
					
						
							|  |  |  | 		<synopsis> | 
					
						
							|  |  |  | 			Get DB Entry. | 
					
						
							|  |  |  | 		</synopsis> | 
					
						
							|  |  |  | 		<syntax> | 
					
						
							|  |  |  | 			<xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" /> | 
					
						
							|  |  |  | 			<parameter name="Family" required="true" /> | 
					
						
							|  |  |  | 			<parameter name="Key" required="true" /> | 
					
						
							|  |  |  | 		</syntax> | 
					
						
							|  |  |  | 		<description> | 
					
						
							|  |  |  | 		</description> | 
					
						
							|  |  |  | 	</manager> | 
					
						
							|  |  |  | 	<manager name="DBPut" language="en_US"> | 
					
						
							|  |  |  | 		<synopsis> | 
					
						
							|  |  |  | 			Put DB entry. | 
					
						
							|  |  |  | 		</synopsis> | 
					
						
							|  |  |  | 		<syntax> | 
					
						
							|  |  |  | 			<xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" /> | 
					
						
							|  |  |  | 			<parameter name="Family" required="true" /> | 
					
						
							|  |  |  | 			<parameter name="Key" required="true" /> | 
					
						
							|  |  |  | 			<parameter name="Val" /> | 
					
						
							|  |  |  | 		</syntax> | 
					
						
							|  |  |  | 		<description> | 
					
						
							|  |  |  | 		</description> | 
					
						
							|  |  |  | 	</manager> | 
					
						
							|  |  |  | 	<manager name="DBDel" language="en_US"> | 
					
						
							|  |  |  | 		<synopsis> | 
					
						
							|  |  |  | 			Delete DB entry. | 
					
						
							|  |  |  | 		</synopsis> | 
					
						
							|  |  |  | 		<syntax> | 
					
						
							|  |  |  | 			<xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" /> | 
					
						
							|  |  |  | 			<parameter name="Family" required="true" /> | 
					
						
							|  |  |  | 			<parameter name="Key" required="true" /> | 
					
						
							|  |  |  | 		</syntax> | 
					
						
							|  |  |  | 		<description> | 
					
						
							|  |  |  | 		</description> | 
					
						
							|  |  |  | 	</manager> | 
					
						
							|  |  |  | 	<manager name="DBDelTree" language="en_US"> | 
					
						
							|  |  |  | 		<synopsis> | 
					
						
							|  |  |  | 			Delete DB Tree. | 
					
						
							|  |  |  | 		</synopsis> | 
					
						
							|  |  |  | 		<syntax> | 
					
						
							|  |  |  | 			<xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" /> | 
					
						
							|  |  |  | 			<parameter name="Family" required="true" /> | 
					
						
							|  |  |  | 			<parameter name="Key" /> | 
					
						
							|  |  |  | 		</syntax> | 
					
						
							|  |  |  | 		<description> | 
					
						
							|  |  |  | 		</description> | 
					
						
							|  |  |  | 	</manager> | 
					
						
							|  |  |  |  ***/ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-06-10 15:30:50 +00:00
										 |  |  | #define MAX_DB_FIELD 256
 | 
					
						
							| 
									
										
										
										
											2004-06-09 01:45:08 +00:00
										 |  |  | AST_MUTEX_DEFINE_STATIC(dblock); | 
					
						
							| 
									
										
										
										
											2010-09-13 22:13:27 +00:00
										 |  |  | static ast_cond_t dbcond; | 
					
						
							| 
									
										
										
										
											2011-07-06 20:58:12 +00:00
										 |  |  | static sqlite3 *astdb; | 
					
						
							|  |  |  | static pthread_t syncthread; | 
					
						
							|  |  |  | static int doexit; | 
					
						
							| 
									
										
										
										
											2014-03-14 16:19:21 +00:00
										 |  |  | static int dosync; | 
					
						
							| 
									
										
										
										
											2010-09-13 22:13:27 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | static void db_sync(void); | 
					
						
							| 
									
										
										
										
											2003-01-30 15:03:20 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-07-06 20:58:12 +00:00
										 |  |  | #define DEFINE_SQL_STATEMENT(stmt,sql) static sqlite3_stmt *stmt; \
 | 
					
						
							|  |  |  | 	const char stmt##_sql[] = sql; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-07-24 21:01:37 +00:00
										 |  |  | DEFINE_SQL_STATEMENT(put_stmt, "INSERT OR REPLACE INTO astdb (key, value) VALUES (?, ?)") | 
					
						
							| 
									
										
										
										
											2011-07-06 20:58:12 +00:00
										 |  |  | DEFINE_SQL_STATEMENT(get_stmt, "SELECT value FROM astdb WHERE key=?") | 
					
						
							|  |  |  | DEFINE_SQL_STATEMENT(del_stmt, "DELETE FROM astdb WHERE key=?") | 
					
						
							| 
									
										
										
										
											2011-11-18 22:20:47 +00:00
										 |  |  | DEFINE_SQL_STATEMENT(deltree_stmt, "DELETE FROM astdb WHERE key || '/' LIKE ? || '/' || '%'") | 
					
						
							| 
									
										
										
										
											2011-07-06 20:58:12 +00:00
										 |  |  | DEFINE_SQL_STATEMENT(deltree_all_stmt, "DELETE FROM astdb") | 
					
						
							| 
									
										
										
										
											2012-01-16 14:31:37 +00:00
										 |  |  | DEFINE_SQL_STATEMENT(gettree_stmt, "SELECT key, value FROM astdb WHERE key || '/' LIKE ? || '/' || '%' ORDER BY key") | 
					
						
							|  |  |  | DEFINE_SQL_STATEMENT(gettree_all_stmt, "SELECT key, value FROM astdb ORDER BY key") | 
					
						
							| 
									
										
										
										
											2012-01-16 17:12:36 +00:00
										 |  |  | DEFINE_SQL_STATEMENT(showkey_stmt, "SELECT key, value FROM astdb WHERE key LIKE '%' || '/' || ? ORDER BY key") | 
					
						
							| 
									
										
										
										
											2011-07-06 20:58:12 +00:00
										 |  |  | DEFINE_SQL_STATEMENT(create_astdb_stmt, "CREATE TABLE IF NOT EXISTS astdb(key VARCHAR(256), value VARCHAR(256), PRIMARY KEY(key))") | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-12-07 15:19:40 -05:00
										 |  |  | /* This query begs an explanation:
 | 
					
						
							|  |  |  |  * | 
					
						
							| 
									
										
										
										
											2017-12-20 12:14:54 -05:00
										 |  |  |  * First, the parameter binding syntax used here is slightly different than the other | 
					
						
							| 
									
										
										
										
											2017-12-07 15:19:40 -05:00
										 |  |  |  * queries in that we use a numbered parameter so that we can bind once and get the same | 
					
						
							|  |  |  |  * value substituted multiple times within the executed query. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * Second, the key comparison is being used to find all keys that are lexicographically | 
					
						
							|  |  |  |  * greater than the provided key, but less than the provided key with a high (but | 
					
						
							|  |  |  |  * invalid) Unicode codepoint appended to it. This will give us all keys in the database | 
					
						
							|  |  |  |  * that have 'key' as a prefix and performs much better than the equivalent "LIKE key || | 
					
						
							|  |  |  |  * '%'" operation. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | DEFINE_SQL_STATEMENT(gettree_prefix_stmt, "SELECT key, value FROM astdb WHERE key > ?1 AND key <= ?1 || X'ffff'") | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-07-06 20:58:12 +00:00
										 |  |  | static int init_stmt(sqlite3_stmt **stmt, const char *sql, size_t len) | 
					
						
							| 
									
										
										
										
											2003-01-30 15:03:20 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2011-07-06 20:58:12 +00:00
										 |  |  | 	ast_mutex_lock(&dblock); | 
					
						
							| 
									
										
										
										
											2011-07-07 16:50:54 +00:00
										 |  |  | 	if (sqlite3_prepare(astdb, sql, len, stmt, NULL) != SQLITE_OK) { | 
					
						
							| 
									
										
										
										
											2011-07-06 20:58:12 +00:00
										 |  |  | 		ast_log(LOG_WARNING, "Couldn't prepare statement '%s': %s\n", sql, sqlite3_errmsg(astdb)); | 
					
						
							|  |  |  | 		ast_mutex_unlock(&dblock); | 
					
						
							| 
									
										
										
										
											2006-02-09 16:59:50 +00:00
										 |  |  | 		return -1; | 
					
						
							| 
									
										
										
										
											2003-01-30 15:03:20 +00:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2011-07-06 20:58:12 +00:00
										 |  |  | 	ast_mutex_unlock(&dblock); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-02-09 16:59:50 +00:00
										 |  |  | 	return 0; | 
					
						
							| 
									
										
										
										
											2003-01-30 15:03:20 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-11-04 01:19:43 +00:00
										 |  |  | /*! \internal
 | 
					
						
							|  |  |  |  * \brief Clean up the prepared SQLite3 statement | 
					
						
							|  |  |  |  * \note dblock should already be locked prior to calling this method | 
					
						
							|  |  |  |  */ | 
					
						
							| 
									
										
										
										
											2013-12-19 16:33:09 +00:00
										 |  |  | static int clean_stmt(sqlite3_stmt **stmt, const char *sql) | 
					
						
							| 
									
										
										
										
											2012-11-04 01:19:43 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2013-12-19 16:33:09 +00:00
										 |  |  | 	if (sqlite3_finalize(*stmt) != SQLITE_OK) { | 
					
						
							| 
									
										
										
										
											2012-11-04 01:19:43 +00:00
										 |  |  | 		ast_log(LOG_WARNING, "Couldn't finalize statement '%s': %s\n", sql, sqlite3_errmsg(astdb)); | 
					
						
							| 
									
										
										
										
											2013-12-19 16:33:09 +00:00
										 |  |  | 		*stmt = NULL; | 
					
						
							| 
									
										
										
										
											2012-11-04 01:19:43 +00:00
										 |  |  | 		return -1; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2013-12-19 16:33:09 +00:00
										 |  |  | 	*stmt = NULL; | 
					
						
							| 
									
										
										
										
											2012-11-04 01:19:43 +00:00
										 |  |  | 	return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*! \internal
 | 
					
						
							|  |  |  |  * \brief Clean up all prepared SQLite3 statements | 
					
						
							|  |  |  |  * \note dblock should already be locked prior to calling this method | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | static void clean_statements(void) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2013-12-19 16:33:09 +00:00
										 |  |  | 	clean_stmt(&get_stmt, get_stmt_sql); | 
					
						
							|  |  |  | 	clean_stmt(&del_stmt, del_stmt_sql); | 
					
						
							|  |  |  | 	clean_stmt(&deltree_stmt, deltree_stmt_sql); | 
					
						
							|  |  |  | 	clean_stmt(&deltree_all_stmt, deltree_all_stmt_sql); | 
					
						
							|  |  |  | 	clean_stmt(&gettree_stmt, gettree_stmt_sql); | 
					
						
							|  |  |  | 	clean_stmt(&gettree_all_stmt, gettree_all_stmt_sql); | 
					
						
							| 
									
										
										
										
											2017-12-07 15:19:40 -05:00
										 |  |  | 	clean_stmt(&gettree_prefix_stmt, gettree_prefix_stmt_sql); | 
					
						
							| 
									
										
										
										
											2013-12-19 16:33:09 +00:00
										 |  |  | 	clean_stmt(&showkey_stmt, showkey_stmt_sql); | 
					
						
							|  |  |  | 	clean_stmt(&put_stmt, put_stmt_sql); | 
					
						
							|  |  |  | 	clean_stmt(&create_astdb_stmt, create_astdb_stmt_sql); | 
					
						
							| 
									
										
										
										
											2012-11-04 01:19:43 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-07-06 20:58:12 +00:00
										 |  |  | static int init_statements(void) | 
					
						
							| 
									
										
										
										
											2003-01-30 15:03:20 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2018-10-18 12:32:26 -05:00
										 |  |  | 	/* Don't initialize create_astdb_statement here as the astdb table needs to exist
 | 
					
						
							|  |  |  | 	 * brefore these statements can be initialized */ | 
					
						
							| 
									
										
										
										
											2011-07-06 20:58:12 +00:00
										 |  |  | 	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)) | 
					
						
							|  |  |  | 	|| init_stmt(&deltree_all_stmt, deltree_all_stmt_sql, sizeof(deltree_all_stmt_sql)) | 
					
						
							|  |  |  | 	|| init_stmt(&gettree_stmt, gettree_stmt_sql, sizeof(gettree_stmt_sql)) | 
					
						
							|  |  |  | 	|| init_stmt(&gettree_all_stmt, gettree_all_stmt_sql, sizeof(gettree_all_stmt_sql)) | 
					
						
							| 
									
										
										
										
											2017-12-07 15:19:40 -05:00
										 |  |  | 	|| init_stmt(&gettree_prefix_stmt, gettree_prefix_stmt_sql, sizeof(gettree_prefix_stmt_sql)) | 
					
						
							| 
									
										
										
										
											2011-07-06 20:58:12 +00:00
										 |  |  | 	|| init_stmt(&showkey_stmt, showkey_stmt_sql, sizeof(showkey_stmt_sql)) | 
					
						
							|  |  |  | 	|| init_stmt(&put_stmt, put_stmt_sql, sizeof(put_stmt_sql)); | 
					
						
							| 
									
										
										
										
											2003-01-30 15:03:20 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-07-06 20:58:12 +00:00
										 |  |  | static int convert_bdb_to_sqlite3(void) | 
					
						
							| 
									
										
										
										
											2004-12-22 01:07:02 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2011-07-06 20:58:12 +00:00
										 |  |  | 	char *cmd; | 
					
						
							|  |  |  | 	int res; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-11-02 18:40:20 -05:00
										 |  |  | 	res = ast_asprintf(&cmd, "%s/astdb2sqlite3 '%s'\n", ast_config_AST_SBIN_DIR, ast_config_AST_DB); | 
					
						
							|  |  |  | 	if (0 <= res) { | 
					
						
							|  |  |  | 		res = ast_safe_system(cmd); | 
					
						
							|  |  |  | 		ast_free(cmd); | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2011-07-06 20:58:12 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	return res; | 
					
						
							| 
									
										
										
										
											2004-12-22 01:07:02 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-07-06 20:58:12 +00:00
										 |  |  | static int db_create_astdb(void) | 
					
						
							| 
									
										
										
										
											2003-01-30 15:03:20 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2011-07-06 20:58:12 +00:00
										 |  |  | 	int res = 0; | 
					
						
							| 
									
										
										
										
											2011-06-10 15:30:50 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-07-06 20:58:12 +00:00
										 |  |  | 	if (!create_astdb_stmt) { | 
					
						
							|  |  |  | 		init_stmt(&create_astdb_stmt, create_astdb_stmt_sql, sizeof(create_astdb_stmt_sql)); | 
					
						
							| 
									
										
										
										
											2011-06-10 15:30:50 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-07-06 20:58:12 +00:00
										 |  |  | 	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); | 
					
						
							| 
									
										
										
										
											2011-06-10 15:30:50 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-07-06 20:58:12 +00:00
										 |  |  | 	return res; | 
					
						
							| 
									
										
										
										
											2011-06-10 15:30:50 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-07-06 20:58:12 +00:00
										 |  |  | static int db_open(void) | 
					
						
							| 
									
										
										
										
											2011-06-10 15:30:50 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2011-07-06 20:58:12 +00:00
										 |  |  | 	char *dbname; | 
					
						
							|  |  |  | 	struct stat dont_care; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-07-31 20:21:43 +00:00
										 |  |  | 	if (!(dbname = ast_alloca(strlen(ast_config_AST_DB) + sizeof(".sqlite3")))) { | 
					
						
							| 
									
										
										
										
											2011-07-06 20:58:12 +00:00
										 |  |  | 		return -1; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	strcpy(dbname, ast_config_AST_DB); | 
					
						
							|  |  |  | 	strcat(dbname, ".sqlite3"); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (stat(dbname, &dont_care) && !stat(ast_config_AST_DB, &dont_care)) { | 
					
						
							|  |  |  | 		if (convert_bdb_to_sqlite3()) { | 
					
						
							|  |  |  | 			ast_log(LOG_ERROR, "*** Database conversion failed!\n"); | 
					
						
							|  |  |  | 			ast_log(LOG_ERROR, "*** Asterisk now uses SQLite3 for its internal\n"); | 
					
						
							|  |  |  | 			ast_log(LOG_ERROR, "*** database. Conversion from the old astdb\n"); | 
					
						
							|  |  |  | 			ast_log(LOG_ERROR, "*** failed. Most likely the astdb2sqlite3 utility\n"); | 
					
						
							|  |  |  | 			ast_log(LOG_ERROR, "*** was not selected for build. To convert the\n"); | 
					
						
							|  |  |  | 			ast_log(LOG_ERROR, "*** old astdb, please delete '%s'\n", dbname); | 
					
						
							|  |  |  | 			ast_log(LOG_ERROR, "*** and re-run 'make menuselect' and select astdb2sqlite3\n"); | 
					
						
							|  |  |  | 			ast_log(LOG_ERROR, "*** in the Utilities section, then 'make && make install'.\n"); | 
					
						
							| 
									
										
										
										
											2011-10-10 22:58:10 +00:00
										 |  |  | 			ast_log(LOG_ERROR, "*** It is also imperative that the user under which\n"); | 
					
						
							|  |  |  | 			ast_log(LOG_ERROR, "*** Asterisk runs have write permission to the directory\n"); | 
					
						
							|  |  |  | 			ast_log(LOG_ERROR, "*** where the database resides.\n"); | 
					
						
							| 
									
										
										
										
											2011-07-06 20:58:12 +00:00
										 |  |  | 			sleep(5); | 
					
						
							|  |  |  | 		} else { | 
					
						
							|  |  |  | 			ast_log(LOG_NOTICE, "Database conversion succeeded!\n"); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2011-06-10 15:30:50 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	ast_mutex_lock(&dblock); | 
					
						
							| 
									
										
										
										
											2011-07-07 16:50:54 +00:00
										 |  |  | 	if (sqlite3_open(dbname, &astdb) != SQLITE_OK) { | 
					
						
							| 
									
										
										
										
											2011-07-06 20:58:12 +00:00
										 |  |  | 		ast_log(LOG_WARNING, "Unable to open Asterisk database '%s': %s\n", dbname, sqlite3_errmsg(astdb)); | 
					
						
							|  |  |  | 		sqlite3_close(astdb); | 
					
						
							| 
									
										
										
										
											2011-06-10 15:30:50 +00:00
										 |  |  | 		ast_mutex_unlock(&dblock); | 
					
						
							|  |  |  | 		return -1; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2014-06-16 09:04:05 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-07-06 20:58:12 +00:00
										 |  |  | 	ast_mutex_unlock(&dblock); | 
					
						
							| 
									
										
										
										
											2011-06-10 15:30:50 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-07-06 20:58:12 +00:00
										 |  |  | 	return 0; | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2011-06-10 15:30:50 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-07-06 20:58:12 +00:00
										 |  |  | static int db_init(void) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	if (astdb) { | 
					
						
							| 
									
										
										
										
											2011-06-10 15:30:50 +00:00
										 |  |  | 		return 0; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-07-06 20:58:12 +00:00
										 |  |  | 	if (db_open() || db_create_astdb() || init_statements()) { | 
					
						
							|  |  |  | 		return -1; | 
					
						
							| 
									
										
										
										
											2011-06-10 15:30:50 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-07-06 20:58:12 +00:00
										 |  |  | 	return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* We purposely don't lock around the sqlite3 call because the transaction
 | 
					
						
							|  |  |  |  * calls will be called with the database lock held. For any other use, make | 
					
						
							|  |  |  |  * sure to take the dblock yourself. */ | 
					
						
							|  |  |  | static int db_execute_sql(const char *sql, int (*callback)(void *, int, char **, char **), void *arg) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	char *errmsg = NULL; | 
					
						
							|  |  |  | 	int res =0; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-06-16 09:04:05 +00:00
										 |  |  | 	if (sqlite3_exec(astdb, sql, callback, arg, &errmsg) != SQLITE_OK) { | 
					
						
							|  |  |  | 		ast_log(LOG_WARNING, "Error executing SQL (%s): %s\n", sql, errmsg); | 
					
						
							| 
									
										
										
										
											2011-07-06 20:58:12 +00:00
										 |  |  | 		sqlite3_free(errmsg); | 
					
						
							|  |  |  | 		res = -1; | 
					
						
							| 
									
										
										
										
											2011-06-10 15:30:50 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-07-06 20:58:12 +00:00
										 |  |  | 	return res; | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2011-06-10 15:30:50 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-07-06 20:58:12 +00:00
										 |  |  | static int ast_db_begin_transaction(void) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	return db_execute_sql("BEGIN TRANSACTION", NULL, NULL); | 
					
						
							| 
									
										
										
										
											2011-06-10 15:30:50 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-07-06 20:58:12 +00:00
										 |  |  | static int ast_db_commit_transaction(void) | 
					
						
							| 
									
										
										
										
											2011-06-10 15:30:50 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2011-07-06 20:58:12 +00:00
										 |  |  | 	return db_execute_sql("COMMIT", NULL, NULL); | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2011-06-10 15:30:50 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-07-06 20:58:12 +00:00
										 |  |  | static int ast_db_rollback_transaction(void) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	return db_execute_sql("ROLLBACK", NULL, NULL); | 
					
						
							| 
									
										
										
										
											2011-06-10 15:30:50 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-07-06 20:58:12 +00:00
										 |  |  | int ast_db_put(const char *family, const char *key, const char *value) | 
					
						
							| 
									
										
										
										
											2011-06-10 15:30:50 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2011-07-06 20:58:12 +00:00
										 |  |  | 	char fullkey[MAX_DB_FIELD]; | 
					
						
							|  |  |  | 	size_t fullkey_len; | 
					
						
							|  |  |  | 	int res = 0; | 
					
						
							| 
									
										
										
										
											2011-06-10 15:30:50 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-07-06 20:58:12 +00:00
										 |  |  | 	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); | 
					
						
							| 
									
										
										
										
											2003-01-30 15:03:20 +00:00
										 |  |  | 		return -1; | 
					
						
							| 
									
										
										
										
											2005-07-20 00:09:39 +00:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2011-06-10 15:30:50 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-07-06 20:58:12 +00:00
										 |  |  | 	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) { | 
					
						
							| 
									
										
										
										
											2018-10-18 12:32:26 -05:00
										 |  |  | 		ast_log(LOG_WARNING, "Couldn't execute statement: %s\n", sqlite3_errmsg(astdb)); | 
					
						
							| 
									
										
										
										
											2011-07-06 20:58:12 +00:00
										 |  |  | 		res = -1; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	sqlite3_reset(put_stmt); | 
					
						
							|  |  |  | 	db_sync(); | 
					
						
							|  |  |  | 	ast_mutex_unlock(&dblock); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return res; | 
					
						
							| 
									
										
										
										
											2003-01-30 15:03:20 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-10-01 20:36:25 +00:00
										 |  |  | /*!
 | 
					
						
							|  |  |  |  * \internal | 
					
						
							|  |  |  |  * \brief Get key value specified by family/key. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * Gets the value associated with the specified \a family and \a key, and | 
					
						
							|  |  |  |  * stores it, either into the fixed sized buffer specified by \a buffer | 
					
						
							|  |  |  |  * and \a bufferlen, or as a heap allocated string if \a bufferlen is -1. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * \note If \a bufferlen is -1, \a buffer points to heap allocated memory | 
					
						
							|  |  |  |  *       and must be freed by calling ast_free(). | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * \retval -1 An error occurred | 
					
						
							|  |  |  |  * \retval 0 Success | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | static int db_get_common(const char *family, const char *key, char **buffer, int bufferlen) | 
					
						
							| 
									
										
										
										
											2003-01-30 15:03:20 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2011-07-06 20:58:12 +00:00
										 |  |  | 	const unsigned char *result; | 
					
						
							| 
									
										
										
										
											2011-06-10 15:30:50 +00:00
										 |  |  | 	char fullkey[MAX_DB_FIELD]; | 
					
						
							| 
									
										
										
										
											2011-07-06 20:58:12 +00:00
										 |  |  | 	size_t fullkey_len; | 
					
						
							|  |  |  | 	int res = 0; | 
					
						
							| 
									
										
										
										
											2003-01-30 15:03:20 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-07-06 20:58:12 +00:00
										 |  |  | 	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); | 
					
						
							| 
									
										
										
										
											2003-01-30 15:03:20 +00:00
										 |  |  | 		return -1; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-07-06 20:58:12 +00:00
										 |  |  | 	fullkey_len = snprintf(fullkey, sizeof(fullkey), "/%s/%s", family, key); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	ast_mutex_lock(&dblock); | 
					
						
							|  |  |  | 	if (sqlite3_bind_text(get_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_step(get_stmt) != SQLITE_ROW) { | 
					
						
							|  |  |  | 		ast_debug(1, "Unable to find key '%s' in family '%s'\n", key, family); | 
					
						
							|  |  |  | 		res = -1; | 
					
						
							|  |  |  | 	} else if (!(result = sqlite3_column_text(get_stmt, 0))) { | 
					
						
							|  |  |  | 		ast_log(LOG_WARNING, "Couldn't get value\n"); | 
					
						
							|  |  |  | 		res = -1; | 
					
						
							|  |  |  | 	} else { | 
					
						
							| 
									
										
										
										
											2012-10-01 20:36:25 +00:00
										 |  |  | 		const char *value = (const char *) result; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		if (bufferlen == -1) { | 
					
						
							|  |  |  | 			*buffer = ast_strdup(value); | 
					
						
							|  |  |  | 		} else { | 
					
						
							|  |  |  | 			ast_copy_string(*buffer, value, bufferlen); | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2011-07-06 20:58:12 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	sqlite3_reset(get_stmt); | 
					
						
							| 
									
										
										
										
											2003-08-13 15:25:16 +00:00
										 |  |  | 	ast_mutex_unlock(&dblock); | 
					
						
							| 
									
										
										
										
											2011-06-10 15:30:50 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2003-01-30 15:03:20 +00:00
										 |  |  | 	return res; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-10-01 20:36:25 +00:00
										 |  |  | int ast_db_get(const char *family, const char *key, char *value, int valuelen) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	ast_assert(value != NULL); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* Make sure we initialize */ | 
					
						
							|  |  |  | 	value[0] = 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return db_get_common(family, key, &value, valuelen); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | int ast_db_get_allocated(const char *family, const char *key, char **out) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	*out = NULL; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return db_get_common(family, key, out, -1); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-07-06 20:58:12 +00:00
										 |  |  | int ast_db_del(const char *family, const char *key) | 
					
						
							| 
									
										
										
										
											2003-01-30 15:03:20 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2011-07-06 20:58:12 +00:00
										 |  |  | 	char fullkey[MAX_DB_FIELD]; | 
					
						
							|  |  |  | 	size_t fullkey_len; | 
					
						
							|  |  |  | 	int res = 0; | 
					
						
							| 
									
										
										
										
											2003-01-30 15:03:20 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-07-06 20:58:12 +00:00
										 |  |  | 	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); | 
					
						
							| 
									
										
										
										
											2003-01-30 15:03:20 +00:00
										 |  |  | 		return -1; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-07-06 20:58:12 +00:00
										 |  |  | 	fullkey_len = snprintf(fullkey, sizeof(fullkey), "/%s/%s", family, key); | 
					
						
							| 
									
										
										
										
											2009-03-17 05:51:54 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-07-06 20:58:12 +00:00
										 |  |  | 	ast_mutex_lock(&dblock); | 
					
						
							|  |  |  | 	if (sqlite3_bind_text(del_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_step(del_stmt) != SQLITE_DONE) { | 
					
						
							|  |  |  | 		ast_debug(1, "Unable to find key '%s' in family '%s'\n", key, family); | 
					
						
							|  |  |  | 		res = -1; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	sqlite3_reset(del_stmt); | 
					
						
							|  |  |  | 	db_sync(); | 
					
						
							|  |  |  | 	ast_mutex_unlock(&dblock); | 
					
						
							| 
									
										
										
										
											2003-01-30 15:03:20 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-07-06 20:58:12 +00:00
										 |  |  | 	return res; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-11-19 15:11:45 +00:00
										 |  |  | int ast_db_deltree(const char *family, const char *keytree) | 
					
						
							| 
									
										
										
										
											2011-07-06 20:58:12 +00:00
										 |  |  | { | 
					
						
							|  |  |  | 	sqlite3_stmt *stmt = deltree_stmt; | 
					
						
							|  |  |  | 	char prefix[MAX_DB_FIELD]; | 
					
						
							|  |  |  | 	int res = 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (!ast_strlen_zero(family)) { | 
					
						
							| 
									
										
										
										
											2011-11-19 15:11:45 +00:00
										 |  |  | 		if (!ast_strlen_zero(keytree)) { | 
					
						
							| 
									
										
										
										
											2011-07-06 20:58:12 +00:00
										 |  |  | 			/* Family and key tree */ | 
					
						
							| 
									
										
										
										
											2011-11-19 15:11:45 +00:00
										 |  |  | 			snprintf(prefix, sizeof(prefix), "/%s/%s", family, keytree); | 
					
						
							| 
									
										
										
										
											2003-01-30 15:03:20 +00:00
										 |  |  | 		} else { | 
					
						
							| 
									
										
										
										
											2011-07-06 20:58:12 +00:00
										 |  |  | 			/* Family only */ | 
					
						
							|  |  |  | 			snprintf(prefix, sizeof(prefix), "/%s", family); | 
					
						
							| 
									
										
										
										
											2003-01-30 15:03:20 +00:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2011-07-06 20:58:12 +00:00
										 |  |  | 	} else { | 
					
						
							|  |  |  | 		prefix[0] = '\0'; | 
					
						
							|  |  |  | 		stmt = deltree_all_stmt; | 
					
						
							| 
									
										
										
										
											2003-01-30 15:03:20 +00:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2009-03-17 05:51:54 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-07-06 20:58:12 +00:00
										 |  |  | 	ast_mutex_lock(&dblock); | 
					
						
							|  |  |  | 	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)); | 
					
						
							|  |  |  | 		res = -1; | 
					
						
							|  |  |  | 	} else if (sqlite3_step(stmt) != SQLITE_DONE) { | 
					
						
							|  |  |  | 		ast_log(LOG_WARNING, "Couldn't execute stmt: %s\n", sqlite3_errmsg(astdb)); | 
					
						
							|  |  |  | 		res = -1; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	res = sqlite3_changes(astdb); | 
					
						
							|  |  |  | 	sqlite3_reset(stmt); | 
					
						
							|  |  |  | 	db_sync(); | 
					
						
							| 
									
										
										
										
											2009-03-17 05:51:54 +00:00
										 |  |  | 	ast_mutex_unlock(&dblock); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2003-01-30 15:03:20 +00:00
										 |  |  | 	return res; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-12-07 15:19:40 -05:00
										 |  |  | static struct ast_db_entry *db_gettree_common(sqlite3_stmt *stmt) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	struct ast_db_entry *head = NULL, *prev = NULL, *cur; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	while (sqlite3_step(stmt) == SQLITE_ROW) { | 
					
						
							|  |  |  | 		const char *key, *value; | 
					
						
							|  |  |  | 		size_t key_len, value_len; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		key   = (const char *) sqlite3_column_text(stmt, 0); | 
					
						
							|  |  |  | 		value = (const char *) sqlite3_column_text(stmt, 1); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		if (!key || !value) { | 
					
						
							|  |  |  | 			break; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		key_len = strlen(key); | 
					
						
							|  |  |  | 		value_len = strlen(value); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		cur = ast_malloc(sizeof(*cur) + key_len + value_len + 2); | 
					
						
							|  |  |  | 		if (!cur) { | 
					
						
							|  |  |  | 			break; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		cur->next = NULL; | 
					
						
							|  |  |  | 		cur->key = cur->data + value_len + 1; | 
					
						
							|  |  |  | 		memcpy(cur->data, value, value_len + 1); | 
					
						
							|  |  |  | 		memcpy(cur->key, key, key_len + 1); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		if (prev) { | 
					
						
							|  |  |  | 			prev->next = cur; | 
					
						
							|  |  |  | 		} else { | 
					
						
							|  |  |  | 			head = cur; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		prev = cur; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return head; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-11-19 15:11:45 +00:00
										 |  |  | struct ast_db_entry *ast_db_gettree(const char *family, const char *keytree) | 
					
						
							| 
									
										
										
										
											2003-01-30 15:03:20 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2011-07-06 20:58:12 +00:00
										 |  |  | 	char prefix[MAX_DB_FIELD]; | 
					
						
							|  |  |  | 	sqlite3_stmt *stmt = gettree_stmt; | 
					
						
							| 
									
										
										
										
											2017-12-07 15:19:40 -05:00
										 |  |  | 	size_t res = 0; | 
					
						
							|  |  |  | 	struct ast_db_entry *ret; | 
					
						
							| 
									
										
										
										
											2011-07-06 20:58:12 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	if (!ast_strlen_zero(family)) { | 
					
						
							| 
									
										
										
										
											2011-11-19 15:11:45 +00:00
										 |  |  | 		if (!ast_strlen_zero(keytree)) { | 
					
						
							| 
									
										
										
										
											2011-07-06 20:58:12 +00:00
										 |  |  | 			/* Family and key tree */ | 
					
						
							| 
									
										
										
										
											2017-12-07 15:19:40 -05:00
										 |  |  | 			res = snprintf(prefix, sizeof(prefix), "/%s/%s", family, keytree); | 
					
						
							| 
									
										
										
										
											2011-07-06 20:58:12 +00:00
										 |  |  | 		} else { | 
					
						
							|  |  |  | 			/* Family only */ | 
					
						
							| 
									
										
										
										
											2017-12-07 15:19:40 -05:00
										 |  |  | 			res = snprintf(prefix, sizeof(prefix), "/%s", family); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		if (res >= sizeof(prefix)) { | 
					
						
							|  |  |  | 			ast_log(LOG_WARNING, "Requested prefix is too long: %s\n", keytree); | 
					
						
							|  |  |  | 			return NULL; | 
					
						
							| 
									
										
										
										
											2011-07-06 20:58:12 +00:00
										 |  |  | 		} | 
					
						
							|  |  |  | 	} else { | 
					
						
							|  |  |  | 		prefix[0] = '\0'; | 
					
						
							|  |  |  | 		stmt = gettree_all_stmt; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2003-01-30 15:03:20 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2003-08-13 15:25:16 +00:00
										 |  |  | 	ast_mutex_lock(&dblock); | 
					
						
							| 
									
										
										
										
											2017-12-07 15:19:40 -05:00
										 |  |  | 	if (res && (sqlite3_bind_text(stmt, 1, prefix, res, SQLITE_STATIC) != SQLITE_OK)) { | 
					
						
							|  |  |  | 		ast_log(LOG_WARNING, "Could not bind %s to stmt: %s\n", prefix, sqlite3_errmsg(astdb)); | 
					
						
							| 
									
										
										
										
											2011-07-06 20:58:12 +00:00
										 |  |  | 		sqlite3_reset(stmt); | 
					
						
							| 
									
										
										
										
											2003-08-13 15:25:16 +00:00
										 |  |  | 		ast_mutex_unlock(&dblock); | 
					
						
							| 
									
										
										
										
											2011-07-06 20:58:12 +00:00
										 |  |  | 		return NULL; | 
					
						
							| 
									
										
										
										
											2003-01-30 15:03:20 +00:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2011-07-06 20:58:12 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-12-07 15:19:40 -05:00
										 |  |  | 	ret = db_gettree_common(stmt); | 
					
						
							| 
									
										
										
										
											2011-07-06 20:58:12 +00:00
										 |  |  | 	sqlite3_reset(stmt); | 
					
						
							| 
									
										
										
										
											2003-08-13 15:25:16 +00:00
										 |  |  | 	ast_mutex_unlock(&dblock); | 
					
						
							| 
									
										
										
										
											2003-01-30 15:03:20 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-07-06 20:58:12 +00:00
										 |  |  | 	return ret; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-12-07 15:19:40 -05:00
										 |  |  | struct ast_db_entry *ast_db_gettree_by_prefix(const char *family, const char *key_prefix) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	char prefix[MAX_DB_FIELD]; | 
					
						
							|  |  |  | 	size_t res; | 
					
						
							|  |  |  | 	struct ast_db_entry *ret; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	res = snprintf(prefix, sizeof(prefix), "/%s/%s", family, key_prefix); | 
					
						
							|  |  |  | 	if (res >= sizeof(prefix)) { | 
					
						
							|  |  |  | 		ast_log(LOG_WARNING, "Requested key prefix is too long: %s\n", key_prefix); | 
					
						
							|  |  |  | 		return NULL; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	ast_mutex_lock(&dblock); | 
					
						
							|  |  |  | 	if (sqlite3_bind_text(gettree_prefix_stmt, 1, prefix, res, SQLITE_STATIC) != SQLITE_OK) { | 
					
						
							|  |  |  | 		ast_log(LOG_WARNING, "Could not bind %s to stmt: %s\n", prefix, sqlite3_errmsg(astdb)); | 
					
						
							|  |  |  | 		sqlite3_reset(gettree_prefix_stmt); | 
					
						
							|  |  |  | 		ast_mutex_unlock(&dblock); | 
					
						
							|  |  |  | 		return NULL; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	ret = db_gettree_common(gettree_prefix_stmt); | 
					
						
							|  |  |  | 	sqlite3_reset(gettree_prefix_stmt); | 
					
						
							|  |  |  | 	ast_mutex_unlock(&dblock); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return ret; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-07-06 20:58:12 +00:00
										 |  |  | void ast_db_freetree(struct ast_db_entry *dbe) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	struct ast_db_entry *last; | 
					
						
							|  |  |  | 	while (dbe) { | 
					
						
							|  |  |  | 		last = dbe; | 
					
						
							|  |  |  | 		dbe = dbe->next; | 
					
						
							|  |  |  | 		ast_free(last); | 
					
						
							| 
									
										
										
										
											2006-10-03 15:53:07 +00:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2003-01-30 15:03:20 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-10-11 19:03:06 +00:00
										 |  |  | static char *handle_cli_database_put(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) | 
					
						
							| 
									
										
										
										
											2003-01-30 15:03:20 +00:00
										 |  |  | { | 
					
						
							|  |  |  | 	int res; | 
					
						
							| 
									
										
										
										
											2007-10-11 19:03:06 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	switch (cmd) { | 
					
						
							|  |  |  | 	case CLI_INIT: | 
					
						
							|  |  |  | 		e->command = "database put"; | 
					
						
							|  |  |  | 		e->usage = | 
					
						
							|  |  |  | 			"Usage: database put <family> <key> <value>\n" | 
					
						
							|  |  |  | 			"       Adds or updates an entry in the Asterisk database for\n" | 
					
						
							|  |  |  | 			"       a given family, key, and value.\n"; | 
					
						
							|  |  |  | 		return NULL; | 
					
						
							|  |  |  | 	case CLI_GENERATE: | 
					
						
							|  |  |  | 		return NULL; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (a->argc != 5) | 
					
						
							|  |  |  | 		return CLI_SHOWUSAGE; | 
					
						
							|  |  |  | 	res = ast_db_put(a->argv[2], a->argv[3], a->argv[4]); | 
					
						
							| 
									
										
										
										
											2005-07-20 00:09:39 +00:00
										 |  |  | 	if (res)  { | 
					
						
							| 
									
										
										
										
											2007-10-11 19:03:06 +00:00
										 |  |  | 		ast_cli(a->fd, "Failed to update entry\n"); | 
					
						
							| 
									
										
										
										
											2005-07-20 00:09:39 +00:00
										 |  |  | 	} else { | 
					
						
							| 
									
										
										
										
											2007-10-11 19:03:06 +00:00
										 |  |  | 		ast_cli(a->fd, "Updated database successfully\n"); | 
					
						
							| 
									
										
										
										
											2005-07-20 00:09:39 +00:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2007-10-11 19:03:06 +00:00
										 |  |  | 	return CLI_SUCCESS; | 
					
						
							| 
									
										
										
										
											2003-01-30 15:03:20 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-10-11 19:03:06 +00:00
										 |  |  | static char *handle_cli_database_get(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) | 
					
						
							| 
									
										
										
										
											2003-01-30 15:03:20 +00:00
										 |  |  | { | 
					
						
							|  |  |  | 	int res; | 
					
						
							| 
									
										
										
										
											2011-06-10 15:30:50 +00:00
										 |  |  | 	char tmp[MAX_DB_FIELD]; | 
					
						
							| 
									
										
										
										
											2007-10-11 19:03:06 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	switch (cmd) { | 
					
						
							|  |  |  | 	case CLI_INIT: | 
					
						
							|  |  |  | 		e->command = "database get"; | 
					
						
							|  |  |  | 		e->usage = | 
					
						
							|  |  |  | 			"Usage: database get <family> <key>\n" | 
					
						
							|  |  |  | 			"       Retrieves an entry in the Asterisk database for a given\n" | 
					
						
							|  |  |  | 			"       family and key.\n"; | 
					
						
							|  |  |  | 		return NULL; | 
					
						
							|  |  |  | 	case CLI_GENERATE: | 
					
						
							|  |  |  | 		return NULL; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (a->argc != 4) | 
					
						
							|  |  |  | 		return CLI_SHOWUSAGE; | 
					
						
							|  |  |  | 	res = ast_db_get(a->argv[2], a->argv[3], tmp, sizeof(tmp)); | 
					
						
							| 
									
										
										
										
											2005-07-20 00:09:39 +00:00
										 |  |  | 	if (res) { | 
					
						
							| 
									
										
										
										
											2007-10-11 19:03:06 +00:00
										 |  |  | 		ast_cli(a->fd, "Database entry not found.\n"); | 
					
						
							| 
									
										
										
										
											2005-07-20 00:09:39 +00:00
										 |  |  | 	} else { | 
					
						
							| 
									
										
										
										
											2007-10-11 19:03:06 +00:00
										 |  |  | 		ast_cli(a->fd, "Value: %s\n", tmp); | 
					
						
							| 
									
										
										
										
											2005-07-20 00:09:39 +00:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2007-10-11 19:03:06 +00:00
										 |  |  | 	return CLI_SUCCESS; | 
					
						
							| 
									
										
										
										
											2003-01-30 15:03:20 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-10-11 19:03:06 +00:00
										 |  |  | static char *handle_cli_database_del(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) | 
					
						
							| 
									
										
										
										
											2003-01-30 15:03:20 +00:00
										 |  |  | { | 
					
						
							|  |  |  | 	int res; | 
					
						
							| 
									
										
										
										
											2007-10-11 19:03:06 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	switch (cmd) { | 
					
						
							|  |  |  | 	case CLI_INIT: | 
					
						
							|  |  |  | 		e->command = "database del"; | 
					
						
							|  |  |  | 		e->usage = | 
					
						
							|  |  |  | 			"Usage: database del <family> <key>\n" | 
					
						
							|  |  |  | 			"       Deletes an entry in the Asterisk database for a given\n" | 
					
						
							|  |  |  | 			"       family and key.\n"; | 
					
						
							|  |  |  | 		return NULL; | 
					
						
							|  |  |  | 	case CLI_GENERATE: | 
					
						
							|  |  |  | 		return NULL; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (a->argc != 4) | 
					
						
							|  |  |  | 		return CLI_SHOWUSAGE; | 
					
						
							|  |  |  | 	res = ast_db_del(a->argv[2], a->argv[3]); | 
					
						
							| 
									
										
										
										
											2005-07-20 00:09:39 +00:00
										 |  |  | 	if (res) { | 
					
						
							| 
									
										
										
										
											2007-10-11 19:03:06 +00:00
										 |  |  | 		ast_cli(a->fd, "Database entry does not exist.\n"); | 
					
						
							| 
									
										
										
										
											2005-07-20 00:09:39 +00:00
										 |  |  | 	} else { | 
					
						
							| 
									
										
										
										
											2007-10-11 19:03:06 +00:00
										 |  |  | 		ast_cli(a->fd, "Database entry removed.\n"); | 
					
						
							| 
									
										
										
										
											2005-07-20 00:09:39 +00:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2007-10-11 19:03:06 +00:00
										 |  |  | 	return CLI_SUCCESS; | 
					
						
							| 
									
										
										
										
											2003-01-30 15:03:20 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-10-11 19:03:06 +00:00
										 |  |  | static char *handle_cli_database_deltree(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) | 
					
						
							| 
									
										
										
										
											2003-01-30 15:03:20 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2012-10-04 15:48:24 +00:00
										 |  |  | 	int num_deleted; | 
					
						
							| 
									
										
										
										
											2007-10-11 19:03:06 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	switch (cmd) { | 
					
						
							|  |  |  | 	case CLI_INIT: | 
					
						
							|  |  |  | 		e->command = "database deltree"; | 
					
						
							|  |  |  | 		e->usage = | 
					
						
							| 
									
										
										
										
											2011-11-19 15:11:45 +00:00
										 |  |  | 			"Usage: database deltree <family> [keytree]\n" | 
					
						
							|  |  |  | 			"   OR: database deltree <family>[/keytree]\n" | 
					
						
							|  |  |  | 			"       Deletes a family or specific keytree within a family\n" | 
					
						
							|  |  |  | 			"       in the Asterisk database.  The two arguments may be\n" | 
					
						
							|  |  |  | 			"       separated by either a space or a slash.\n"; | 
					
						
							| 
									
										
										
										
											2007-10-11 19:03:06 +00:00
										 |  |  | 		return NULL; | 
					
						
							|  |  |  | 	case CLI_GENERATE: | 
					
						
							|  |  |  | 		return NULL; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if ((a->argc < 3) || (a->argc > 4)) | 
					
						
							|  |  |  | 		return CLI_SHOWUSAGE; | 
					
						
							|  |  |  | 	if (a->argc == 4) { | 
					
						
							| 
									
										
										
										
											2012-10-04 15:48:24 +00:00
										 |  |  | 		num_deleted = ast_db_deltree(a->argv[2], a->argv[3]); | 
					
						
							| 
									
										
										
										
											2005-07-20 00:09:39 +00:00
										 |  |  | 	} else { | 
					
						
							| 
									
										
										
										
											2012-10-04 15:48:24 +00:00
										 |  |  | 		num_deleted = ast_db_deltree(a->argv[2], NULL); | 
					
						
							| 
									
										
										
										
											2005-07-20 00:09:39 +00:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2012-10-04 15:48:24 +00:00
										 |  |  | 	if (num_deleted < 0) { | 
					
						
							|  |  |  | 		ast_cli(a->fd, "Database unavailable.\n"); | 
					
						
							|  |  |  | 	} else if (num_deleted == 0) { | 
					
						
							| 
									
										
										
										
											2007-10-11 19:03:06 +00:00
										 |  |  | 		ast_cli(a->fd, "Database entries do not exist.\n"); | 
					
						
							| 
									
										
										
										
											2005-07-20 00:09:39 +00:00
										 |  |  | 	} else { | 
					
						
							| 
									
										
										
										
											2012-10-04 15:48:24 +00:00
										 |  |  | 		ast_cli(a->fd, "%d database entries removed.\n",num_deleted); | 
					
						
							| 
									
										
										
										
											2005-07-20 00:09:39 +00:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2007-10-11 19:03:06 +00:00
										 |  |  | 	return CLI_SUCCESS; | 
					
						
							| 
									
										
										
										
											2003-01-30 15:03:20 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-10-11 19:03:06 +00:00
										 |  |  | static char *handle_cli_database_show(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) | 
					
						
							| 
									
										
										
										
											2003-01-30 15:03:20 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2011-06-10 15:30:50 +00:00
										 |  |  | 	char prefix[MAX_DB_FIELD]; | 
					
						
							| 
									
										
										
										
											2007-09-10 16:24:29 +00:00
										 |  |  | 	int counter = 0; | 
					
						
							| 
									
										
										
										
											2011-07-06 20:58:12 +00:00
										 |  |  | 	sqlite3_stmt *stmt = gettree_stmt; | 
					
						
							| 
									
										
										
										
											2003-01-30 15:03:20 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-10-11 19:03:06 +00:00
										 |  |  | 	switch (cmd) { | 
					
						
							|  |  |  | 	case CLI_INIT: | 
					
						
							|  |  |  | 		e->command = "database show"; | 
					
						
							|  |  |  | 		e->usage = | 
					
						
							| 
									
										
										
										
											2011-11-19 15:11:45 +00:00
										 |  |  | 			"Usage: database show [family [keytree]]\n" | 
					
						
							|  |  |  | 			"   OR: database show [family[/keytree]]\n" | 
					
						
							| 
									
										
										
										
											2007-10-11 19:03:06 +00:00
										 |  |  | 			"       Shows Asterisk database contents, optionally restricted\n" | 
					
						
							| 
									
										
										
										
											2011-11-19 15:11:45 +00:00
										 |  |  | 			"       to a given family, or family and keytree. The two arguments\n" | 
					
						
							|  |  |  | 			"       may be separated either by a space or by a slash.\n"; | 
					
						
							| 
									
										
										
										
											2007-10-11 19:03:06 +00:00
										 |  |  | 		return NULL; | 
					
						
							|  |  |  | 	case CLI_GENERATE: | 
					
						
							|  |  |  | 		return NULL; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (a->argc == 4) { | 
					
						
							| 
									
										
										
										
											2003-01-30 15:03:20 +00:00
										 |  |  | 		/* Family and key tree */ | 
					
						
							| 
									
										
										
										
											2007-10-11 19:03:06 +00:00
										 |  |  | 		snprintf(prefix, sizeof(prefix), "/%s/%s", a->argv[2], a->argv[3]); | 
					
						
							|  |  |  | 	} else if (a->argc == 3) { | 
					
						
							| 
									
										
										
										
											2003-01-30 15:03:20 +00:00
										 |  |  | 		/* Family only */ | 
					
						
							| 
									
										
										
										
											2007-10-11 19:03:06 +00:00
										 |  |  | 		snprintf(prefix, sizeof(prefix), "/%s", a->argv[2]); | 
					
						
							|  |  |  | 	} else if (a->argc == 2) { | 
					
						
							| 
									
										
										
										
											2003-01-30 15:03:20 +00:00
										 |  |  | 		/* Neither */ | 
					
						
							| 
									
										
										
										
											2004-07-09 10:08:09 +00:00
										 |  |  | 		prefix[0] = '\0'; | 
					
						
							| 
									
										
										
										
											2011-07-06 20:58:12 +00:00
										 |  |  | 		stmt = gettree_all_stmt; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-07-20 00:09:39 +00:00
										 |  |  | 	} else { | 
					
						
							| 
									
										
										
										
											2007-10-11 19:03:06 +00:00
										 |  |  | 		return CLI_SHOWUSAGE; | 
					
						
							| 
									
										
										
										
											2005-07-20 00:09:39 +00:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2011-06-10 15:30:50 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-07-06 20:58:12 +00:00
										 |  |  | 	ast_mutex_lock(&dblock); | 
					
						
							|  |  |  | 	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; | 
					
						
							| 
									
										
										
										
											2003-01-30 15:03:20 +00:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2011-06-10 15:30:50 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-07-06 20:58:12 +00:00
										 |  |  | 	while (sqlite3_step(stmt) == SQLITE_ROW) { | 
					
						
							|  |  |  | 		const char *key_s, *value_s; | 
					
						
							|  |  |  | 		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; | 
					
						
							| 
									
										
										
										
											2011-06-10 15:30:50 +00:00
										 |  |  | 		ast_cli(a->fd, "%-50s: %-25s\n", key_s, value_s); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-07-06 20:58:12 +00:00
										 |  |  | 	sqlite3_reset(stmt); | 
					
						
							|  |  |  | 	ast_mutex_unlock(&dblock); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	ast_cli(a->fd, "%d results found.\n", counter); | 
					
						
							|  |  |  | 	return CLI_SUCCESS; | 
					
						
							| 
									
										
										
										
											2003-01-30 15:03:20 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-10-11 19:03:06 +00:00
										 |  |  | static char *handle_cli_database_showkey(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) | 
					
						
							| 
									
										
										
										
											2004-12-22 01:07:02 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2007-03-21 02:46:02 +00:00
										 |  |  | 	int counter = 0; | 
					
						
							| 
									
										
										
										
											2004-12-22 01:07:02 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-10-11 19:03:06 +00:00
										 |  |  | 	switch (cmd) { | 
					
						
							|  |  |  | 	case CLI_INIT: | 
					
						
							| 
									
										
										
										
											2007-11-03 04:55:06 +00:00
										 |  |  | 		e->command = "database showkey"; | 
					
						
							| 
									
										
										
										
											2007-10-11 19:03:06 +00:00
										 |  |  | 		e->usage = | 
					
						
							| 
									
										
										
										
											2011-11-19 15:11:45 +00:00
										 |  |  | 			"Usage: database showkey <keytree>\n" | 
					
						
							| 
									
										
										
										
											2007-10-11 19:03:06 +00:00
										 |  |  | 			"       Shows Asterisk database contents, restricted to a given key.\n"; | 
					
						
							|  |  |  | 		return NULL; | 
					
						
							|  |  |  | 	case CLI_GENERATE: | 
					
						
							|  |  |  | 		return NULL; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-07-06 20:58:12 +00:00
										 |  |  | 	if (a->argc != 3) { | 
					
						
							| 
									
										
										
										
											2007-10-11 19:03:06 +00:00
										 |  |  | 		return CLI_SHOWUSAGE; | 
					
						
							| 
									
										
										
										
											2005-07-20 00:09:39 +00:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2011-06-10 15:30:50 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-07-06 20:58:12 +00:00
										 |  |  | 	ast_mutex_lock(&dblock); | 
					
						
							|  |  |  | 	if (!ast_strlen_zero(a->argv[2]) && (sqlite3_bind_text(showkey_stmt, 1, a->argv[2], -1, SQLITE_STATIC) != SQLITE_OK)) { | 
					
						
							|  |  |  | 		ast_log(LOG_WARNING, "Could bind %s to stmt: %s\n", a->argv[2], sqlite3_errmsg(astdb)); | 
					
						
							|  |  |  | 		sqlite3_reset(showkey_stmt); | 
					
						
							|  |  |  | 		ast_mutex_unlock(&dblock); | 
					
						
							|  |  |  | 		return NULL; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	while (sqlite3_step(showkey_stmt) == SQLITE_ROW) { | 
					
						
							|  |  |  | 		const char *key_s, *value_s; | 
					
						
							|  |  |  | 		if (!(key_s = (const char *) sqlite3_column_text(showkey_stmt, 0))) { | 
					
						
							|  |  |  | 			break; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		if (!(value_s = (const char *) sqlite3_column_text(showkey_stmt, 1))) { | 
					
						
							|  |  |  | 			break; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		++counter; | 
					
						
							|  |  |  | 		ast_cli(a->fd, "%-50s: %-25s\n", key_s, value_s); | 
					
						
							| 
									
										
										
										
											2004-12-22 01:07:02 +00:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2011-07-06 20:58:12 +00:00
										 |  |  | 	sqlite3_reset(showkey_stmt); | 
					
						
							|  |  |  | 	ast_mutex_unlock(&dblock); | 
					
						
							| 
									
										
										
										
											2011-06-10 15:30:50 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-10-11 19:03:06 +00:00
										 |  |  | 	ast_cli(a->fd, "%d results found.\n", counter); | 
					
						
							| 
									
										
										
										
											2011-06-10 15:30:50 +00:00
										 |  |  | 	return CLI_SUCCESS; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-07-06 20:58:12 +00:00
										 |  |  | static int display_results(void *arg, int columns, char **values, char **colnames) | 
					
						
							| 
									
										
										
										
											2011-06-10 15:30:50 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2011-07-06 20:58:12 +00:00
										 |  |  | 	struct ast_cli_args *a = arg; | 
					
						
							|  |  |  | 	size_t x; | 
					
						
							| 
									
										
										
										
											2011-06-10 15:30:50 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-07-06 20:58:12 +00:00
										 |  |  | 	for (x = 0; x < columns; x++) { | 
					
						
							|  |  |  | 		ast_cli(a->fd, "%-5s: %-50s\n", colnames[x], values[x]); | 
					
						
							| 
									
										
										
										
											2011-06-10 15:30:50 +00:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2011-07-06 20:58:12 +00:00
										 |  |  | 	ast_cli(a->fd, "\n"); | 
					
						
							| 
									
										
										
										
											2011-06-10 15:30:50 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	return 0; | 
					
						
							| 
									
										
										
										
											2004-12-22 01:07:02 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-07-06 20:58:12 +00:00
										 |  |  | static char *handle_cli_database_query(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) | 
					
						
							| 
									
										
										
										
											2003-04-13 04:17:45 +00:00
										 |  |  | { | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-07-06 20:58:12 +00:00
										 |  |  | 	switch (cmd) { | 
					
						
							|  |  |  | 	case CLI_INIT: | 
					
						
							|  |  |  | 		e->command = "database query"; | 
					
						
							|  |  |  | 		e->usage = | 
					
						
							|  |  |  | 			"Usage: database query \"<SQL Statement>\"\n" | 
					
						
							|  |  |  | 			"       Run a user-specified SQL query on the database. Be careful.\n"; | 
					
						
							|  |  |  | 		return NULL; | 
					
						
							|  |  |  | 	case CLI_GENERATE: | 
					
						
							|  |  |  | 		return NULL; | 
					
						
							| 
									
										
										
										
											2005-07-20 00:09:39 +00:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2011-06-10 15:30:50 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-07-06 20:58:12 +00:00
										 |  |  | 	if (a->argc != 3) { | 
					
						
							|  |  |  | 		return CLI_SHOWUSAGE; | 
					
						
							| 
									
										
										
										
											2003-04-13 04:17:45 +00:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2011-06-10 15:30:50 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-07-06 20:58:12 +00:00
										 |  |  | 	ast_mutex_lock(&dblock); | 
					
						
							|  |  |  | 	db_execute_sql(a->argv[2], display_results, a); | 
					
						
							|  |  |  | 	db_sync(); /* Go ahead and sync the db in case they write */ | 
					
						
							|  |  |  | 	ast_mutex_unlock(&dblock); | 
					
						
							| 
									
										
										
										
											2003-04-13 04:17:45 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-07-06 20:58:12 +00:00
										 |  |  | 	return CLI_SUCCESS; | 
					
						
							| 
									
										
										
										
											2003-04-13 04:17:45 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-06-15 17:34:30 +00:00
										 |  |  | static struct ast_cli_entry cli_database[] = { | 
					
						
							| 
									
										
										
										
											2007-10-22 20:05:18 +00:00
										 |  |  | 	AST_CLI_DEFINE(handle_cli_database_show,    "Shows database contents"), | 
					
						
							|  |  |  | 	AST_CLI_DEFINE(handle_cli_database_showkey, "Shows database contents"), | 
					
						
							|  |  |  | 	AST_CLI_DEFINE(handle_cli_database_get,     "Gets database value"), | 
					
						
							|  |  |  | 	AST_CLI_DEFINE(handle_cli_database_put,     "Adds/updates database value"), | 
					
						
							|  |  |  | 	AST_CLI_DEFINE(handle_cli_database_del,     "Removes database key/value"), | 
					
						
							| 
									
										
										
										
											2011-11-19 15:11:45 +00:00
										 |  |  | 	AST_CLI_DEFINE(handle_cli_database_deltree, "Removes database keytree/values"), | 
					
						
							| 
									
										
										
										
											2011-07-06 20:58:12 +00:00
										 |  |  | 	AST_CLI_DEFINE(handle_cli_database_query,   "Run a user-specified query on the astdb"), | 
					
						
							| 
									
										
										
										
											2006-09-18 19:54:18 +00:00
										 |  |  | }; | 
					
						
							| 
									
										
										
										
											2003-01-30 15:03:20 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-01-05 22:43:18 +00:00
										 |  |  | static int manager_dbput(struct mansession *s, const struct message *m) | 
					
						
							| 
									
										
										
										
											2005-01-29 23:33:14 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2007-01-05 22:43:18 +00:00
										 |  |  | 	const char *family = astman_get_header(m, "Family"); | 
					
						
							|  |  |  | 	const char *key = astman_get_header(m, "Key"); | 
					
						
							|  |  |  | 	const char *val = astman_get_header(m, "Val"); | 
					
						
							| 
									
										
										
										
											2005-01-29 23:33:14 +00:00
										 |  |  | 	int res; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-03-19 15:53:40 +00:00
										 |  |  | 	if (ast_strlen_zero(family)) { | 
					
						
							| 
									
										
										
										
											2005-01-29 23:33:14 +00:00
										 |  |  | 		astman_send_error(s, m, "No family specified"); | 
					
						
							|  |  |  | 		return 0; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2006-03-19 15:53:40 +00:00
										 |  |  | 	if (ast_strlen_zero(key)) { | 
					
						
							| 
									
										
										
										
											2005-01-29 23:33:14 +00:00
										 |  |  | 		astman_send_error(s, m, "No key specified"); | 
					
						
							|  |  |  | 		return 0; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-06-24 17:42:39 +00:00
										 |  |  | 	res = ast_db_put(family, key, S_OR(val, "")); | 
					
						
							| 
									
										
										
										
											2005-07-20 00:09:39 +00:00
										 |  |  | 	if (res) { | 
					
						
							| 
									
										
										
										
											2005-01-29 23:33:14 +00:00
										 |  |  | 		astman_send_error(s, m, "Failed to update entry"); | 
					
						
							| 
									
										
										
										
											2005-07-20 00:09:39 +00:00
										 |  |  | 	} else { | 
					
						
							| 
									
										
										
										
											2005-01-29 23:33:14 +00:00
										 |  |  | 		astman_send_ack(s, m, "Updated database successfully"); | 
					
						
							| 
									
										
										
										
											2005-07-20 00:09:39 +00:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2005-01-29 23:33:14 +00:00
										 |  |  | 	return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-01-05 22:43:18 +00:00
										 |  |  | static int manager_dbget(struct mansession *s, const struct message *m) | 
					
						
							| 
									
										
										
										
											2005-01-29 23:33:14 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2007-01-05 22:43:18 +00:00
										 |  |  | 	const char *id = astman_get_header(m,"ActionID"); | 
					
						
							| 
									
										
										
										
											2015-01-09 18:16:54 +00:00
										 |  |  | 	char idText[256]; | 
					
						
							| 
									
										
										
										
											2007-01-05 22:43:18 +00:00
										 |  |  | 	const char *family = astman_get_header(m, "Family"); | 
					
						
							|  |  |  | 	const char *key = astman_get_header(m, "Key"); | 
					
						
							| 
									
										
										
										
											2011-06-10 15:30:50 +00:00
										 |  |  | 	char tmp[MAX_DB_FIELD]; | 
					
						
							| 
									
										
										
										
											2005-01-29 23:33:14 +00:00
										 |  |  | 	int res; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-03-19 15:53:40 +00:00
										 |  |  | 	if (ast_strlen_zero(family)) { | 
					
						
							| 
									
										
										
										
											2005-01-29 23:33:14 +00:00
										 |  |  | 		astman_send_error(s, m, "No family specified."); | 
					
						
							|  |  |  | 		return 0; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2006-03-19 15:53:40 +00:00
										 |  |  | 	if (ast_strlen_zero(key)) { | 
					
						
							| 
									
										
										
										
											2005-01-29 23:33:14 +00:00
										 |  |  | 		astman_send_error(s, m, "No key specified."); | 
					
						
							|  |  |  | 		return 0; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-01-09 18:16:54 +00:00
										 |  |  | 	idText[0] = '\0'; | 
					
						
							| 
									
										
										
										
											2005-10-26 18:54:24 +00:00
										 |  |  | 	if (!ast_strlen_zero(id)) | 
					
						
							| 
									
										
										
										
											2005-07-20 00:38:20 +00:00
										 |  |  | 		snprintf(idText, sizeof(idText) ,"ActionID: %s\r\n", id); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-01-29 23:33:14 +00:00
										 |  |  | 	res = ast_db_get(family, key, tmp, sizeof(tmp)); | 
					
						
							| 
									
										
										
										
											2005-07-20 00:09:39 +00:00
										 |  |  | 	if (res) { | 
					
						
							| 
									
										
										
										
											2005-01-29 23:33:14 +00:00
										 |  |  | 		astman_send_error(s, m, "Database entry not found"); | 
					
						
							| 
									
										
										
										
											2005-07-20 00:09:39 +00:00
										 |  |  | 	} else { | 
					
						
							| 
									
										
										
										
											2015-01-12 18:09:27 +00:00
										 |  |  | 		astman_send_listack(s, m, "Result will follow", "start"); | 
					
						
							| 
									
										
										
										
											2015-01-09 18:16:54 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-03-25 23:50:09 +00:00
										 |  |  | 		astman_append(s, "Event: DBGetResponse\r\n" | 
					
						
							| 
									
										
										
										
											2005-01-29 23:33:14 +00:00
										 |  |  | 				"Family: %s\r\n" | 
					
						
							|  |  |  | 				"Key: %s\r\n" | 
					
						
							| 
									
										
										
										
											2005-07-20 00:38:20 +00:00
										 |  |  | 				"Val: %s\r\n" | 
					
						
							|  |  |  | 				"%s" | 
					
						
							|  |  |  | 				"\r\n", | 
					
						
							|  |  |  | 				family, key, tmp, idText); | 
					
						
							| 
									
										
										
										
											2015-01-09 18:16:54 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		astman_send_list_complete_start(s, m, "DBGetComplete", 1); | 
					
						
							|  |  |  | 		astman_send_list_complete_end(s); | 
					
						
							| 
									
										
										
										
											2005-01-29 23:33:14 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-01-25 22:49:24 +00:00
										 |  |  | static int manager_dbdel(struct mansession *s, const struct message *m) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	const char *family = astman_get_header(m, "Family"); | 
					
						
							|  |  |  | 	const char *key = astman_get_header(m, "Key"); | 
					
						
							|  |  |  | 	int res; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (ast_strlen_zero(family)) { | 
					
						
							|  |  |  | 		astman_send_error(s, m, "No family specified."); | 
					
						
							|  |  |  | 		return 0; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (ast_strlen_zero(key)) { | 
					
						
							|  |  |  | 		astman_send_error(s, m, "No key specified."); | 
					
						
							|  |  |  | 		return 0; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	res = ast_db_del(family, key); | 
					
						
							|  |  |  | 	if (res) | 
					
						
							|  |  |  | 		astman_send_error(s, m, "Database entry not found"); | 
					
						
							|  |  |  | 	else | 
					
						
							|  |  |  | 		astman_send_ack(s, m, "Key deleted successfully"); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int manager_dbdeltree(struct mansession *s, const struct message *m) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	const char *family = astman_get_header(m, "Family"); | 
					
						
							|  |  |  | 	const char *key = astman_get_header(m, "Key"); | 
					
						
							| 
									
										
										
										
											2012-10-04 15:48:24 +00:00
										 |  |  | 	int num_deleted; | 
					
						
							| 
									
										
										
										
											2007-01-25 22:49:24 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	if (ast_strlen_zero(family)) { | 
					
						
							|  |  |  | 		astman_send_error(s, m, "No family specified."); | 
					
						
							|  |  |  | 		return 0; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-10-04 15:48:24 +00:00
										 |  |  | 	if (!ast_strlen_zero(key)) { | 
					
						
							|  |  |  | 		num_deleted = ast_db_deltree(family, key); | 
					
						
							|  |  |  | 	} else { | 
					
						
							|  |  |  | 		num_deleted = ast_db_deltree(family, NULL); | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2007-01-25 22:49:24 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-10-04 15:48:24 +00:00
										 |  |  | 	if (num_deleted < 0) { | 
					
						
							|  |  |  | 		astman_send_error(s, m, "Database unavailable"); | 
					
						
							|  |  |  | 	} else if (num_deleted == 0) { | 
					
						
							| 
									
										
										
										
											2007-01-25 22:49:24 +00:00
										 |  |  | 		astman_send_error(s, m, "Database entry not found"); | 
					
						
							| 
									
										
										
										
											2012-10-04 15:48:24 +00:00
										 |  |  | 	} else { | 
					
						
							| 
									
										
										
										
											2007-01-25 22:49:24 +00:00
										 |  |  | 		astman_send_ack(s, m, "Key tree deleted successfully"); | 
					
						
							| 
									
										
										
										
											2012-10-04 15:48:24 +00:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2011-07-06 20:58:12 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-01-25 22:49:24 +00:00
										 |  |  | 	return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-09-13 22:13:27 +00:00
										 |  |  | /*!
 | 
					
						
							|  |  |  |  * \internal | 
					
						
							|  |  |  |  * \brief Signal the astdb sync thread to do its thing. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * \note dblock is assumed to be held when calling this function. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | static void db_sync(void) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2014-03-14 16:19:21 +00:00
										 |  |  | 	dosync = 1; | 
					
						
							| 
									
										
										
										
											2010-09-13 22:13:27 +00:00
										 |  |  | 	ast_cond_signal(&dbcond); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*!
 | 
					
						
							|  |  |  |  * \internal | 
					
						
							|  |  |  |  * \brief astdb sync thread | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * This thread is in charge of syncing astdb to disk after a change. | 
					
						
							|  |  |  |  * By pushing it off to this thread to take care of, this I/O bound operation | 
					
						
							|  |  |  |  * will not block other threads from performing other critical processing. | 
					
						
							|  |  |  |  * If changes happen rapidly, this thread will also ensure that the sync | 
					
						
							|  |  |  |  * operations are rate limited. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | static void *db_sync_thread(void *data) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	ast_mutex_lock(&dblock); | 
					
						
							| 
									
										
										
										
											2011-07-06 20:58:12 +00:00
										 |  |  | 	ast_db_begin_transaction(); | 
					
						
							| 
									
										
										
										
											2010-09-13 22:13:27 +00:00
										 |  |  | 	for (;;) { | 
					
						
							| 
									
										
										
										
											2017-12-22 09:23:22 -05:00
										 |  |  | 		/* If dosync is set, db_sync() was called during sleep(1),
 | 
					
						
							|  |  |  | 		 * and the pending transaction should be committed. | 
					
						
							| 
									
										
										
										
											2014-03-14 16:19:21 +00:00
										 |  |  | 		 * Otherwise, block until db_sync() is called. | 
					
						
							|  |  |  | 		 */ | 
					
						
							|  |  |  | 		while (!dosync) { | 
					
						
							|  |  |  | 			ast_cond_wait(&dbcond, &dblock); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		dosync = 0; | 
					
						
							| 
									
										
										
										
											2011-07-06 20:58:12 +00:00
										 |  |  | 		if (ast_db_commit_transaction()) { | 
					
						
							|  |  |  | 			ast_db_rollback_transaction(); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		if (doexit) { | 
					
						
							|  |  |  | 			ast_mutex_unlock(&dblock); | 
					
						
							|  |  |  | 			break; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		ast_db_begin_transaction(); | 
					
						
							| 
									
										
										
										
											2010-09-13 22:13:27 +00:00
										 |  |  | 		ast_mutex_unlock(&dblock); | 
					
						
							|  |  |  | 		sleep(1); | 
					
						
							|  |  |  | 		ast_mutex_lock(&dblock); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return NULL; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-08-16 17:33:21 +00:00
										 |  |  | /*!
 | 
					
						
							|  |  |  |  * \internal | 
					
						
							|  |  |  |  * \brief Clean up resources on Asterisk shutdown | 
					
						
							|  |  |  |  */ | 
					
						
							| 
									
										
										
										
											2011-07-06 20:58:12 +00:00
										 |  |  | static void astdb_atexit(void) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2012-11-04 01:19:43 +00:00
										 |  |  | 	ast_cli_unregister_multiple(cli_database, ARRAY_LEN(cli_database)); | 
					
						
							| 
									
										
										
										
											2012-10-02 01:47:16 +00:00
										 |  |  | 	ast_manager_unregister("DBGet"); | 
					
						
							|  |  |  | 	ast_manager_unregister("DBPut"); | 
					
						
							|  |  |  | 	ast_manager_unregister("DBDel"); | 
					
						
							|  |  |  | 	ast_manager_unregister("DBDelTree"); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-01-09 19:37:23 +00:00
										 |  |  | 	/* Set doexit to 1 to kill thread. db_sync must be called with
 | 
					
						
							|  |  |  | 	 * mutex held. */ | 
					
						
							|  |  |  | 	ast_mutex_lock(&dblock); | 
					
						
							| 
									
										
										
										
											2014-03-14 16:19:21 +00:00
										 |  |  | 	doexit = 1; | 
					
						
							| 
									
										
										
										
											2011-07-06 20:58:12 +00:00
										 |  |  | 	db_sync(); | 
					
						
							| 
									
										
										
										
											2012-01-09 19:37:23 +00:00
										 |  |  | 	ast_mutex_unlock(&dblock); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-07-06 20:58:12 +00:00
										 |  |  | 	pthread_join(syncthread, NULL); | 
					
						
							|  |  |  | 	ast_mutex_lock(&dblock); | 
					
						
							| 
									
										
										
										
											2012-11-04 01:19:43 +00:00
										 |  |  | 	clean_statements(); | 
					
						
							|  |  |  | 	if (sqlite3_close(astdb) == SQLITE_OK) { | 
					
						
							|  |  |  | 		astdb = NULL; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2011-07-06 20:58:12 +00:00
										 |  |  | 	ast_mutex_unlock(&dblock); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2003-01-30 15:03:20 +00:00
										 |  |  | int astdb_init(void) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2019-12-27 18:29:45 -05:00
										 |  |  | 	ast_cond_init(&dbcond, NULL); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-07-06 20:58:12 +00:00
										 |  |  | 	if (db_init()) { | 
					
						
							|  |  |  | 		return -1; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2010-09-13 22:13:27 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-07-06 20:58:12 +00:00
										 |  |  | 	if (ast_pthread_create_background(&syncthread, NULL, db_sync_thread, NULL)) { | 
					
						
							| 
									
										
										
										
											2010-09-13 22:13:27 +00:00
										 |  |  | 		return -1; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-07-06 20:58:12 +00:00
										 |  |  | 	ast_register_atexit(astdb_atexit); | 
					
						
							| 
									
										
										
										
											2008-12-05 10:31:25 +00:00
										 |  |  | 	ast_cli_register_multiple(cli_database, ARRAY_LEN(cli_database)); | 
					
						
							| 
									
										
										
										
											2012-03-20 17:31:28 +00:00
										 |  |  | 	ast_manager_register_xml_core("DBGet", EVENT_FLAG_SYSTEM | EVENT_FLAG_REPORTING, manager_dbget); | 
					
						
							|  |  |  | 	ast_manager_register_xml_core("DBPut", EVENT_FLAG_SYSTEM, manager_dbput); | 
					
						
							|  |  |  | 	ast_manager_register_xml_core("DBDel", EVENT_FLAG_SYSTEM, manager_dbdel); | 
					
						
							|  |  |  | 	ast_manager_register_xml_core("DBDelTree", EVENT_FLAG_SYSTEM, manager_dbdeltree); | 
					
						
							| 
									
										
										
										
											2003-01-30 15:03:20 +00:00
										 |  |  | 	return 0; | 
					
						
							|  |  |  | } |