Store custom device states in astdb so that they will persist a restart. As a

side benefit, this simplifies the code a bit, too.


git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@79098 65c4cc65-6c06-0410-ace0-fbb531ad65f3
This commit is contained in:
Russell Bryant 2007-08-10 20:48:49 +00:00
parent e927902fe7
commit 047dbef446
1 changed files with 34 additions and 47 deletions

View File

@ -41,14 +41,9 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/linkedlists.h" #include "asterisk/linkedlists.h"
#include "asterisk/devicestate.h" #include "asterisk/devicestate.h"
#include "asterisk/cli.h" #include "asterisk/cli.h"
#include "asterisk/astdb.h"
struct custom_device { static const char astdb_family[] = "CustomDevstate";
int state;
AST_RWLIST_ENTRY(custom_device) entry;
char name[1];
};
static AST_RWLIST_HEAD_STATIC(custom_devices, custom_device);
static int devstate_read(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len) static int devstate_read(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
{ {
@ -59,8 +54,7 @@ static int devstate_read(struct ast_channel *chan, const char *cmd, char *data,
static int devstate_write(struct ast_channel *chan, const char *cmd, char *data, const char *value) static int devstate_write(struct ast_channel *chan, const char *cmd, char *data, const char *value)
{ {
struct custom_device *dev; size_t len = strlen("Custom:");
int len = strlen("Custom:");
if (strncasecmp(data, "Custom:", len)) { if (strncasecmp(data, "Custom:", len)) {
ast_log(LOG_WARNING, "The DEVSTATE function can only be used to set 'Custom:' device state!\n"); ast_log(LOG_WARNING, "The DEVSTATE function can only be used to set 'Custom:' device state!\n");
@ -72,46 +66,25 @@ static int devstate_write(struct ast_channel *chan, const char *cmd, char *data,
return -1; return -1;
} }
AST_RWLIST_WRLOCK(&custom_devices); ast_db_put(astdb_family, data, value);
AST_RWLIST_TRAVERSE(&custom_devices, dev, entry) {
if (!strcasecmp(dev->name, data)) ast_devstate_changed(ast_devstate_val(value), "Custom:%s", data);
break;
}
if (!dev) {
if (!(dev = ast_calloc(1, sizeof(*dev) + strlen(data) + 1))) {
AST_RWLIST_UNLOCK(&custom_devices);
return -1;
}
strcpy(dev->name, data);
AST_RWLIST_INSERT_HEAD(&custom_devices, dev, entry);
}
dev->state = ast_devstate_val(value);
ast_devstate_changed(dev->state, "Custom:%s", dev->name);
AST_RWLIST_UNLOCK(&custom_devices);
return 0; return 0;
} }
static enum ast_device_state custom_devstate_callback(const char *data) static enum ast_device_state custom_devstate_callback(const char *data)
{ {
struct custom_device *dev; char buf[256] = "";
enum ast_device_state state = AST_DEVICE_UNKNOWN;
AST_RWLIST_RDLOCK(&custom_devices); ast_db_get(astdb_family, data, buf, sizeof(buf));
AST_RWLIST_TRAVERSE(&custom_devices, dev, entry) {
if (!strcasecmp(dev->name, data)) {
state = dev->state;
break;
}
}
AST_RWLIST_UNLOCK(&custom_devices);
return state; return ast_devstate_val(buf);
} }
static char *cli_funcdevstate_list(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) static char *cli_funcdevstate_list(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
{ {
struct custom_device *dev; struct ast_db_entry *db_entry, *db_tree;
switch (cmd) { switch (cmd) {
case CLI_INIT: case CLI_INIT:
@ -133,12 +106,18 @@ static char *cli_funcdevstate_list(struct ast_cli_entry *e, int cmd, struct ast_
"--- Custom Device States --------------------------------------------\n" "--- Custom Device States --------------------------------------------\n"
"---------------------------------------------------------------------\n" "---------------------------------------------------------------------\n"
"---\n"); "---\n");
AST_RWLIST_RDLOCK(&custom_devices);
AST_RWLIST_TRAVERSE(&custom_devices, dev, entry) { db_entry = db_tree = ast_db_gettree(astdb_family, NULL);
for (; db_entry; db_entry = db_entry->next) {
const char *dev_name = strrchr(db_entry->key, '/') + 1;
if (dev_name <= (const char *) 1)
continue;
ast_cli(a->fd, "--- Name: 'Custom:%s' State: '%s'\n" ast_cli(a->fd, "--- Name: 'Custom:%s' State: '%s'\n"
"---\n", dev->name, ast_devstate_str(dev->state)); "---\n", dev_name, db_entry->data);
} }
AST_RWLIST_UNLOCK(&custom_devices); ast_db_freetree(db_tree);
db_tree = NULL;
ast_cli(a->fd, ast_cli(a->fd,
"---------------------------------------------------------------------\n" "---------------------------------------------------------------------\n"
"---------------------------------------------------------------------\n" "---------------------------------------------------------------------\n"
@ -178,24 +157,32 @@ static struct ast_custom_function devstate_function = {
static int unload_module(void) static int unload_module(void)
{ {
struct custom_device *dev;
int res = 0; int res = 0;
res |= ast_custom_function_unregister(&devstate_function); res |= ast_custom_function_unregister(&devstate_function);
res |= ast_devstate_prov_del("Custom"); res |= ast_devstate_prov_del("Custom");
res |= ast_cli_unregister_multiple(cli_funcdevstate, ARRAY_LEN(cli_funcdevstate)); res |= ast_cli_unregister_multiple(cli_funcdevstate, ARRAY_LEN(cli_funcdevstate));
AST_RWLIST_WRLOCK(&custom_devices);
while ((dev = AST_RWLIST_REMOVE_HEAD(&custom_devices, entry)))
ast_free(dev);
AST_RWLIST_UNLOCK(&custom_devices);
return res; return res;
} }
static int load_module(void) static int load_module(void)
{ {
int res = 0; int res = 0;
struct ast_db_entry *db_entry, *db_tree;
/* Populate the device state cache on the system with all of the currently
* known custom device states. */
db_entry = db_tree = ast_db_gettree(astdb_family, NULL);
for (; db_entry; db_entry = db_entry->next) {
const char *dev_name = strrchr(db_entry->key, '/') + 1;
if (dev_name <= (const char *) 1)
continue;
ast_devstate_changed(ast_devstate_val(db_entry->data),
"Custom:%s\n", dev_name);
}
ast_db_freetree(db_tree);
db_tree = NULL;
res |= ast_custom_function_register(&devstate_function); res |= ast_custom_function_register(&devstate_function);
res |= ast_devstate_prov_add("Custom", custom_devstate_callback); res |= ast_devstate_prov_add("Custom", custom_devstate_callback);