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

Reply via email to