Author: mjordan Date: Mon Mar 16 21:18:35 2015 New Revision: 433003 URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=433003 Log: Update with pre-review findings
Modified: team/mjordan/trunk-astdb-cluster/CHANGES team/mjordan/trunk-astdb-cluster/configs/samples/pjsip.conf.sample team/mjordan/trunk-astdb-cluster/funcs/func_db.c team/mjordan/trunk-astdb-cluster/include/asterisk/astdb.h team/mjordan/trunk-astdb-cluster/include/asterisk/event_defs.h team/mjordan/trunk-astdb-cluster/main/db.c team/mjordan/trunk-astdb-cluster/res/res_pjsip_publish_asterisk.c team/mjordan/trunk-astdb-cluster/tests/test_db.c Modified: team/mjordan/trunk-astdb-cluster/CHANGES URL: http://svnview.digium.com/svn/asterisk/team/mjordan/trunk-astdb-cluster/CHANGES?view=diff&rev=433003&r1=433002&r2=433003 ============================================================================== --- team/mjordan/trunk-astdb-cluster/CHANGES (original) +++ team/mjordan/trunk-astdb-cluster/CHANGES Mon Mar 16 21:18:35 2015 @@ -79,6 +79,28 @@ dedicated thread per consumer in certain cases. The initial settings for the thread pool can now be configured in 'stasis.conf'. + * The AstDB now has the ability to share families of key/value pairs with + other Asterisk servers. Families in the AstDB can be marked as shared using + dialplan functions (which can be accessed via AMI, AGI, and ARI) or CLI + commands. Sharing has two strategies: 'global' and 'unique'. Global shared + families have a common family name across all Asterisk servers, and any + update to a key in that shared family is reflected in the same family across + other servers. Unique shared families are distributes to other Asterisk servers, + but are placed in a new family that corresponds to the remote instance's + EID. Currently, the PJSIP stack is the only mechanism available to share + AstDB families. See CLI updates, DB_SHARED/DB_SHARED_EXISTS, and the + res_pjsip updates for more information. + +CLI +------------------ + * The 'database show' and 'database showkey' commands have been updated + to display the shared status of the family the key(s) reside in a new + column. A value of '(G)' indicates the key is shared 'globally', a value + of '(U)' indicates the key is shared 'uniquely'. + + * Added commands 'database put shared' and 'database del shared'. These + commands add/delete the shared status of AstDB families, respectively. + Functions ------------------ @@ -87,6 +109,15 @@ ------------------ * Added CHANNEL(onhold) item that returns 1 (onhold) and 0 (not-onhold) for the hold status of a channel. + +DB_SHARED +------------------ + * A new function, this will either create a new shared family in the AstDB + or delete an existing shared family. + +DB_SHARED_EXISTS +------------------ + * Determines whether an AstDB family is shared. DTMF Features ------------------ @@ -105,6 +136,13 @@ * Added preferchannelclass=no option to prefer the application-passed class over the channel-set musicclass. This allows separate hold-music from application (e.g. Queue or Dial) specified music. + +res_pjsip_publish_asterisk +------------------ + * Added the ability to distribute AstDB shared families between Asterisk + instances. This includes inbound/outbound PUBLISH support for a new event + type, 'asterisk-db'. + ------------------------------------------------------------------------------ --- Functionality changes from Asterisk 13.2.0 to Asterisk 13.3.0 ------------ Modified: team/mjordan/trunk-astdb-cluster/configs/samples/pjsip.conf.sample URL: http://svnview.digium.com/svn/asterisk/team/mjordan/trunk-astdb-cluster/configs/samples/pjsip.conf.sample?view=diff&rev=433003&r1=433002&r2=433003 ============================================================================== --- team/mjordan/trunk-astdb-cluster/configs/samples/pjsip.conf.sample (original) +++ team/mjordan/trunk-astdb-cluster/configs/samples/pjsip.conf.sample Mon Mar 16 21:18:35 2015 @@ -73,6 +73,10 @@ ; * Contains information about an outbound SIP registration ; * Phone Provisioning "phoneprov" ; * Contains information needed by res_phoneprov for autoprovisioning +; * Inbound publication handler "inbound-publication" +; * Defines a handler for received PUBLISH requests +; * Outbound publisher "outbound-publish" +; * Defines an entity to send PUBLISH requests to ; The following sections show example configurations for various scenarios. ; Most require a couple or more configuration types configured in concert. @@ -586,6 +590,54 @@ ;AUTH_ID=1000-auth ;automatically added by this module ;TRANSPORT_ID=transport-udp-nat ;automatically added by this module ;LABEL=1000 ;added by user + +;==============EXAMPLE PUBLISH CONFIGURATION================================ +; The production and handling of PUBLISH requests is broken into three different +; sections: "inbound-publication", "asterisk-publication", and "outbound-publish". +; An "inbound-publication" section defines how Asterisk will handle received +; PUBLISH requests from a particular endpoint; an "asterisk-publication" section +; specifically handles intra-Asterisk event types; and an "outbound-publish" +; section defines how Asterisk will transmit PUBLISH requests to a particular +; endpoint. + +; The following example demonstrates distributing device state to another +; Asterisk instance. In this case, this example assumes that there is an +; "endpoint" definition for the other Asterisk instance named "ast2". We'll +; provide a small stub for this endpoint, but otherwise leave it undefined. + +; [ast2] +; type=endpoint ; An endpoint instance for the "other" Asterisk instance +; + +; To handle inbound device state updates, we define both an "inbound-publication" +; section as well as an "asterisk-publication" section. The "inbound-publication" +; defines a handler for an event type of "asterisk-devicestate" that maps to +; the "asterisk-publication" section. Note that all event types for +; inbound PUBLISH handlers prefix the event type(s) that they handle with +; "event_". The value of the event type specifies the "asterisk-publication" +; section that will define how we handle these events. + +; [ast2] +; type=inbound-publication +; event_asterisk-devicestate=ast2 ; Handle "asterisk-devicestate" events +; ; using the "asterisk-publication" section +; ; "ast2" + +; [ast2] +; type=asterisk-publication +; device_state=yes ; Specify that we will handle intra-Asterisk +; ; device state updates + +; To PUBLISH our device state to endpoint "ast2", we define an "outbound-publish" +; section. This section specifies that we will PUBLISH events of type +; "asterisk-devicestate" to the SIP URI "sip:a...@my-awesome-service.com:5060". + +; [ast2] +; type=outbound-publish +; server_uri=sip:a...@my-awesome-service.com:5060 ; PUBLISH device states to this URI +; event=asterisk-devicestate ; The event type to publish + + ; MODULE PROVIDING BELOW SECTION(S): res_pjsip ;==========================ENDPOINT SECTION OPTIONS========================= @@ -930,3 +982,55 @@ ; Common variables include LINE, LINEKEYS, etc. ; See phoneprov.conf.sample for others. ;type= ; Must be of type phoneprov (default: "") + + + +; MODULE(S) PROVIDING BELOW SECTION(S): res_pjsip_pubsub, res_pjsip_outbound_publish, +; res_pjsip_publish_asterisk +;=============================PUBLISH OPTIONS================================= +; [inbound-publication] +; type= ; Must be of type inbound-publication (default: "") +; event_asterisk-devicestate= ; The asterisk-publication section that defines how + ; asterisk-devicestate PUBLISH requests are handled +; event_asterisk-mwi= ; The asterisk-publication section that defines how + ; asterisk-mwi PUBLISH requests are handled +; event_asterisk-db= ; The asterisk-publication section that defines how + ; asterisk-db PUBLISH requests are handled +; endpoint= ; Endpoints that we should accept PUBLISH requests + ; from (default: "") + +; [outbound-publish] +; type= ; Must be of type outbound-publish (default: "") +; expiration= ; Expiration time for PUBLISH requests in seconds + ; (default: 3600) +; outbound_auth= ; Authentication object to be used for outbound + ; publishes (default: "") +; outbound_proxy= ; SIP URI of the outbound proxy used to send publishes + ; (default: "") +; server_uri= ; SIP URI of the server and entity to publish to +; from_uri= ; SIP URI to use in the From header +; to_uri= ; SIP URI to use in the To header +; max_auth_attempts= ; Maximum number of authentication attempts before + ; stopping the publication (default: 5) +; event= ; Event type to publish (default: "") + +; [asterisk-publication] +; type= ; Must be of type asterisk-publication (default: "") +; devicestate_publish= ; Optional name of an outbound publish item that can be + ; used to publish a request for full device state information +; mailboxstate_publish= ; Optional name of an outbound publish item that can be used + ; to publish a request for full mailbox state information +; db_publish= ; Optional name of an outbound publish item that can be used + ; to publish a request for full AstDB shared family information +; device_state= ; Permit incoming "asterisk-devicestate" events. + ; (default: No) +; device_state_filter= ; Optional regular expression used to filter what devices + ; we accept events for. +; mailbox_state= ; Permit incoming "asterisk-mailboxstate" events. + ; (default: No) +; mailbox_state_filter= ; Optional regular expression used to filter what mailboxes + ; we accept events for. +; db_state= ; Permit incoming "asterisk-db" events. (default: No) +; db_state_filter= ; Optional regular expression used to filter what AstDB + ; shared families we accept events for. + Modified: team/mjordan/trunk-astdb-cluster/funcs/func_db.c URL: http://svnview.digium.com/svn/asterisk/team/mjordan/trunk-astdb-cluster/funcs/func_db.c?view=diff&rev=433003&r1=433002&r2=433003 ============================================================================== --- team/mjordan/trunk-astdb-cluster/funcs/func_db.c (original) +++ team/mjordan/trunk-astdb-cluster/funcs/func_db.c Mon Mar 16 21:18:35 2015 @@ -1,9 +1,9 @@ /* * Asterisk -- An open source telephony toolkit. * - * Copyright (C) 2005-2015, Russell Bryant <russ...@clemson.edu> - * - * func_db.c adapted from the old app_db.c, copyright by the following people + * Copyright (C) 2005-2015, Russell Bryant <russ...@clemson.edu> + * + * func_db.c adapted from the old app_db.c, copyright by the following people * Copyright (C) 2005, Mark Spencer <marks...@digium.com> * Copyright (C) 2003, Jefferson Noxon <j...@debian.org> * @@ -23,7 +23,6 @@ * \brief Functions for interaction with the Asterisk database * * \author Russell Bryant <russ...@clemson.edu> - * \author Matt Jordan <mjor...@digium.com> * * \ingroup functions */ @@ -53,30 +52,6 @@ <syntax argsep="/"> <parameter name="family" required="true" /> <parameter name="key" required="true" /> - </syntax> - <description> - <para>This function will read from or write a value to the Asterisk database. On a - read, this function returns the corresponding value from the database, or blank - if it does not exist. Reading a database value will also set the variable - DB_RESULT. If you wish to find out if an entry exists, use the DB_EXISTS - function.</para> - </description> - <see-also> - <ref type="application">DBdel</ref> - <ref type="function">DB_DELETE</ref> - <ref type="application">DBdeltree</ref> - <ref type="function">DB_EXISTS</ref> - </see-also> - </function> - <function name="DB_SHARED" language="en_US"> - <synopsis> - Create or delete a shared family in the Asterisk database. - </synopsis> - <syntax argsep="/"> - <parameter name="action" required="true"> - </parameter> - <parameter name="type"> - </parameter> </syntax> <description> <para>This function will read from or write a value to the Asterisk database. On a @@ -148,6 +123,120 @@ <ref type="application">DBdeltree</ref> </see-also> </function> + <function name="DB_SHARED" language="en_US"> + <synopsis> + W/O. Create or delete a shared family in the Asterisk database. + </synopsis> + <syntax> + <parameter name="action" required="true"> + <enumlist> + <enum name="put"> + <para>Create a shared family.</para> + </enum> + <enum name="delete"> + <para>Delete a shared family.</para> + </enum> + </enumlist> + </parameter> + <parameter name="type"> + <enumlist> + <enum name="global"> + <para> + Create a global shared family. + </para> + </enum> + <enum name="unique"> + <para> + Create a unique shared family. + </para> + </enum> + </enumlist> + </parameter> + </syntax> + <description> + <para> + This function will mark a family in the AstDB as shared + across a cluster of Asterisk servers. Updates to keys in + the shared family are distributed to the other Asterisk + servers in the cluster. + </para> + <para> + Families may be shared in one of two ways: 'global' or 'unique'. + </para> + <para> + A global shared family shares its keys/values across + Asterisk servers as a shared namespace. Any server that + changes a value in a global shared family will have that + same key be updated in the shared families of other servers. + </para> + <para> + A unique shared family shares its keys/values across + Asterisk servers, but the keys/values are stored in a + family matching the originating Asterisk server's + <replaceable>EID</replaceable>. Other Asterisk servers must + also have a shared family matching the originating Asterisk + server's shared family. + </para> + <note> + <para>The mechanism of sharing the information to other + Asterisk servers is independent of this function.</para> + </note> + <example title="Create global shared family"> + ; Share AstDB family 'global_shared' globally across servers + same => n,Set(DB_SHARED(put,global)=global_shared) + + ; Update to key/value 'foo/bar' will be distributed to + ; other Asterisk servers that have also shared the + ; 'global_shared' family + same => n,Set(DB(global_shared/foo)=bar) + </example> + <example title="Create unique shared family"> + ; Share AstDB family 'unique_shared' uniquely across servers + same => n,Set(DB_SHARED(put,unique)=unique_shared) + + ; Update to key/value 'foo/bar' will be distributed to + ; other Asterisk servers that have also shared the + ; 'unique_shared' family. Assuming this server's EID is + ; 11:11:11:11:11:11, the key will be stored in + ; '11:11:11:11:11:11/unique_shared/foo' with value 'bar' + ; on those servers. + same => n,Set(DB(unique_shared/foo)=bar) + </example> + <example title="Delete global shared family"> + ; Share AstDB family 'global_shared' globally across servers + same => n,Set(DB_SHARED(put,global)=global_shared) + + ; This update will be shared + same => n,Set(DB(global_shared/foo)=bar) + + ; Remove the shared status of 'global_shared' + same => n,Set(DB_SHARED(delete)=global_shared) + + ; This update will not be shared + same => n,Set(DB(global_shared/foo)=unbar) + </example> + </description> + <see-also> + <ref type="function">DB</ref> + <ref type="function">DB_SHARED_EXISTS</ref> + </see-also> + </function> + <function name="DB_SHARED_EXISTS" language="en_US"> + <synopsis> + Check to see if a family is shared. + </synopsis> + <syntax> + <parameter name="family" required="true" /> + </syntax> + <description> + <para>This function will check to see if a family is shared between + Asteris instances. If so, the function will return <literal>1</literal>. + If not, it will return <literal>0</literal>.</para> + </description> + <see-also> + <ref type="function">DB_SHARED</ref> + </see-also> + </function> ***/ static int function_db_read(struct ast_channel *chan, const char *cmd, @@ -386,7 +475,6 @@ } else { ast_copy_string(buf, "0", len); } - pbx_builtin_setvar_helper(chan, "DB_RESULT", buf); return 0; } @@ -425,9 +513,9 @@ if (!strcasecmp(args.action, "put")) { if (ast_strlen_zero(args.type) || !strcasecmp(args.type, "global")) { - share_type = SHARED_DB_TYPE_GLOBAL; + share_type = DB_SHARE_TYPE_GLOBAL; } else if (!strcasecmp(args.type, "unique")) { - share_type = SHARED_DB_TYPE_UNIQUE; + share_type = DB_SHARE_TYPE_UNIQUE; } else { ast_log(LOG_WARNING, "DB_SHARED: Unknown 'type' %s\n", args.type); return -1; @@ -438,7 +526,7 @@ ast_debug(2, "Failed to create shared family '%s'\n", value); } else { ast_verb(4, "Created %s shared family '%s'\n", - share_type == SHARED_DB_TYPE_GLOBAL ? "GLOBAL" : "UNIQUE", + share_type == DB_SHARE_TYPE_GLOBAL ? "GLOBAL" : "UNIQUE", value); } } else if (!strcasecmp(args.action, "delete")) { Modified: team/mjordan/trunk-astdb-cluster/include/asterisk/astdb.h URL: http://svnview.digium.com/svn/asterisk/team/mjordan/trunk-astdb-cluster/include/asterisk/astdb.h?view=diff&rev=433003&r1=433002&r2=433003 ============================================================================== --- team/mjordan/trunk-astdb-cluster/include/asterisk/astdb.h (original) +++ team/mjordan/trunk-astdb-cluster/include/asterisk/astdb.h Mon Mar 16 21:18:35 2015 @@ -35,9 +35,9 @@ enum ast_db_shared_type { /* Items in the shared family are common across all Asterisk instances */ - SHARED_DB_TYPE_GLOBAL = 0, + DB_SHARE_TYPE_GLOBAL = 0, /*! Items in the shared family are made unique across all Asterisk instances */ - SHARED_DB_TYPE_UNIQUE, + DB_SHARE_TYPE_UNIQUE, }; /*! \brief An actual entry in the AstDB */ @@ -148,7 +148,6 @@ */ void ast_db_refresh_shared(void); - /*! * \since 14.0.0 * \brief Add a new shared family Modified: team/mjordan/trunk-astdb-cluster/include/asterisk/event_defs.h URL: http://svnview.digium.com/svn/asterisk/team/mjordan/trunk-astdb-cluster/include/asterisk/event_defs.h?view=diff&rev=433003&r1=433002&r2=433003 ============================================================================== --- team/mjordan/trunk-astdb-cluster/include/asterisk/event_defs.h (original) +++ team/mjordan/trunk-astdb-cluster/include/asterisk/event_defs.h Mon Mar 16 21:18:35 2015 @@ -58,10 +58,8 @@ AST_EVENT_ACL_CHANGE = 0x0b, /*! Send out a ping for debugging distributed events */ AST_EVENT_PING = 0x0c, - /*! Send out a shared database event */ - AST_EVENT_DB_SHARED = 0x0d, /*! Number of event types. This should be the last event type + 1 */ - AST_EVENT_TOTAL = 0x0e, + AST_EVENT_TOTAL = 0x0d, }; /*! \brief Event Information Element types */ @@ -304,38 +302,8 @@ * Payload type: UINT */ AST_EVENT_IE_CACHABLE = 0x003d, - /*! - * \brief AstDB Family - * Used by: AST_EVENT_DB_SHARED - * Payload type: STR - */ - AST_EVENT_IE_DB_FAMILY = 0x003e, - /*! - * \brief AstDB action to take - * Used by: AST_EVENT_DB_SHARED - * Payload type: STR - */ - AST_EVENT_ID_DB_ACTION_TYPE = 0x003f, - /*! - * \brief AstDB share type - * Used by: AST_EVENT_DB_SHARED - * Payload type: UINT - */ - AST_EVENT_IE_DB_SHARE_TYPE = 0x0040, - /*! - * \brief AstDB key - * Used by: AST_EVENT_DB_SHARED - * Payload type: STR - */ - AST_EVENT_IE_DB_KEY = 0x0041, - /*! - * \brief AstDB value - * Used by: AST_EVENT_DB_SHARED - * Payload type: STR - */ - AST_EVENT_IE_DB_VALUE = 0x0042, /*! \brief Must be the last IE value +1 */ - AST_EVENT_IE_TOTAL = 0x0043, + AST_EVENT_IE_TOTAL = 0x003e, }; /*! Modified: team/mjordan/trunk-astdb-cluster/main/db.c URL: http://svnview.digium.com/svn/asterisk/team/mjordan/trunk-astdb-cluster/main/db.c?view=diff&rev=433003&r1=433002&r2=433003 ============================================================================== --- team/mjordan/trunk-astdb-cluster/main/db.c (original) +++ team/mjordan/trunk-astdb-cluster/main/db.c Mon Mar 16 21:18:35 2015 @@ -51,7 +51,6 @@ #include "asterisk/cli.h" #include "asterisk/utils.h" #include "asterisk/manager.h" -#include "asterisk/event.h" /*** DOCUMENTATION <manager name="DBGet" language="en_US"> @@ -113,7 +112,11 @@ static int doexit; static int dosync; -/*! \brief A container of families to share across Asterisk instances */ +/*! + * \brief A container of families to share across Asterisk instances. + * \note Entries in this container should be treated as immutable. The container + * needs locking; the entries do not. + */ static struct ao2_container *shared_families; /*! \brief The Stasis topic for shared families */ @@ -227,9 +230,7 @@ return entry; } -/*! \internal - * \brief AO2 destructor for \c ast_db_shared_family - */ +/*! \internal \brief AO2 destructor for \c ast_db_shared_family */ static void shared_db_family_dtor(void *obj) { struct ast_db_shared_family *family = obj; @@ -425,7 +426,7 @@ ao2_link_flags(shared_families, shared_family, OBJ_NOLOCK); db_put_common(SHARED_FAMILY, shared_family->name, - share_type == SHARED_DB_TYPE_UNIQUE ? "UNIQUE" : "GLOBAL", 0); + share_type == DB_SHARE_TYPE_UNIQUE ? "UNIQUE" : "GLOBAL", 0); ao2_ref(shared_family, -1); @@ -448,13 +449,24 @@ return res; } +/*! + * \internal + * \brief Update remote instances that a shared family key/value was updated + * + * \param family The AstDB family + * \param key The AstDB key + * \param value The AstDB value + * + * \retval 0 entry was processed successfully + * \retval -1 error + */ static int db_entry_put_shared(const char *family, const char *key, const char *value) { struct ast_db_shared_family *shared_family; struct ast_db_shared_family *clone; /* See if we are shared */ - shared_family = ao2_find(shared_families, family, OBJ_SEARCH_PARTIAL_KEY); + shared_family = ao2_find(shared_families, family, OBJ_SEARCH_KEY); if (!shared_family) { return 0; } @@ -480,13 +492,24 @@ return 0; } +/*! + * \internal + * \brief Update remote instances that a shared family key/value was deleted + * + * \param family The AstDB family + * \param key The AstDB key + * \param value The AstDB value + * + * \retval 0 entry was processed successfully + * \retval -1 error + */ static int db_entry_del_shared(const char *family, const char *key) { struct ast_db_shared_family *shared_family; struct ast_db_shared_family *clone; /* See if we are shared */ - shared_family = ao2_find(shared_families, family, OBJ_SEARCH_PARTIAL_KEY); + shared_family = ao2_find(shared_families, family, OBJ_SEARCH_KEY); if (!shared_family) { return 0; } @@ -542,6 +565,18 @@ return res; } +/*! + * \internal + * \brief Common routine to update an entry in the AstDB + * + * \param family The AstDB family + * \param key The AstDB key + * \param value The AstDB value + * \param share If non-zero, try to inform other instances that the key was updated + * + * \retval 0 success + * \retval -1 error + */ static int db_put_common(const char *family, const char *key, const char *value, int share) { char fullkey[MAX_DB_FIELD]; @@ -652,6 +687,17 @@ return db_get_common(family, key, out, -1); } +/*! + * \internal + * \brief Common routine to delete an entry in the AstDB + * + * \param family The AstDB family + * \param key The AstDB key + * \param share If non-zero, try to inform other instances that the key was deleted + * + * \retval 0 success + * \retval -1 error + */ static int db_del_common(const char *family, const char *key, int share) { char fullkey[MAX_DB_FIELD]; @@ -680,7 +726,7 @@ } ast_mutex_unlock(&dblock); - return res; + return res; } int ast_db_del(const char *family, const char *key) @@ -688,6 +734,17 @@ return db_del_common(family, key, 1); } +/*! + * \internal + * \brief Common routine to delete an entire tree in the AstDB + * + * \param family The AstDB family + * \param key The AstDB key. May be NULL. + * \param share If non-zero, try to inform other instances that the key was deleted + * + * \retval 0 success + * \retval -1 error + */ static int db_deltree_common(const char *family, const char *keytree, int share) { sqlite3_stmt *stmt = deltree_stmt; @@ -723,7 +780,7 @@ } ast_mutex_unlock(&dblock); - return res; + return res; } int ast_db_deltree(const char *family, const char *keytree) @@ -897,9 +954,9 @@ } if (!strcasecmp(a->argv[4], "unique")) { - share_type = SHARED_DB_TYPE_UNIQUE; + share_type = DB_SHARE_TYPE_UNIQUE; } else if (!strcasecmp(a->argv[4], "global")) { - share_type = SHARED_DB_TYPE_GLOBAL; + share_type = DB_SHARE_TYPE_GLOBAL; } else { ast_cli(a->fd, "Unknown share type: '%s'\n", a->argv[4]); return CLI_SUCCESS; @@ -975,6 +1032,7 @@ return CLI_SUCCESS; } +/*! \internal \brief Helper for CLI commands that print the AstDB */ static int print_database_show(struct ast_cli_args *a, sqlite3_stmt *stmt) { int counter = 0; @@ -1005,7 +1063,7 @@ ++counter; ast_cli(a->fd, "%-50s: %-25s %s\n", key_s, value_s, - shared_family ? (shared_family->share_type == SHARED_DB_TYPE_UNIQUE ? "(U)" : "(G)") : ""); + shared_family ? (shared_family->share_type == DB_SHARE_TYPE_UNIQUE ? "(U)" : "(G)") : ""); ao2_cleanup(shared_family); ast_free(family_s); @@ -1324,7 +1382,8 @@ return NULL; } -int ast_db_publish_shared_message(struct stasis_message_type *type, struct ast_db_shared_family *shared_family, struct ast_eid *eid) +int ast_db_publish_shared_message(struct stasis_message_type *type, + struct ast_db_shared_family *shared_family, struct ast_eid *eid) { struct stasis_message *message; @@ -1371,18 +1430,17 @@ ao2_ref(clone, -1); ao2_ref(shared_family, -1); } - ao2_iterator_destroy(&it_shared_families); -} - -static struct ast_event *db_del_shared_type_to_event(struct stasis_message *message) -{ - return NULL; + ao2_iterator_destroy(&it_shared_families); } static struct ast_json *db_entries_to_json(struct ast_db_entry *entry) { struct ast_json *json; struct ast_db_entry *cur; + + if (!entry) { + return ast_json_null(); + } json = ast_json_array_create(); if (!json) { @@ -1414,17 +1472,27 @@ { struct stasis_message_type *type = stasis_message_type(message); struct ast_db_shared_family *shared_family; + struct ast_json *entries; + + if (type != ast_db_put_shared_type() && type != ast_db_del_shared_type()) { + return NULL; + } shared_family = stasis_message_data(message); if (!shared_family) { + return NULL; + } + + entries = db_entries_to_json(shared_family->entries); + if (!entries) { return NULL; } return ast_json_pack("{s: s, s: s, s: s, s: o}", "verb", type == ast_db_put_shared_type() ? "put" : "delete", "family", shared_family->name, - "share_type", shared_family->share_type == SHARED_DB_TYPE_UNIQUE ? "unique" : "global", - "entries", shared_family->entries ? db_entries_to_json(shared_family->entries) : ast_json_null()); + "share_type", shared_family->share_type == DB_SHARE_TYPE_UNIQUE ? "unique" : "global", + "entries", entries); } struct stasis_topic *ast_db_cluster_topic(void) @@ -1468,7 +1536,7 @@ } ao2_ref(shared_check, -1); - if (shared_family->share_type == SHARED_DB_TYPE_UNIQUE) { + if (shared_family->share_type == DB_SHARE_TYPE_UNIQUE) { char eid_workspace[20]; /* Length is family + '/' + EID length (20) + 1 */ @@ -1527,7 +1595,9 @@ ast_manager_unregister("DBDel"); ast_manager_unregister("DBDelTree"); - ao2_cleanup(db_cluster_topic); + ao2_ref(message_router, -1); + message_router = NULL; + ao2_ref(db_cluster_topic, -1); db_cluster_topic = NULL; STASIS_MESSAGE_TYPE_CLEANUP(ast_db_put_shared_type); STASIS_MESSAGE_TYPE_CLEANUP(ast_db_del_shared_type); @@ -1572,9 +1642,9 @@ } if (!strcasecmp(cur->data, "unique")) { - share_type = SHARED_DB_TYPE_UNIQUE; + share_type = DB_SHARE_TYPE_UNIQUE; } else if (!strcasecmp(cur->data, "global")) { - share_type = SHARED_DB_TYPE_GLOBAL; + share_type = DB_SHARE_TYPE_GLOBAL; } else { continue; } @@ -1596,8 +1666,7 @@ db_cluster_topic = stasis_topic_create("ast_db_cluster_topic"); if (!db_cluster_topic) { - ao2_ref(shared_families, -1); - return -1; + goto error_cleanup; } STASIS_MESSAGE_TYPE_INIT(ast_db_put_shared_type); @@ -1605,9 +1674,7 @@ message_router = stasis_message_router_create_pool(ast_db_cluster_topic()); if (!message_router) { - ao2_ref(db_cluster_topic, -1); - ao2_ref(shared_families, -1); - return -1; + goto error_cleanup; } stasis_message_router_add(message_router, ast_db_put_shared_type(), db_put_shared_msg_cb, NULL); @@ -1615,18 +1682,14 @@ db_del_shared_msg_cb, NULL); if (db_init()) { - ao2_ref(db_cluster_topic, -1); - ao2_ref(shared_families, -1); - return -1; + goto error_cleanup; } restore_shared_families(); ast_cond_init(&dbcond, NULL); if (ast_pthread_create_background(&syncthread, NULL, db_sync_thread, NULL)) { - ao2_ref(db_cluster_topic, -1); - ao2_ref(shared_families, -1); - return -1; + goto error_cleanup; } ast_register_atexit(astdb_atexit); @@ -1636,4 +1699,12 @@ ast_manager_register_xml_core("DBDel", EVENT_FLAG_SYSTEM, manager_dbdel); ast_manager_register_xml_core("DBDelTree", EVENT_FLAG_SYSTEM, manager_dbdeltree); return 0; -} + +error_cleanup: + ao2_cleanup(message_router); + ao2_cleanup(db_cluster_topic); + STASIS_MESSAGE_TYPE_CLEANUP(ast_db_put_shared_type); + STASIS_MESSAGE_TYPE_CLEANUP(ast_db_del_shared_type); + ao2_cleanup(shared_families); + return -1; +} Modified: team/mjordan/trunk-astdb-cluster/res/res_pjsip_publish_asterisk.c URL: http://svnview.digium.com/svn/asterisk/team/mjordan/trunk-astdb-cluster/res/res_pjsip_publish_asterisk.c?view=diff&rev=433003&r1=433002&r2=433003 ============================================================================== --- team/mjordan/trunk-astdb-cluster/res/res_pjsip_publish_asterisk.c (original) +++ team/mjordan/trunk-astdb-cluster/res/res_pjsip_publish_asterisk.c Mon Mar 16 21:18:35 2015 @@ -363,7 +363,7 @@ if (!eid || ast_eid_cmp(&ast_eid_default, eid)) { /* If the event is aggregate, unknown, or didn't originate from this * server, don't send it out. */ - return; + return; } shared_family = stasis_message_data(msg); @@ -798,9 +798,9 @@ ast_sorcery_object_get_id(config)); return -1; } else if (!strcasecmp(str_share_type, "global")) { - share_type = SHARED_DB_TYPE_GLOBAL; + share_type = DB_SHARE_TYPE_GLOBAL; } else if (!strcasecmp(str_share_type, "unique")) { - share_type = SHARED_DB_TYPE_UNIQUE; + share_type = DB_SHARE_TYPE_UNIQUE; } else { ast_debug(1, "Received bad AstDB state event for resource '%s': unknown verb '%s'\n", ast_sorcery_object_get_id(config), str_share_type); @@ -1298,7 +1298,7 @@ for (i = 0; i < ARRAY_LEN(event_publisher_handlers); i++) { if (ast_sip_register_event_publisher_handler(event_publisher_handlers[i])) { ast_log(LOG_WARNING, "Unable to register event publisher handler %s\n", - event_publisher_handlers[i]->event_name); + event_publisher_handlers[i]->event_name); for (j = 0; j < ARRAY_LEN(&publish_handlers); j++) { ast_sip_unregister_publish_handler(publish_handlers[j]); } Modified: team/mjordan/trunk-astdb-cluster/tests/test_db.c URL: http://svnview.digium.com/svn/asterisk/team/mjordan/trunk-astdb-cluster/tests/test_db.c?view=diff&rev=433003&r1=433002&r2=433003 ============================================================================== --- team/mjordan/trunk-astdb-cluster/tests/test_db.c (original) +++ team/mjordan/trunk-astdb-cluster/tests/test_db.c Mon Mar 16 21:18:35 2015 @@ -4,7 +4,6 @@ * Copyright (C) 2011-2015, Digium, Inc. * * Terry Wilson <twil...@digium.com> - * Matt Jordan <mjor...@digium.com> * * See http://www.asterisk.org for more information about * the Asterisk project. Please do not directly contact @@ -22,7 +21,6 @@ * \brief AstDB Unit Tests * * \author Terry Wilson <twil...@digium.com> - * \author Matt Jordan <mjor...@digium.com> * */ @@ -386,6 +384,16 @@ return res; } +/*! + * \brief Test the AstDB for the given family, key, value tuple + * + * As annoying as it is, it's actually really hard to synchronize on when the + * AstDB updates itself from the received publication of a shared family value. + * This is because while we can synchronize on the delivery to a topic, we can't + * synchronize that the AstDB handler's for that topic has written the value out. + * Hence, we use this loop - if we don't get a value written within 1000 usec, + * something is definitely wrong and we should just fail the unit test. + */ #define TEST_FOR_VALUE(family, key, value) do { \ int i; \ for (i = 0; i < 10; i++) { \ @@ -416,22 +424,22 @@ break; } - res = ast_db_put_shared(GLOBAL_SHARED_FAMILY, SHARED_DB_TYPE_GLOBAL); + res = ast_db_put_shared(GLOBAL_SHARED_FAMILY, DB_SHARE_TYPE_GLOBAL); ast_test_validate(test, res == 0, "Creating global shared area"); res = ast_db_is_shared(GLOBAL_SHARED_FAMILY); ast_test_validate(test, res == 1, "Test existance of global shared area"); - res = ast_db_put_shared(GLOBAL_SHARED_FAMILY, SHARED_DB_TYPE_GLOBAL); + res = ast_db_put_shared(GLOBAL_SHARED_FAMILY, DB_SHARE_TYPE_GLOBAL); ast_test_validate(test, res != 0, "Creating duplicate global shared area"); - res = ast_db_put_shared(GLOBAL_SHARED_FAMILY, SHARED_DB_TYPE_UNIQUE); + res = ast_db_put_shared(GLOBAL_SHARED_FAMILY, DB_SHARE_TYPE_UNIQUE); ast_test_validate(test, res != 0, "Creating duplicate unique of global shared area"); - res = ast_db_put_shared(UNIQUE_SHARED_FAMILY, SHARED_DB_TYPE_UNIQUE); + res = ast_db_put_shared(UNIQUE_SHARED_FAMILY, DB_SHARE_TYPE_UNIQUE); ast_test_validate(test, res == 0, "Creating unique shared area"); res = ast_db_is_shared(UNIQUE_SHARED_FAMILY); ast_test_validate(test, res == 1, "Test existance of unique shared area"); - res = ast_db_put_shared(UNIQUE_SHARED_FAMILY, SHARED_DB_TYPE_UNIQUE); + res = ast_db_put_shared(UNIQUE_SHARED_FAMILY, DB_SHARE_TYPE_UNIQUE); ast_test_validate(test, res != 0, "Creating duplicate unique shared area"); - res = ast_db_put_shared(UNIQUE_SHARED_FAMILY, SHARED_DB_TYPE_GLOBAL); + res = ast_db_put_shared(UNIQUE_SHARED_FAMILY, DB_SHARE_TYPE_GLOBAL); ast_test_validate(test, res != 0, "Creating duplicate global of unique shared area"); ast_db_del_shared(GLOBAL_SHARED_FAMILY); @@ -456,7 +464,7 @@ break; } - res = ast_db_put_shared(GLOBAL_SHARED_FAMILY, SHARED_DB_TYPE_GLOBAL); + res = ast_db_put_shared(GLOBAL_SHARED_FAMILY, DB_SHARE_TYPE_GLOBAL); ast_test_validate(test, res == 0, "Creating global shared area"); res = ast_db_del_shared(GLOBAL_SHARED_FAMILY); ast_test_validate(test, res == 0, "Deletion of global shared area"); @@ -465,7 +473,7 @@ res = ast_db_del_shared(GLOBAL_SHARED_FAMILY); ast_test_validate(test, res != 0, "Allowed duplicate deletion of global shared area"); - res = ast_db_put_shared(UNIQUE_SHARED_FAMILY, SHARED_DB_TYPE_UNIQUE); + res = ast_db_put_shared(UNIQUE_SHARED_FAMILY, DB_SHARE_TYPE_UNIQUE); ast_test_validate(test, res == 0, "Creating unique shared area"); res = ast_db_del_shared(UNIQUE_SHARED_FAMILY); ast_test_validate(test, res == 0, "Deletion of unique shared area"); @@ -507,7 +515,7 @@ /* Create a key that is not published due to not being shared yet */ res = ast_db_put(UNIQUE_SHARED_FAMILY, "foo", "bar"); ast_test_validate(test, res == 0, "Creation of non-published test key"); - res = ast_db_put_shared(UNIQUE_SHARED_FAMILY, SHARED_DB_TYPE_UNIQUE); + res = ast_db_put_shared(UNIQUE_SHARED_FAMILY, DB_SHARE_TYPE_UNIQUE); ast_test_validate(test, res == 0, "Creation of unique shared area"); /* Publish a new key */ @@ -562,7 +570,7 @@ /* Create a key that is not published due to not being shared yet */ res = ast_db_put(GLOBAL_SHARED_FAMILY, "foo", "bar"); ast_test_validate(test, res == 0, "Creation of non-published test key"); - res = ast_db_put_shared(GLOBAL_SHARED_FAMILY, SHARED_DB_TYPE_GLOBAL); + res = ast_db_put_shared(GLOBAL_SHARED_FAMILY, DB_SHARE_TYPE_GLOBAL); ast_test_validate(test, res == 0, "Creation of global shared area"); /* Publish a new key */ @@ -584,7 +592,7 @@ ast_db_deltree(GLOBAL_SHARED_FAMILY, ""); ast_db_del_shared(GLOBAL_SHARED_FAMILY); - return AST_TEST_PASS; + return AST_TEST_PASS; } AST_TEST_DEFINE(test_ast_db_put_shared_unique_update) @@ -613,12 +621,12 @@ ast_test_status_update(test, "Verifying unique shared area can be updated\n"); - shared_family = ast_db_shared_family_alloc(UNIQUE_SHARED_FAMILY, SHARED_DB_TYPE_UNIQUE); + shared_family = ast_db_shared_family_alloc(UNIQUE_SHARED_FAMILY, DB_SHARE_TYPE_UNIQUE); ast_test_validate(test, shared_family != NULL); shared_family->entries = ast_db_entry_create("foo", "bar"); ast_test_validate(test, shared_family->entries != NULL); - res = ast_db_put_shared(UNIQUE_SHARED_FAMILY, SHARED_DB_TYPE_UNIQUE); + res = ast_db_put_shared(UNIQUE_SHARED_FAMILY, DB_SHARE_TYPE_UNIQUE); ast_test_validate(test, res == 0, "Creation of unique shared area"); ast_db_publish_shared_message(ast_db_put_shared_type(), shared_family, &eid); @@ -634,7 +642,7 @@ ao2_ref(shared_family, -1); ast_test_status_update(test, "Verifying unique non-shared area is not updated\n"); - shared_family = ast_db_shared_family_alloc(UNIQUE_SHARED_FAMILY, SHARED_DB_TYPE_UNIQUE); + shared_family = ast_db_shared_family_alloc(UNIQUE_SHARED_FAMILY, DB_SHARE_TYPE_UNIQUE); ast_test_validate(test, shared_family != NULL); shared_family->entries = ast_db_entry_create("foo", "yackity"); ast_test_validate(test, shared_family->entries != NULL); @@ -675,12 +683,12 @@ ast_test_status_update(test, "Verifying global shared area can be updated\n"); - shared_family = ast_db_shared_family_alloc(GLOBAL_SHARED_FAMILY, SHARED_DB_TYPE_GLOBAL); + shared_family = ast_db_shared_family_alloc(GLOBAL_SHARED_FAMILY, DB_SHARE_TYPE_GLOBAL); ast_test_validate(test, shared_family != NULL); shared_family->entries = ast_db_entry_create("foo", "bar"); ast_test_validate(test, shared_family->entries != NULL); - res = ast_db_put_shared(GLOBAL_SHARED_FAMILY, SHARED_DB_TYPE_GLOBAL); + res = ast_db_put_shared(GLOBAL_SHARED_FAMILY, DB_SHARE_TYPE_GLOBAL); ast_test_validate(test, res == 0, "Creation of global shared area"); ast_db_publish_shared_message(ast_db_put_shared_type(), shared_family, &eid); @@ -696,7 +704,7 @@ ao2_ref(shared_family, -1); ast_test_status_update(test, "Verifying global non-shared area is not updated\n"); [... 19 lines stripped ...] -- _____________________________________________________________________ -- Bandwidth and Colocation Provided by http://www.api-digital.com -- svn-commits mailing list To UNSUBSCRIBE or update options visit: http://lists.digium.com/mailman/listinfo/svn-commits