[svn-commits] mjordan: branch mjordan/trunk-astdb-cluster r433003 - in /team/mjordan/trunk-...

SVN commits to the Digium repositories svn-commits at lists.digium.com
Mon Mar 16 21:18:38 CDT 2015


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:ast2 at my-awesome-service.com:5060".
+
+; [ast2]
+; type=outbound-publish
+; server_uri=sip:ast2 at 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 <russelb at clemson.edu> 
- *
- * func_db.c adapted from the old app_db.c, copyright by the following people 
+ * Copyright (C) 2005-2015, Russell Bryant <russelb at clemson.edu>
+ *
+ * func_db.c adapted from the old app_db.c, copyright by the following people
  * Copyright (C) 2005, Mark Spencer <markster at digium.com>
  * Copyright (C) 2003, Jefferson Noxon <jeff at debian.org>
  *
@@ -23,7 +23,6 @@
  * \brief Functions for interaction with the Asterisk database
  *
  * \author Russell Bryant <russelb at clemson.edu>
- * \author Matt Jordan <mjordan at 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 <twilson at digium.com>
- * Matt Jordan <mjordan at 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 <twilson at digium.com>
- * \author Matt Jordan <mjordan at 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 ...]



More information about the svn-commits mailing list