diff options
-rw-r--r-- | apps/app_chanspy.c | 4 | ||||
-rw-r--r-- | apps/app_dial.c | 8 | ||||
-rw-r--r-- | apps/app_queue.c | 10 | ||||
-rw-r--r-- | apps/app_speech_utils.c | 2 | ||||
-rw-r--r-- | apps/app_stack.c | 4 | ||||
-rw-r--r-- | channels/chan_iax2.c | 18 | ||||
-rw-r--r-- | funcs/func_enum.c | 2 | ||||
-rw-r--r-- | funcs/func_global.c | 4 | ||||
-rw-r--r-- | funcs/func_lock.c | 4 | ||||
-rw-r--r-- | funcs/func_odbc.c | 6 | ||||
-rw-r--r-- | funcs/func_speex.c | 8 | ||||
-rw-r--r-- | funcs/func_volume.c | 4 | ||||
-rw-r--r-- | include/asterisk/channel.h | 55 | ||||
-rw-r--r-- | include/asterisk/datastore.h | 78 | ||||
-rw-r--r-- | include/asterisk/manager.h | 26 | ||||
-rw-r--r-- | main/Makefile | 2 | ||||
-rw-r--r-- | main/audiohook.c | 4 | ||||
-rw-r--r-- | main/channel.c | 66 | ||||
-rw-r--r-- | main/datastore.c | 73 | ||||
-rw-r--r-- | main/manager.c | 58 | ||||
-rw-r--r-- | main/pbx.c | 6 | ||||
-rw-r--r-- | pbx/pbx_dundi.c | 2 | ||||
-rw-r--r-- | pbx/pbx_lua.c | 6 | ||||
-rw-r--r-- | res/res_agi.c | 4 | ||||
-rw-r--r-- | res/res_smdi.c | 2 |
25 files changed, 316 insertions, 140 deletions
diff --git a/apps/app_chanspy.c b/apps/app_chanspy.c index 4c5ab3333..b59b03f69 100644 --- a/apps/app_chanspy.c +++ b/apps/app_chanspy.c @@ -560,7 +560,7 @@ static struct chanspy_ds *chanspy_ds_free(struct chanspy_ds *chanspy_ds) /* chanspy_ds->chan is NULL after this call */ chanspy_ds_destroy(datastore->data); datastore->data = NULL; - ast_channel_datastore_free(datastore); + ast_datastore_free(datastore); } ast_channel_unlock(chan); } @@ -576,7 +576,7 @@ static struct chanspy_ds *setup_chanspy_ds(struct ast_channel *chan, struct chan ast_mutex_lock(&chanspy_ds->lock); - if (!(datastore = ast_channel_datastore_alloc(&chanspy_ds_info, chanspy_ds->unique_id))) { + if (!(datastore = ast_datastore_alloc(&chanspy_ds_info, chanspy_ds->unique_id))) { ast_mutex_unlock(&chanspy_ds->lock); chanspy_ds = chanspy_ds_free(chanspy_ds); ast_channel_unlock(chan); diff --git a/apps/app_dial.c b/apps/app_dial.c index 9b5fe44df..07cbf51ee 100644 --- a/apps/app_dial.c +++ b/apps/app_dial.c @@ -1354,7 +1354,7 @@ static int dial_exec_full(struct ast_channel *chan, void *data, struct ast_flags ast_copy_flags64(peerflags, &opts, OPT_DTMF_EXIT | OPT_GO_ON | OPT_ORIGINAL_CLID | OPT_CALLER_HANGUP | OPT_IGNORE_FORWARDING); /* Create datastore for channel dial features for caller */ - if (!(ds_caller_features = ast_channel_datastore_alloc(&dial_features_info, NULL))) { + if (!(ds_caller_features = ast_datastore_alloc(&dial_features_info, NULL))) { ast_log(LOG_WARNING, "Unable to create channel datastore for dial features. Aborting!\n"); goto out; } @@ -1416,7 +1416,7 @@ static int dial_exec_full(struct ast_channel *chan, void *data, struct ast_flags if (datastore) dialed_interfaces = datastore->data; else { - if (!(datastore = ast_channel_datastore_alloc(&dialed_interface_info, NULL))) { + if (!(datastore = ast_datastore_alloc(&dialed_interface_info, NULL))) { ast_log(LOG_WARNING, "Unable to create channel datastore for dialed interfaces. Aborting!\n"); ast_free(tmp); goto out; @@ -1522,7 +1522,7 @@ static int dial_exec_full(struct ast_channel *chan, void *data, struct ast_flags ast_copy_string(tc->exten, chan->exten, sizeof(tc->exten)); /* Save callee features */ - if (!(ds_callee_features = ast_channel_datastore_alloc(&dial_features_info, NULL))) { + if (!(ds_callee_features = ast_datastore_alloc(&dial_features_info, NULL))) { ast_log(LOG_WARNING, "Unable to create channel datastore for dial features. Aborting!\n"); ast_free(tmp); goto out; @@ -1624,7 +1624,7 @@ static int dial_exec_full(struct ast_channel *chan, void *data, struct ast_flags * datastore again, causing a crash */ if (!ast_channel_datastore_remove(chan, datastore)) - ast_channel_datastore_free(datastore); + ast_datastore_free(datastore); if (!peer) { if (result) { res = result; diff --git a/apps/app_queue.c b/apps/app_queue.c index eb7cf0f78..e32442bca 100644 --- a/apps/app_queue.c +++ b/apps/app_queue.c @@ -3120,7 +3120,7 @@ static void queue_transfer_fixup(void *data, struct ast_channel *old_chan, struc } ast_channel_datastore_remove(new_chan, datastore); - ast_channel_datastore_free(datastore); + ast_datastore_free(datastore); } /*! \brief mechanism to tell if a queue caller was atxferred by a queue member. @@ -3147,7 +3147,7 @@ static void setup_transfer_datastore(struct queue_ent *qe, struct member *member } ast_channel_lock(qe->chan); - if (!(ds = ast_channel_datastore_alloc(&queue_transfer_info, NULL))) { + if (!(ds = ast_datastore_alloc(&queue_transfer_info, NULL))) { ast_channel_unlock(qe->chan); ast_log(LOG_WARNING, "Unable to create transfer datastore. queue_log will not show attended transfer\n"); return; @@ -3321,7 +3321,7 @@ static int try_calling(struct queue_ent *qe, const char *options, char *announce goto out; } if (!datastore) { - if (!(datastore = ast_channel_datastore_alloc(&dialed_interface_info, NULL))) { + if (!(datastore = ast_datastore_alloc(&dialed_interface_info, NULL))) { ao2_ref(cur, -1); ao2_unlock(qe->parent); if (use_weight) @@ -3423,7 +3423,7 @@ static int try_calling(struct queue_ent *qe, const char *options, char *announce * datastore again, causing a crash */ if (datastore && !ast_channel_datastore_remove(qe->chan, datastore)) { - ast_channel_datastore_free(datastore); + ast_datastore_free(datastore); } ao2_lock(qe->parent); if (qe->parent->strategy == QUEUE_STRATEGY_RRMEMORY) { @@ -3845,7 +3845,7 @@ static int try_calling(struct queue_ent *qe, const char *options, char *announce transfer_ds = ast_channel_datastore_find(qe->chan, &queue_transfer_info, NULL); if (transfer_ds) { ast_channel_datastore_remove(qe->chan, transfer_ds); - ast_channel_datastore_free(transfer_ds); + ast_datastore_free(transfer_ds); } ast_channel_unlock(qe->chan); } diff --git a/apps/app_speech_utils.c b/apps/app_speech_utils.c index 568c01bc3..939a92f58 100644 --- a/apps/app_speech_utils.c +++ b/apps/app_speech_utils.c @@ -364,7 +364,7 @@ static int speech_create(struct ast_channel *chan, void *data) return 0; } - datastore = ast_channel_datastore_alloc(&speech_datastore, NULL); + datastore = ast_datastore_alloc(&speech_datastore, NULL); if (datastore == NULL) { ast_speech_destroy(speech); pbx_builtin_setvar_helper(chan, "ERROR", "1"); diff --git a/apps/app_stack.c b/apps/app_stack.c index 669f7f4e7..4c42a0158 100644 --- a/apps/app_stack.c +++ b/apps/app_stack.c @@ -242,7 +242,7 @@ static int gosub_exec(struct ast_channel *chan, void *data) if (!stack_store) { ast_debug(1, "Channel %s has no datastore, so we're allocating one.\n", chan->name); - stack_store = ast_channel_datastore_alloc(&stack_info, NULL); + stack_store = ast_datastore_alloc(&stack_info, NULL); if (!stack_store) { ast_log(LOG_ERROR, "Unable to allocate new datastore. Gosub will fail.\n"); return -1; @@ -251,7 +251,7 @@ static int gosub_exec(struct ast_channel *chan, void *data) oldlist = ast_calloc(1, sizeof(*oldlist)); if (!oldlist) { ast_log(LOG_ERROR, "Unable to allocate datastore list head. Gosub will fail.\n"); - ast_channel_datastore_free(stack_store); + ast_datastore_free(stack_store); return -1; } diff --git a/channels/chan_iax2.c b/channels/chan_iax2.c index 6722818ce..34f4843de 100644 --- a/channels/chan_iax2.c +++ b/channels/chan_iax2.c @@ -6474,7 +6474,7 @@ static int authenticate_reply(struct chan_iax2_pvt *p, struct sockaddr_in *sin, struct ast_variable *var, *prev = NULL; AST_LIST_HEAD(, ast_var_t) *varlist; varlist = ast_calloc(1, sizeof(*varlist)); - variablestore = ast_channel_datastore_alloc(&iax2_variable_datastore_info, NULL); + variablestore = ast_datastore_alloc(&iax2_variable_datastore_info, NULL); if (variablestore && varlist && p->owner) { variablestore->data = varlist; variablestore->inheritance = DATASTORE_INHERIT_FOREVER; @@ -6499,7 +6499,7 @@ static int authenticate_reply(struct chan_iax2_pvt *p, struct sockaddr_in *sin, if (p->owner) ast_log(LOG_ERROR, "Memory allocation error while processing IAX2 variables\n"); if (variablestore) - ast_channel_datastore_free(variablestore); + ast_datastore_free(variablestore); if (varlist) ast_free(varlist); } @@ -7967,7 +7967,7 @@ static int acf_iaxvar_write(struct ast_channel *chan, const char *cmd, char *dat struct ast_var_t *var; if (!variablestore) { - variablestore = ast_channel_datastore_alloc(&iax2_variable_datastore_info, NULL); + variablestore = ast_datastore_alloc(&iax2_variable_datastore_info, NULL); if (!variablestore) { ast_log(LOG_ERROR, "Memory allocation error\n"); return -1; @@ -8362,7 +8362,7 @@ static int socket_process(struct iax2_thread *thread) struct ast_variable *var, *prev = NULL; AST_LIST_HEAD(, ast_var_t) *varlist; varlist = ast_calloc(1, sizeof(*varlist)); - variablestore = ast_channel_datastore_alloc(&iax2_variable_datastore_info, NULL); + variablestore = ast_datastore_alloc(&iax2_variable_datastore_info, NULL); if (variablestore && varlist) { variablestore->data = varlist; variablestore->inheritance = DATASTORE_INHERIT_FOREVER; @@ -8386,7 +8386,7 @@ static int socket_process(struct iax2_thread *thread) } else { ast_log(LOG_ERROR, "Memory allocation error while processing IAX2 variables\n"); if (variablestore) - ast_channel_datastore_free(variablestore); + ast_datastore_free(variablestore); if (varlist) ast_free(varlist); } @@ -9139,7 +9139,7 @@ retryowner2: struct ast_variable *var, *prev = NULL; AST_LIST_HEAD(, ast_var_t) *varlist; varlist = ast_calloc(1, sizeof(*varlist)); - variablestore = ast_channel_datastore_alloc(&iax2_variable_datastore_info, NULL); + variablestore = ast_datastore_alloc(&iax2_variable_datastore_info, NULL); if (variablestore && varlist) { variablestore->data = varlist; variablestore->inheritance = DATASTORE_INHERIT_FOREVER; @@ -9163,7 +9163,7 @@ retryowner2: } else { ast_log(LOG_ERROR, "Memory allocation error while processing IAX2 variables\n"); if (variablestore) - ast_channel_datastore_free(variablestore); + ast_datastore_free(variablestore); if (varlist) ast_free(varlist); } @@ -9203,7 +9203,7 @@ retryowner2: struct ast_variable *var, *prev = NULL; AST_LIST_HEAD(, ast_var_t) *varlist; varlist = ast_calloc(1, sizeof(*varlist)); - variablestore = ast_channel_datastore_alloc(&iax2_variable_datastore_info, NULL); + variablestore = ast_datastore_alloc(&iax2_variable_datastore_info, NULL); if (variablestore && varlist) { variablestore->data = varlist; variablestore->inheritance = DATASTORE_INHERIT_FOREVER; @@ -9227,7 +9227,7 @@ retryowner2: } else { ast_log(LOG_ERROR, "Memory allocation error while processing IAX2 variables\n"); if (variablestore) - ast_channel_datastore_free(variablestore); + ast_datastore_free(variablestore); if (varlist) ast_free(varlist); } diff --git a/funcs/func_enum.c b/funcs/func_enum.c index 0fba5af3b..54893a9bf 100644 --- a/funcs/func_enum.c +++ b/funcs/func_enum.c @@ -189,7 +189,7 @@ static int enum_query_read(struct ast_channel *chan, const char *cmd, char *data snprintf(buf, len, "%u", erds->id); - if (!(datastore = ast_channel_datastore_alloc(&enum_result_datastore_info, buf))) { + if (!(datastore = ast_datastore_alloc(&enum_result_datastore_info, buf))) { ast_free(erds->context); ast_free(erds); goto finish; diff --git a/funcs/func_global.c b/funcs/func_global.c index d97379ce9..3380cef12 100644 --- a/funcs/func_global.c +++ b/funcs/func_global.c @@ -158,7 +158,7 @@ static int shared_write(struct ast_channel *chan, const char *cmd, char *data, c ast_channel_lock(chan); if (!(varstore = ast_channel_datastore_find(chan, &shared_variable_info, NULL))) { - if (!(varstore = ast_channel_datastore_alloc(&shared_variable_info, NULL))) { + if (!(varstore = ast_datastore_alloc(&shared_variable_info, NULL))) { ast_log(LOG_ERROR, "Unable to allocate new datastore. Shared variable not set.\n"); ast_channel_unlock(chan); return -1; @@ -166,7 +166,7 @@ static int shared_write(struct ast_channel *chan, const char *cmd, char *data, c if (!(varshead = ast_calloc(1, sizeof(*varshead)))) { ast_log(LOG_ERROR, "Unable to allocate variable structure. Shared variable not set.\n"); - ast_channel_datastore_free(varstore); + ast_datastore_free(varstore); ast_channel_unlock(chan); return -1; } diff --git a/funcs/func_lock.c b/funcs/func_lock.c index 53b05a3e8..133ea3e22 100644 --- a/funcs/func_lock.c +++ b/funcs/func_lock.c @@ -96,7 +96,7 @@ static int get_lock(struct ast_channel *chan, char *lockname, int try) if (!lock_store) { ast_debug(1, "Channel %s has no lock datastore, so we're allocating one.\n", chan->name); - lock_store = ast_channel_datastore_alloc(&lock_info, NULL); + lock_store = ast_datastore_alloc(&lock_info, NULL); if (!lock_store) { ast_log(LOG_ERROR, "Unable to allocate new datastore. No locks will be obtained.\n"); return -1; @@ -105,7 +105,7 @@ static int get_lock(struct ast_channel *chan, char *lockname, int try) list = ast_calloc(1, sizeof(*list)); if (!list) { ast_log(LOG_ERROR, "Unable to allocate datastore list head. %sLOCK will fail.\n", try ? "TRY" : ""); - ast_channel_datastore_free(lock_store); + ast_datastore_free(lock_store); return -1; } diff --git a/funcs/func_odbc.c b/funcs/func_odbc.c index 13701873f..6ac47bdcb 100644 --- a/funcs/func_odbc.c +++ b/funcs/func_odbc.c @@ -480,7 +480,7 @@ end_acf_read: struct ast_datastore *odbc_store; uid = ast_atomic_fetchadd_int(&resultcount, +1) + 1; snprintf(buf, len, "%d", uid); - odbc_store = ast_channel_datastore_alloc(&odbc_info, buf); + odbc_store = ast_datastore_alloc(&odbc_info, buf); if (!odbc_store) { ast_log(LOG_ERROR, "Rows retrieved, but unable to store it in the channel. Results fail.\n"); odbc_datastore_free(resultset); @@ -550,7 +550,7 @@ static int acf_fetch(struct ast_channel *chan, const char *cmd, char *data, char if (!row) { /* Cleanup datastore */ ast_channel_datastore_remove(chan, store); - ast_channel_datastore_free(store); + ast_datastore_free(store); return -1; } pbx_builtin_setvar_helper(chan, "~ODBCFIELDS~", resultset->names); @@ -584,7 +584,7 @@ static int exec_odbcfinish(struct ast_channel *chan, void *data) if (!store) /* Already freed; no big deal. */ return 0; ast_channel_datastore_remove(chan, store); - ast_channel_datastore_free(store); + ast_datastore_free(store); return 0; } diff --git a/funcs/func_speex.c b/funcs/func_speex.c index 7b2484010..4ddfab80b 100644 --- a/funcs/func_speex.c +++ b/funcs/func_speex.c @@ -151,12 +151,12 @@ static int speex_write(struct ast_channel *chan, const char *cmd, char *data, co if (!(datastore = ast_channel_datastore_find(chan, &speex_datastore, NULL))) { ast_channel_unlock(chan); - if (!(datastore = ast_channel_datastore_alloc(&speex_datastore, NULL))) { + if (!(datastore = ast_datastore_alloc(&speex_datastore, NULL))) { return 0; } if (!(si = ast_calloc(1, sizeof(*si)))) { - ast_channel_datastore_free(datastore); + ast_datastore_free(datastore); return 0; } @@ -177,7 +177,7 @@ static int speex_write(struct ast_channel *chan, const char *cmd, char *data, co ast_log(LOG_ERROR, "Invalid argument provided to the %s function\n", cmd); if (is_new) { - ast_channel_datastore_free(datastore); + ast_datastore_free(datastore); return -1; } } @@ -237,7 +237,7 @@ static int speex_write(struct ast_channel *chan, const char *cmd, char *data, co ast_audiohook_detach(&si->audiohook); } - ast_channel_datastore_free(datastore); + ast_datastore_free(datastore); } if (is_new) { diff --git a/funcs/func_volume.c b/funcs/func_volume.c index 9a5247f54..530f9b876 100644 --- a/funcs/func_volume.c +++ b/funcs/func_volume.c @@ -106,10 +106,10 @@ static int volume_write(struct ast_channel *chan, const char *cmd, char *data, c if (!(datastore = ast_channel_datastore_find(chan, &volume_datastore, NULL))) { /* Allocate a new datastore to hold the reference to this volume and audiohook information */ - if (!(datastore = ast_channel_datastore_alloc(&volume_datastore, NULL))) + if (!(datastore = ast_datastore_alloc(&volume_datastore, NULL))) return 0; if (!(vi = ast_calloc(1, sizeof(*vi)))) { - ast_channel_datastore_free(datastore); + ast_datastore_free(datastore); return 0; } ast_audiohook_init(&vi->audiohook, AST_AUDIOHOOK_TYPE_MANIPULATE, "Volume"); diff --git a/include/asterisk/channel.h b/include/asterisk/channel.h index 5923f7cc1..6166359fa 100644 --- a/include/asterisk/channel.h +++ b/include/asterisk/channel.h @@ -150,8 +150,7 @@ extern "C" { #include "asterisk/utils.h" #include "asterisk/linkedlists.h" #include "asterisk/stringfields.h" - -#define DATASTORE_INHERIT_FOREVER INT_MAX +#include "asterisk/datastore.h" #define AST_MAX_FDS 10 /* @@ -186,37 +185,6 @@ struct ast_generator { void (*digit)(struct ast_channel *chan, char digit); }; -/*! \brief Structure for a data store type */ -struct ast_datastore_info { - const char *type; /*!< Type of data store */ - void *(*duplicate)(void *data); /*!< Duplicate item data (used for inheritance) */ - void (*destroy)(void *data); /*!< Destroy function */ - /*! - * \brief Fix up channel references - * - * \arg data The datastore data - * \arg old_chan The old channel owning the datastore - * \arg new_chan The new channel owning the datastore - * - * This is exactly like the fixup callback of the channel technology interface. - * It allows a datastore to fix any pointers it saved to the owning channel - * in case that the owning channel has changed. Generally, this would happen - * when the datastore is set to be inherited, and a masquerade occurs. - * - * \return nothing. - */ - void (*chan_fixup)(void *data, struct ast_channel *old_chan, struct ast_channel *new_chan); -}; - -/*! \brief Structure for a channel data store */ -struct ast_datastore { - const char *uid; /*!< Unique data store identifier */ - void *data; /*!< Contained data */ - const struct ast_datastore_info *info; /*!< Data store type information */ - unsigned int inheritance; /*!< Number of levels this item will continue to be inherited */ - AST_LIST_ENTRY(ast_datastore) entry; /*!< Used for easy linking */ -}; - /*! \brief Structure for all kinds of caller ID identifications. * \note All string fields here are malloc'ed, so they need to be * freed when the structure is deleted. @@ -653,16 +621,24 @@ enum channelreloadreason { }; /*! - * \brief Create a channel datastore structure - * * \note None of the datastore API calls lock the ast_channel they are using. * So, the channel should be locked before calling the functions that * take a channel argument. */ -struct ast_datastore *ast_channel_datastore_alloc(const struct ast_datastore_info *info, const char *uid); -/*! \brief Free a channel datastore structure */ -int ast_channel_datastore_free(struct ast_datastore *datastore); +/*! + * \brief Create a channel data store object + * \deprecated You should use the ast_datastore_alloc() generic function instead. + */ +struct ast_datastore *ast_channel_datastore_alloc(const struct ast_datastore_info *info, const char *uid) + __attribute__ ((deprecated)); + +/*! + * \brief Free a channel data store object + * \deprecated You should use the ast_datastore_free() generic function instead. + */ +int ast_channel_datastore_free(struct ast_datastore *datastore) + __attribute__ ((deprecated)); /*! \brief Inherit datastores from a parent to a child. */ int ast_channel_datastore_inherit(struct ast_channel *from, struct ast_channel *to); @@ -695,6 +671,9 @@ int ast_channel_datastore_remove(struct ast_channel *chan, struct ast_datastore * * \note The datastore returned from this function must not be used if the * reference to the channel is released. + * + * \retval pointer to the datastore if found + * \retval NULL if not found */ struct ast_datastore *ast_channel_datastore_find(struct ast_channel *chan, const struct ast_datastore_info *info, const char *uid); diff --git a/include/asterisk/datastore.h b/include/asterisk/datastore.h new file mode 100644 index 000000000..fe1ff8462 --- /dev/null +++ b/include/asterisk/datastore.h @@ -0,0 +1,78 @@ +/* + * Asterisk -- An open source telephony toolkit. + * + * Copyright (C) 2007 - 2008, Digium, Inc. + * + * 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. + * + * This program is free software, distributed under the terms of + * the GNU General Public License Version 2. See the LICENSE file + * at the top of the source tree. + */ + +/*! \file + * \brief Asterisk datastore objects + */ + +#ifndef _ASTERISK_DATASTORE_H +#define _ASTERISK_DATASTORE_H + +#if defined(__cplusplus) || defined(c_plusplus) +extern "C" { +#endif + +#include "asterisk/linkedlists.h" + +#define DATASTORE_INHERIT_FOREVER INT_MAX + +/*! \brief Structure for a data store type */ +struct ast_datastore_info { + const char *type; /*!< Type of data store */ + void *(*duplicate)(void *data); /*!< Duplicate item data (used for inheritance) */ + void (*destroy)(void *data); /*!< Destroy function */ + + /*! + * \brief Fix up channel references + * + * \arg data The datastore data + * \arg old_chan The old channel owning the datastore + * \arg new_chan The new channel owning the datastore + * + * This is exactly like the fixup callback of the channel technology interface. + * It allows a datastore to fix any pointers it saved to the owning channel + * in case that the owning channel has changed. Generally, this would happen + * when the datastore is set to be inherited, and a masquerade occurs. + * + * \return nothing. + */ + void (*chan_fixup)(void *data, struct ast_channel *old_chan, struct ast_channel *new_chan); +}; + +/*! \brief Structure for a data store object */ +struct ast_datastore { + const char *uid; /*!< Unique data store identifier */ + void *data; /*!< Contained data */ + const struct ast_datastore_info *info; /*!< Data store type information */ + unsigned int inheritance; /*!< Number of levels this item will continue to be inherited */ + AST_LIST_ENTRY(ast_datastore) entry; /*!< Used for easy linking */ +}; + +/*! + * \brief Create a data store object + */ +struct ast_datastore *ast_datastore_alloc(const struct ast_datastore_info *info, const char *uid); + +/*! + * \brief Free a data store object + */ +int ast_datastore_free(struct ast_datastore *datastore); + +#if defined(__cplusplus) || defined(c_plusplus) +} +#endif + +#endif /* _ASTERISK_DATASTORE_H */ diff --git a/include/asterisk/manager.h b/include/asterisk/manager.h index ecc047829..fa1d27292 100644 --- a/include/asterisk/manager.h +++ b/include/asterisk/manager.h @@ -21,6 +21,7 @@ #include "asterisk/network.h" #include "asterisk/lock.h" +#include "asterisk/datastore.h" /*! \file @@ -212,4 +213,29 @@ int init_manager(void); /*! \brief Called by Asterisk module functions and the CLI command */ int reload_manager(void); +/*! + * \brief Add a datastore to a session + * + * \retval 0 success + * \retval non-zero failure + */ + +int astman_datastore_add(struct mansession *s, struct ast_datastore *datastore); + +/*! + * \brief Remove a datastore from a session + * + * \retval 0 success + * \retval non-zero failure + */ +int astman_datastore_remove(struct mansession *s, struct ast_datastore *datastore); + +/*! + * \brief Find a datastore on a session + * + * \retval pointer to the datastore if found + * \retval NULL if not found + */ +struct ast_datastore *astman_datastore_find(struct mansession *s, const struct ast_datastore_info *info, const char *uid); + #endif /* _ASTERISK_MANAGER_H */ diff --git a/main/Makefile b/main/Makefile index a985819de..db4aad7e4 100644 --- a/main/Makefile +++ b/main/Makefile @@ -28,7 +28,7 @@ OBJS= tcptls.o io.o sched.o logger.o frame.o loader.o config.o channel.o \ cryptostub.o sha1.o http.o fixedjitterbuf.o abstract_jb.o \ strcompat.o threadstorage.o dial.o event.o adsistub.o audiohook.o \ astobj2.o hashtab.o global_datastores.o version.o \ - features.o taskprocessor.o timing.o + features.o taskprocessor.o timing.o datastore.o # we need to link in the objects statically, not as a library, because # otherwise modules will not have them available if none of the static diff --git a/main/audiohook.c b/main/audiohook.c index bd30ab772..2145154ae 100644 --- a/main/audiohook.c +++ b/main/audiohook.c @@ -843,13 +843,13 @@ static struct audiohook_volume *audiohook_volume_get(struct ast_channel *chan, i } /* If we are not allowed to create a datastore or if we fail to create a datastore, bail out now as we have nothing for them */ - if (!create || !(datastore = ast_channel_datastore_alloc(&audiohook_volume_datastore, NULL))) { + if (!create || !(datastore = ast_datastore_alloc(&audiohook_volume_datastore, NULL))) { return NULL; } /* Create a new audiohook_volume structure to contain our adjustments and audiohook */ if (!(audiohook_volume = ast_calloc(1, sizeof(*audiohook_volume)))) { - ast_channel_datastore_free(datastore); + ast_datastore_free(datastore); return NULL; } diff --git a/main/channel.c b/main/channel.c index 3a9726393..98a89f0dc 100644 --- a/main/channel.c +++ b/main/channel.c @@ -1294,7 +1294,7 @@ void ast_channel_free(struct ast_channel *chan) /* Get rid of each of the data stores on the channel */ while ((datastore = AST_LIST_REMOVE_HEAD(&chan->datastores, entry))) /* Free the data store */ - ast_channel_datastore_free(datastore); + ast_datastore_free(datastore); /* Lock and unlock the channel just to be sure nobody has it locked still due to a reference that was stored in a datastore. (i.e. app_chanspy) */ @@ -1369,46 +1369,12 @@ void ast_channel_free(struct ast_channel *chan) struct ast_datastore *ast_channel_datastore_alloc(const struct ast_datastore_info *info, const char *uid) { - struct ast_datastore *datastore = NULL; - - /* Make sure we at least have type so we can identify this */ - if (!info) { - return NULL; - } - - /* Allocate memory for datastore and clear it */ - datastore = ast_calloc(1, sizeof(*datastore)); - if (!datastore) { - return NULL; - } - - datastore->info = info; - - datastore->uid = ast_strdup(uid); - - return datastore; + return ast_datastore_alloc(info, uid); } int ast_channel_datastore_free(struct ast_datastore *datastore) { - int res = 0; - - /* Using the destroy function (if present) destroy the data */ - if (datastore->info->destroy != NULL && datastore->data != NULL) { - datastore->info->destroy(datastore->data); - datastore->data = NULL; - } - - /* Free allocated UID memory */ - if (datastore->uid != NULL) { - ast_free((void *) datastore->uid); - datastore->uid = NULL; - } - - /* Finally free memory used by ourselves */ - ast_free(datastore); - - return res; + return ast_datastore_free(datastore); } int ast_channel_datastore_inherit(struct ast_channel *from, struct ast_channel *to) @@ -1417,7 +1383,7 @@ int ast_channel_datastore_inherit(struct ast_channel *from, struct ast_channel * AST_LIST_TRAVERSE(&from->datastores, datastore, entry) { if (datastore->inheritance > 0) { - datastore2 = ast_channel_datastore_alloc(datastore->info, datastore->uid); + datastore2 = ast_datastore_alloc(datastore->info, datastore->uid); if (datastore2) { datastore2->data = datastore->info->duplicate(datastore->data); datastore2->inheritance = datastore->inheritance == DATASTORE_INHERIT_FOREVER ? DATASTORE_INHERIT_FOREVER : datastore->inheritance - 1; @@ -1450,19 +1416,21 @@ struct ast_datastore *ast_channel_datastore_find(struct ast_channel *chan, const return NULL; AST_LIST_TRAVERSE_SAFE_BEGIN(&chan->datastores, datastore, entry) { - if (datastore->info == info) { - if (uid != NULL && datastore->uid != NULL) { - if (!strcasecmp(uid, datastore->uid)) { - /* Matched by type AND uid */ - break; - } - } else { - /* Matched by type at least */ - break; - } + if (datastore->info != info) { + continue; + } + + if (uid == NULL) { + /* matched by type only */ + break; + } + + if ((datastore->uid != NULL) && !strcasecmp(uid, datastore->uid)) { + /* Matched by type AND uid */ + break; } } - AST_LIST_TRAVERSE_SAFE_END + AST_LIST_TRAVERSE_SAFE_END; return datastore; } diff --git a/main/datastore.c b/main/datastore.c new file mode 100644 index 000000000..be5479796 --- /dev/null +++ b/main/datastore.c @@ -0,0 +1,73 @@ +/* + * Asterisk -- An open source telephony toolkit. + * + * Copyright (C) 2007 - 2008, Digium, Inc. + * + * 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. + * + * This program is free software, distributed under the terms of + * the GNU General Public License Version 2. See the LICENSE file + * at the top of the source tree. + */ + +/*! \file + * + * \brief Asterisk datastore objects + */ + +#include "asterisk.h" + +ASTERISK_FILE_VERSION(__FILE__, "$Revision$") + +#include "asterisk/_private.h" + +#include "asterisk/datastore.h" +#include "asterisk/utils.h" + +struct ast_datastore *ast_datastore_alloc(const struct ast_datastore_info *info, const char *uid) +{ + struct ast_datastore *datastore = NULL; + + /* Make sure we at least have type so we can identify this */ + if (!info) { + return NULL; + } + + /* Allocate memory for datastore and clear it */ + datastore = ast_calloc(1, sizeof(*datastore)); + if (!datastore) { + return NULL; + } + + datastore->info = info; + + datastore->uid = ast_strdup(uid); + + return datastore; +} + +int ast_datastore_free(struct ast_datastore *datastore) +{ + int res = 0; + + /* Using the destroy function (if present) destroy the data */ + if (datastore->info->destroy != NULL && datastore->data != NULL) { + datastore->info->destroy(datastore->data); + datastore->data = NULL; + } + + /* Free allocated UID memory */ + if (datastore->uid != NULL) { + ast_free((void *) datastore->uid); + datastore->uid = NULL; + } + + /* Finally free memory used by ourselves */ + ast_free(datastore); + + return res; +} diff --git a/main/manager.c b/main/manager.c index 746da3b86..e038b740c 100644 --- a/main/manager.c +++ b/main/manager.c @@ -172,6 +172,7 @@ struct mansession { struct eventqent *last_ev; /*!< last event processed. */ int writetimeout; /*!< Timeout for ast_carefulwrite() */ int pending_event; /*!< Pending events indicator in case when waiting_thread is NULL */ + AST_LIST_HEAD_NOLOCK(mansession_datastores, ast_datastore) datastores; /*!< Data stores on the session */ AST_LIST_ENTRY(mansession) list; }; @@ -786,6 +787,14 @@ static void ref_event(struct eventqent *e) static void free_session(struct mansession *s) { struct eventqent *eqe = s->last_ev; + struct ast_datastore *datastore; + + /* Get rid of each of the data stores on the session */ + while ((datastore = AST_LIST_REMOVE_HEAD(&s->datastores, entry))) { + /* Free the data store */ + ast_datastore_free(datastore); + } + if (s->f != NULL) fclose(s->f); ast_mutex_destroy(&s->__lock); @@ -3092,18 +3101,21 @@ static void *session_do(void *data) ast_mutex_init(&s->__lock); s->send_events = -1; + /* Hook to the tail of the event queue */ + s->last_ev = grab_last(); + /* these fields duplicate those in the 'ser' structure */ s->fd = ser->fd; s->f = ser->f; s->sin = ser->requestor; + AST_LIST_HEAD_INIT_NOLOCK(&s->datastores); + AST_LIST_LOCK(&sessions); AST_LIST_INSERT_HEAD(&sessions, s, list); ast_atomic_fetchadd_int(&num_sessions, 1); AST_LIST_UNLOCK(&sessions); - /* Hook to the tail of the event queue */ - s->last_ev = grab_last(); - s->f = ser->f; + astman_append(s, "Asterisk Call Manager/%s\r\n", AMI_VERSION); /* welcome prompt */ for (;;) { if ((res = do_message(s)) < 0) @@ -3729,6 +3741,7 @@ static struct ast_str *generic_http_callback(enum output_format format, */ while ((s->managerid = rand() ^ (unsigned long) s) == 0); s->last_ev = grab_last(); + AST_LIST_HEAD_INIT_NOLOCK(&s->datastores); AST_LIST_LOCK(&sessions); AST_LIST_INSERT_HEAD(&sessions, s, list); ast_atomic_fetchadd_int(&num_sessions, 1); @@ -4258,3 +4271,42 @@ int reload_manager(void) { return __init_manager(1); } + +int astman_datastore_add(struct mansession *s, struct ast_datastore *datastore) +{ + AST_LIST_INSERT_HEAD(&s->datastores, datastore, entry); + + return 0; +} + +int astman_datastore_remove(struct mansession *s, struct ast_datastore *datastore) +{ + return AST_LIST_REMOVE(&s->datastores, datastore, entry) ? 0 : -1; +} + +struct ast_datastore *astman_datastore_find(struct mansession *s, const struct ast_datastore_info *info, const char *uid) +{ + struct ast_datastore *datastore = NULL; + + if (info == NULL) + return NULL; + + AST_LIST_TRAVERSE_SAFE_BEGIN(&s->datastores, datastore, entry) { + if (datastore->info != info) { + continue; + } + + if (uid == NULL) { + /* matched by type only */ + break; + } + + if ((datastore->uid != NULL) && !strcasecmp(uid, datastore->uid)) { + /* Matched by type AND uid */ + break; + } + } + AST_LIST_TRAVERSE_SAFE_END; + + return datastore; +} diff --git a/main/pbx.c b/main/pbx.c index 9772ca53c..3edea4e05 100644 --- a/main/pbx.c +++ b/main/pbx.c @@ -2558,17 +2558,17 @@ int pbx_builtin_raise_exception(struct ast_channel *chan, void *vreason) struct pbx_exception *exception = NULL; if (!ds) { - ds = ast_channel_datastore_alloc(&exception_store_info, NULL); + ds = ast_datastore_alloc(&exception_store_info, NULL); if (!ds) return -1; exception = ast_calloc(1, sizeof(struct pbx_exception)); if (!exception) { - ast_channel_datastore_free(ds); + ast_datastore_free(ds); return -1; } if (ast_string_field_init(exception, 128)) { ast_free(exception); - ast_channel_datastore_free(ds); + ast_datastore_free(ds); return -1; } ds->data = exception; diff --git a/pbx/pbx_dundi.c b/pbx/pbx_dundi.c index ca13bdc76..25206f156 100644 --- a/pbx/pbx_dundi.c +++ b/pbx/pbx_dundi.c @@ -3956,7 +3956,7 @@ static int dundi_query_read(struct ast_channel *chan, const char *cmd, char *dat drds->id = ast_atomic_fetchadd_int((int *) &dundi_result_id, 1); snprintf(buf, len, "%u", drds->id); - if (!(datastore = ast_channel_datastore_alloc(&dundi_result_datastore_info, buf))) { + if (!(datastore = ast_datastore_alloc(&dundi_result_datastore_info, buf))) { drds_destroy(drds); ast_module_user_remove(u); return -1; diff --git a/pbx/pbx_lua.c b/pbx/pbx_lua.c index 704d811de..689ba1c77 100644 --- a/pbx/pbx_lua.c +++ b/pbx/pbx_lua.c @@ -988,7 +988,7 @@ static lua_State *lua_get_state(struct ast_channel *chan) if (!datastore) { /* nothing found, allocate a new lua state */ - datastore = ast_channel_datastore_alloc(&lua_datastore, NULL); + datastore = ast_datastore_alloc(&lua_datastore, NULL); if (!datastore) { ast_log(LOG_ERROR, "Error allocation channel datastore for lua_State\n"); return NULL; @@ -996,7 +996,7 @@ static lua_State *lua_get_state(struct ast_channel *chan) datastore->data = luaL_newstate(); if (!datastore->data) { - ast_channel_datastore_free(datastore); + ast_datastore_free(datastore); ast_log(LOG_ERROR, "Error allocating lua_State, no memory\n"); return NULL; } @@ -1015,7 +1015,7 @@ static lua_State *lua_get_state(struct ast_channel *chan) ast_channel_datastore_remove(chan, datastore); ast_channel_unlock(chan); - ast_channel_datastore_free(datastore); + ast_datastore_free(datastore); return NULL; } } diff --git a/res/res_agi.c b/res/res_agi.c index 1de15c59a..8cfc391e2 100644 --- a/res/res_agi.c +++ b/res/res_agi.c @@ -255,14 +255,14 @@ static int add_to_agi(struct ast_channel *chan) /* the channel has never been on Async AGI, let's allocate it's datastore */ - datastore = ast_channel_datastore_alloc(&agi_commands_datastore_info, "AGI"); + datastore = ast_datastore_alloc(&agi_commands_datastore_info, "AGI"); if (!datastore) { return -1; } agi_cmds_list = ast_calloc(1, sizeof(*agi_cmds_list)); if (!agi_cmds_list) { ast_log(LOG_ERROR, "Unable to allocate Async AGI commands list.\n"); - ast_channel_datastore_free(datastore); + ast_datastore_free(datastore); return -1; } datastore->data = agi_cmds_list; diff --git a/res/res_smdi.c b/res/res_smdi.c index 9bcccab49..b6aa8024c 100644 --- a/res/res_smdi.c +++ b/res/res_smdi.c @@ -1162,7 +1162,7 @@ static int smdi_msg_retrieve_read(struct ast_channel *chan, const char *cmd, cha smd->id = ast_atomic_fetchadd_int((int *) &smdi_msg_id, 1); snprintf(buf, len, "%u", smd->id); - if (!(datastore = ast_channel_datastore_alloc(&smdi_msg_datastore_info, buf))) + if (!(datastore = ast_datastore_alloc(&smdi_msg_datastore_info, buf))) goto return_error; datastore->data = smd; |