make datastore creation and destruction a generic API since it is not really channel...
authorKevin P. Fleming <kpfleming@digium.com>
Tue, 5 Aug 2008 16:56:11 +0000 (16:56 +0000)
committerKevin P. Fleming <kpfleming@digium.com>
Tue, 5 Aug 2008 16:56:11 +0000 (16:56 +0000)
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@135680 65c4cc65-6c06-0410-ace0-fbb531ad65f3

25 files changed:
apps/app_chanspy.c
apps/app_dial.c
apps/app_queue.c
apps/app_speech_utils.c
apps/app_stack.c
channels/chan_iax2.c
funcs/func_enum.c
funcs/func_global.c
funcs/func_lock.c
funcs/func_odbc.c
funcs/func_speex.c
funcs/func_volume.c
include/asterisk/channel.h
include/asterisk/datastore.h [new file with mode: 0644]
include/asterisk/manager.h
main/Makefile
main/audiohook.c
main/channel.c
main/datastore.c [new file with mode: 0644]
main/manager.c
main/pbx.c
pbx/pbx_dundi.c
pbx/pbx_lua.c
res/res_agi.c
res/res_smdi.c

index 4c5ab33..b59b03f 100644 (file)
@@ -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);
index 9b5fe44..07cbf51 100644 (file)
@@ -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;
index eb7cf0f..e32442b 100644 (file)
@@ -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);
                }
index 568c01b..939a92f 100644 (file)
@@ -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");
index 669f7f4..4c42a01 100644 (file)
@@ -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;
                }
 
index 6722818..34f4843 100644 (file)
@@ -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);
                                                        }
index 0fba5af..54893a9 100644 (file)
@@ -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;
index d97379c..3380cef 100644 (file)
@@ -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;
                }
index 53b05a3..133ea3e 100644 (file)
@@ -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;
                }
 
index 1370187..6ac47bd 100644 (file)
@@ -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;
 }
 
index 7b24840..4ddfab8 100644 (file)
@@ -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) { 
index 9a5247f..530f9b8 100644 (file)
@@ -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");
index 5923f7c..6166359 100644 (file)
@@ -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 (file)
index 0000000..fe1ff84
--- /dev/null
@@ -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 */
index ecc0478..fa1d272 100644 (file)
@@ -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 */
index a985819..db4aad7 100644 (file)
@@ -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
index bd30ab7..2145154 100644 (file)
@@ -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;
        }
 
index 3a97263..98a89f0 100644 (file)
@@ -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 (file)
index 0000000..be54797
--- /dev/null
@@ -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;
+}
index 746da3b..e038b74 100644 (file)
@@ -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;
+}
index 9772ca5..3edea4e 100644 (file)
@@ -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;
index ca13bdc..25206f1 100644 (file)
@@ -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;
index 704d811..689ba1c 100644 (file)
@@ -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;
                        }
                }
index 1de15c5..8cfc391 100644 (file)
@@ -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;
index 9bcccab..b6aa802 100644 (file)
@@ -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;