<!-- Module User's Guide -->

<chapter>

	<title>&adminguide;</title>

	<section id="overview" xreflabel="Overview">
	<title>Overview</title>
	<para>
		This modules implements a dispatcher for destination addresses. It
		computes hashes over various parts of the request and selects an
		address from a destination set. The selected address may then either
		overwrite the R-URI of a SIP request or be used as an outbound proxy.
	</para>
	<para>
		The module can be used as a stateless load balancer, having no
		guarantee of fair distribution.
	</para>
	<para>
		For the distribution algorithm, the module allows the definition of
		weights for the destination. This is useful in order to get a different
		ratio of traffic between destinations.
	</para>
	<para>
		Starting with version 2.1, the dispatcher module keeps its destination sets 
		into different partitions. Each partition is described by its own
		"db_url", "table_name", "dst_avp", "grp_avp", "cnt_avp", "sock_avp",
                "attr_avp", "blacklists", "ping_from", "ping_method" and
                "persistent_state" set of attributes. Setting any of these
                module parameters will only alter the "default" partition's properties.
	</para>
	<para>
		In order to create a new partition, the <xref linkend="param_partition"/>
		parameter can be used.  If none of the 8 partition specific parameters
		are defined for the "default" partition, then this partition will not
		be created.  Once the "default" partition is created, any undefined
		parameter from other partitions will inherit the value of the
		corresponding parameter of the "default" partition.  If there is no
		"default" partition, the default value specified in the parameter's
		description will be used.  Finally, note that each dispatcher table
		specified using the "table_name" partition attribute requires a
		corresponding "version" table record within the partition's database,
		specified through "db_url".
	</para>
	<para>
		Since version 2.1, the "flags" parameter has been moved to 
		ds_select_dst() and ds_select_domain() along with "force_dst" and
		"use_default" flags.
	</para>
	</section>
	<section id="dependencies" xreflabel="Dependencies">
	<title>Dependencies</title>
	<section>
		<title>&osips; modules</title>
		<para>
		The following modules must be loaded before this module:
			<itemizedlist>
			<listitem>
			<para>
				<emphasis>TM - only if active recovery of failed hosts is required</emphasis>.
			</para>
			</listitem>
			<listitem>
			<para>
				<emphasis>clusterer</emphasis> - only if "cluster_id"
				option is enabled.
			</para>
			</listitem>
			<listitem>
			<para>
				<emphasis>database</emphasis> - one of the DB SQL modules
			</para>
			</listitem>
			<listitem>
			<para>
				<emphasis>freeswitch - only if "fetch_freeswitch_stats" is enabled.</emphasis>.
			</para>
			</listitem>
			</itemizedlist>
		</para>
	</section>
	<section>
		<title>External libraries or applications</title>
		<para>
		The following libraries or applications must be installed before
		running &osips; with this module:
			<itemizedlist>
			<listitem>
			<para>
				<emphasis>none</emphasis>.
			</para>
			</listitem>
			</itemizedlist>
		</para>
	</section>
	</section>

	<section id="exported_parameters" xreflabel="Exported Parameters">
	<title>Exported Parameters</title>
	<section id="param_db_url" xreflabel="db_url">
		<title><varname>db_url</varname> (string)</title>
		<para>
		The default DB connection of the module, overriding the global
		'db_default_url' setting.  Once specified, partitions which are missing
		the 'db_url' property will inherit their URL from this value.
		</para>
		<para>
		<emphasis>
			Default value is <quote>NULL</quote>.
		</emphasis>
		</para>
		<example>
		<title>Setting the default database URL for dispatcher</title>
<programlisting format="linespecific">
...
modparam("dispatcher", "db_url", "mysql://user:passwb@localhost/database")
...
</programlisting>
		</example>
	</section>

	<section id="param_attrs_avp" xreflabel="attrs_avp">
		<title><varname>attrs_avp</varname> (str)</title>
		<para>
		The name of the avp to contain the attributes string of the current
		destination. When a destination is selected, automatically, this AVP
		will provide the attributes string - this is an opaque string (from
		OpenSIPS point of view) : it is loaded from destination definition (
		via DB) and blindly provided in the script.
		Setting this parameter will only change the default partition's
		attrs_avp. Use the partition parameter to create and alter
		other partitions.
		</para>
		<note>
		</note>
		<para>
		<emphasis>
			Default value is <quote>null</quote> - don't provide ATTRIBUTEs.
		</emphasis>
		</para>
		<example>
		<title>Set the 'default' partition's <quote>attrs_avp</quote> parameter</title>
<programlisting format="linespecific">
...
modparam("dispatcher", "attrs_avp", "$avp(272)")
...
</programlisting>
		</example>
	</section>

	<section id="param_script_attrs_avp" xreflabel="script_attrs_avp">
		<title><varname>script_attrs_avp</varname> (str)</title>
		<para>
		Name of the avp to contain the script attributes string of the current
		destination. When a destination is selected, automatically, this AVP
		will provide the attributes string - this is an opaque string (from
		OpenSIPS point of view) : it is provided via the ds_push_script_attrs
		MI or SCRIPT function.
		</para>
		<note>
		</note>
		<para>
		<emphasis>
			Default value is <quote>null</quote> - don't provide SCRIPT ATTRIBUTEs.
		</emphasis>
		</para>
		<example>
		<title>Set the 'default' partition's <quote>script_attrs_avp</quote> parameter</title>
<programlisting format="linespecific">
...
modparam("dispatcher", "attrs_avp", "$avp(script_attrs)")
...
</programlisting>
		</example>
	</section>

	<section id="algo_route_param" xreflabel="algo_route">
		<title><varname>algo_route</varname> (str)</title>
		<para>
		Name of the route to be called when using algo 10.
		The route will get as param the dst_uri, attrs and script_attrs for the
		dispatcher entry that currently needs to be evaluated ( available via 
		$param(1), $param(2) and $param(3) or via $param(dst_uri), $param(attrs) and $param(script_attrs) when the route gets called ).
		The return value of the route is considered by the dispatcher module to
		be the current weight of the dispatcher entry, and when using the 10
		algo, the dispatcher entries are sorted in ascending weight order.

		If the returned value from the algo route is negative, the current dispatcher entry will be automatically skipped from usage
		</para>
		<para>
		<emphasis>
			Default value is <quote>null</quote> - disabled.
		</emphasis>
		</para>
		<example>
		<title>Use algo_route for hashing:</title>
<programlisting format="linespecific">
...
modparam("dispatcher", "algo_route", "my_dispatcher_logic)")
...
route[my_dispatcher_logic] {
        $var(curent_score) = 0;
        xlog("DISPATCHER - Running logic for $param(dst_uri) with attrs $param(attrs) and script attrs $param(script_attrs) \n");

	# decide to penalize current dispatcher entry, based on your logic
	if (my_condition_here)
		$var(current_score) = $var(current_score) + 10;

        return $var(rc);
}

</programlisting>
		</example>
	</section>


	<section id="param_hash_pvar" xreflabel="hash_pvar">
		<title><varname>hash_pvar</varname> (str)</title>
		<para>
		String with PVs used for the hashing algorithm 7.
		</para>
		<note>
		<para>
		You must set this parameter if you want do hashing over custom message
		parts.
		</para>
		</note>
		<para>
		<emphasis>
			Default value is <quote>null</quote> - disabled.
		</emphasis>
		</para>
		<example>
		<title>Use $avp(273) for hashing:</title>
<programlisting format="linespecific">
...
modparam("dispatcher", "hash_pvar", "$avp(273)")
...
</programlisting>
		</example>
		<example>
		<title>Use combination of PVs for hashing:</title>
<programlisting format="linespecific">
...
modparam("dispatcher", "hash_pvar", "hash the $fU@$ci")
...
</programlisting>
		</example>
	</section>

	<section id="param_setid_pvar" xreflabel="setid_pvar">
		<title><varname>setid_pvar</varname> (str)</title>
		<para>
		The name of the PV where to store the set ID (group ID) when calling
		ds_is_in_list() without group parameter (third parameter).
		</para>
		<para>
		<emphasis>
			Default value is <quote>null</quote> - don't set PV.
		</emphasis>
		</para>
		<example>
		<title>Set the <quote>setid_pvar</quote> parameter</title>
<programlisting format="linespecific">
...
modparam("dispatcher", "setid_pvar", "$var(setid)")
...
</programlisting>
		</example>
	</section>

	<section id="param_ds_ping_method" xreflabel="ds_ping_method">
		<title><varname>ds_ping_method</varname> (string)</title>
		<para>
		With this Method you can define, with which method you want to probe
		the failed gateways. This method is only available, if compiled with
		the probing of failed gateways enabled.
		</para>
		<para>
		Use the 'partition' parameter if you want to define the ping method
		other partitions.
		</para>
		<para>
		<emphasis>
			Default value is <quote>OPTIONS</quote>.
		</emphasis>
		</para>
		<example>
		<title>Set the <quote>ds_ping_method</quote> parameter</title>
<programlisting format="linespecific">
...
modparam("dispatcher", "ds_ping_method", "INFO")
...
</programlisting>
		</example>
	</section>

	<section id="param_ds_ping_from" xreflabel="ds_ping_from">
		<title><varname>ds_ping_from</varname> (string)</title>
		<para>
		With this Method you can define the "From:"-Line for the request,
		sent to the failed gateways. This method is only available, if
		compiled with the probing of failed gateways enabled.
		</para>
		<para>
		Use the 'partition' parameter if you want to define the "From:"
		ping header of other partitions.
		</para>
		<para>
		<emphasis>
			Default value is <quote>sip:dispatcher@localhost</quote>.
		</emphasis>
		</para>
		<example>
		<title>Set the <quote>ds_ping_from</quote> parameter</title>
<programlisting format="linespecific">
...
modparam("dispatcher", "ds_ping_from", "sip:proxy@sip.somehost.com")
...
</programlisting>
		</example>
	</section>

	<section id="param_ds_ping_interval" xreflabel="ds_ping_interval">
		<title><varname>ds_ping_interval</varname> (int)</title>
		<para>
		With this Method you can define the interval for sending a request to
		a failed gateway. This parameter is only used, when the TM-Module is
		loaded. If set to <quote>0</quote>, the pinging of failed requests
		is disabled.
		</para>
		<para>
		<emphasis>
			Default value is <quote>0</quote> (disabled).
		</emphasis>
		</para>
		<example>
		<title>Set the <quote>ds_ping_interval</quote> parameter</title>
<programlisting format="linespecific">
...
modparam("dispatcher", "ds_ping_interval", 30)
...
</programlisting>
		</example>
	</section>

	<section id="param_ds_ping_maxfwd" xreflabel="ds_ping_maxfwd">
		<title><varname>ds_ping_maxfwd</varname> (int)</title>
		<para>
		This parameter allows you to enforce a specific Max-Forward value
		for the SIP pinging requests generated by the Dispatcher modules.
		If not explicitly set, no value will be enforced and it let the
		Transaction Layer (TM module) to set a default Max-Forward value.
		</para>
		<para>
		The accepted values are any positive integer values, including the
		<quote>0</quote> value.
		</para>
		<example>
		<title>Set the <quote>ds_ping_maxfwd</quote> parameter</title>
<programlisting format="linespecific">
...
modparam("dispatcher", "ds_ping_maxfwd", 2)
...
</programlisting>
		</example>
	</section>


	<section id="param_ds_probing_sock" xreflabel="ds_probing_sock">
		<title><varname>ds_probing_sock</varname> (str)</title>
		<para>
		A socket description [proto:]host[:port] of the local socket (which
		is used by OpenSIPS for SIP traffic) to be used (if multiple) for
		sending the probing messages from.
		</para>
		<para>
		<emphasis>
			Default value is <quote>NULL(none)</quote>.
		</emphasis>
		</para>
		<example>
		<title>Set the <quote>ds_probing_sock</quote> parameter</title>
<programlisting format="linespecific">
...
modparam("dispatcher", "ds_probing_sock", "udp:192.168.1.100:5077")
...
</programlisting>
		</example>
	</section>

	<section id="param_ds_probing_threshold" xreflabel="ds_probing_threshold">
		<title><varname>ds_probing_threshold</varname> (int)</title>
		<para>
		If you want to set a gateway into probing mode, you will need a
		specific number of requests until it will change from "active" to
		probing. The number of attempts can be set with this parameter.
		</para>
		<para>
		<emphasis>
			Default value is <quote>3</quote>.
		</emphasis>
		</para>
		<example>
		<title>Set the <quote>ds_probing_threshold</quote> parameter</title>
<programlisting format="linespecific">
...
modparam("dispatcher", "ds_probing_threshold", 10)
...
</programlisting>
		</example>
	</section>

	<section id="param_ds_probing_mode" xreflabel="ds_probing_mode">
		<title><varname>ds_probing_mode</varname> (int)</title>
		<para>
		Controls what gateways are tested to see if they are reachable. If set
		to 0, only the gateways with state PROBING are tested, if set to 1, all
		gateways are tested. If set to 1 and the response is 408 (timeout),
		an active gateway is set to PROBING state.
		</para>
		<para>
		<emphasis>
			Default value is <quote>0</quote>.
		</emphasis>
		</para>
		<example>
		<title>Set the <quote>ds_probing_mode</quote> parameter</title>
<programlisting format="linespecific">
...
modparam("dispatcher", "ds_probing_mode", 1)
...
</programlisting>
		</example>
	</section>

	<section id="param_ds_probing_list" xreflabel="ds_probing_list">
		<title><varname>ds_probing_list</varname> (str)</title>
		<para>
                Defines a list of one or more setids that limits which
                destinations are probed if probing is active.  This is useful
                when multiple proxies share the same dispatcher table, but you
                want to limit which ones are responsible for probing specific
                destinations.
		</para>
		<para>
		<emphasis>
			Default value is <quote>NULL (probe all sets)</quote>.
		</emphasis>
		</para>
		<example>
		<title>Set the <quote>ds_probing_list</quote> parameter</title>
<programlisting format="linespecific">
...
modparam("dispatcher", "ds_probing_list", "1,2,3")
...
</programlisting>
		</example>
	</section>

	<section id="param_ds_define_blacklist" xreflabel="ds_define_blacklist">
		<title><varname>ds_define_blacklist</varname> (str)</title>
		<para>
		Defines a blacklist based on a dispatching setid from the 'default'
		partition.
		This list will contain the IPs (no port, all protocols) of the
		destinations matching the given setid.
		Use the 'partition' parameter if you want to define blacklists
		based on other partitions' sets.
		</para>
		<para>
		Multiple instances of this param are allowed.
		</para>
		<para>
		<emphasis>
			Default value is <quote>NULL</quote>.
		</emphasis>
		</para>
		<example>
			<title>Set the 'default' partition's <quote>ds_define_blacklist</quote>
				parameter</title>
<programlisting format="linespecific">
...
modparam("dispatcher", "ds_define_blacklist", "list= 1,4,3")
modparam("dispatcher", "ds_define_blacklist", "blist2= 2,10,6")
...
</programlisting>
		</example>
	</section>

	<section id="param_options_reply_codes" xreflabel="options_reply_codes">
		<title><varname>options_reply_codes</varname> (str)</title>
		<para>
		This parameter must contain a list of SIP reply codes separated by
		comma. The codes defined here will be considered as valid reply codes
		for OPTIONS messages used for pinging, apart for 200.
		</para>
		<para>
		<emphasis>
			Default value is <quote>NULL</quote>.
		</emphasis>
		</para>
		<example>
		<title>Set the <quote>options_reply_codes</quote> parameter</title>
<programlisting format="linespecific">
...
modparam("dispatcher", "options_reply_codes", "501, 403")
...
</programlisting>
		</example>
	</section>

	<section id="param_dst_avp" xreflabel="dst_avp">
		<title><varname>dst_avp</varname> (str)</title>
		<para>
		This is mainly for internal usage and represents the name of the avp
		which will hold the list with addresses, in the order
		they have been selected by the chosen algorithm. If use_default is 1,
		the value of last dst_avp_id is the last address in destination set. The
		first dst_avp_id is the selected destinations. All the other addresses
		from the destination set will be added in the avp list to be able to
		implement serial forking.
		Setting this parameter will only change the default partition's
		dst_avp. Use the partition parameter to create and alter
		other partitions.
		</para>
		<para>
		<emphasis>
			For the 'default' partition the default value
			is <quote>$avp(ds_dst_failover)</quote>. For any other partition,
			the default value is <quote>$avp(ds_dst_failover_partitionname)</quote>.
		</emphasis>
		</para>
		<example>
		<title>Set the 'default' partition's <quote>dst_avp</quote> parameter</title>
<programlisting format="linespecific">
...
modparam("dispatcher", "dst_avp", "$avp(271)")
...
</programlisting>
		</example>
	</section>

	<section id="param_grp_avp" xreflabel="grp_avp">
		<title><varname>grp_avp</varname> (str)</title>
		<para>
		This is mainly for internal usage and represents the name of the avp
		storing the group id of the destination set. Good
		to have it for later usage or checks.
		Setting this parameter will only change the default partition's
		grp_avp. Use the partition parameter to create and alter
		other partitions.
		</para>
		<para>
		<emphasis>
			For the 'default' partition the default value
			is <quote>$avp(ds_grp_failover)</quote>. For any other partition,
			the default value is <quote>$avp(ds_grp_failover_partitionname)</quote>.
		</emphasis>
		</para>
		<example>
		<title>Set the 'default' partition's <quote>grp_avp</quote> parameter</title>
<programlisting format="linespecific">
...
modparam("dispatcher", "grp_avp", "$avp(273)")
...
</programlisting>
		</example>
	</section>

	<section id="param_cnt_avp" xreflabel="cnt_avp">
		<title><varname>cnt_avp</varname> (str)</title>
		<para>
		This is mainly for internal usage and represents the name of the avp
		storing the number of destination addresses kept in dst_avp avps.
		Setting this parameter will only change the default partition's
		cnt_avp. Use the partition parameter to create and alter
		other partitions.
		</para>
		<para>
		<emphasis>
			For the 'default' partition the default value
			is <quote>$avp(ds_cnt_failover)</quote>. For any other partition,
			the default value is <quote>$avp(ds_cnt_failover_partitionname)</quote>.
		</emphasis>
		</para>
		<example>
		<title>Set the 'default' partition's <quote>cnt_avp</quote> parameter</title>
<programlisting format="linespecific">
...
modparam("dispatcher", "cnt_avp", "$avp(274)")
...
</programlisting>
		</example>
	</section>

	<section id="param_sock_avp" xreflabel="sock_avp">
		<title><varname>sock_avp</varname> (str)</title>
		<para>
		This is mainly for internal usage and represents the name of the avp
		storing the sockets to be used for the destination addresses kept in
		dst_avp avps.
		Setting this parameter will only change the default partition's
		sock_avp. Use the partition parameter to create and alter
		other partitions.
		</para>
		<para>
		<emphasis>
			For the 'default' partition the default value
			is <quote>$avp(ds_sock_failover)</quote>. For any other partition,
			the default value is <quote>$avp(ds_sock_failover_partitionname)</quote>.
		</emphasis>
		</para>
		<example>
		<title>Set the 'default' partition's <quote>sock_avp</quote> parameter</title>
<programlisting format="linespecific">
...
modparam("dispatcher", "sock_avp", "$avp(275)")
...
</programlisting>
		</example>
	</section>

	<section id="param_pvar_algo_pattern" xreflabel="pvar_algo_pattern">
		<title><varname>pvar_algo_pattern</varname> (str)</title>
		<para>
		This parameter is used by the PVAR(9) algorithm to specify the
		pseudovariable pattern used to detect the load of each destination. The
		name of the pseudovariable should contain the string <quote>%u</quote>,
		which will be internally replaced by the module with the uri of the
		destination. The string <quote>%i</quote> can also be used and will be
		replaced with the set ID of the destination (useful in cases where same
		uri exists in multiple sets).
		</para>
		<para>
		</para>
		<para>
		<emphasis>
			Default value is <quote>none</quote>.
		</emphasis>
		</para>
		<example>
		<title>Set the <quote>pvar_algo_pattern</quote> parameter</title>
<programlisting format="linespecific">
...
modparam("dispatcher", "pvar_algo_pattern", "$stat(load_%u)")
...
</programlisting>
		</example>
	</section>

	<section id="param_persistent_state" xreflabel="persistent_state">
		<title><varname>persistent_state</varname> (int)</title>
		<para>
		Specifies whether the <emphasis>state</emphasis> column
		should be loaded at startup and flushed during runtime or not
		for the "default" partition.
		</para>
		<para>
		Use the 'partition' parameter if you want to define the persistent
		state of other partitions.
		</para>
		<para>
		<emphasis>Default value is <quote>1</quote> (enabled).
		</emphasis>
		</para>
		<example>
		<title>Set the <varname>persistent_state</varname> parameter</title>
		<programlisting format="linespecific">
...
# disable all DB operations with the state of a destination
modparam("dispatcher", "persistent_state", 0)
...
</programlisting>
		</example>
	</section>

	<section id="param_cluster_id" xreflabel="cluster_id">
		<title><varname>cluster_id</varname> (integer)</title>
		<para>
		The ID of the cluster the module is part of. The clustering support is 
		used in dispatcher module for two purposes: for sharing the status 
		of the destinations and for controlling the pinging to destinations.
		</para>
		<para>
		If clustering enbled, the module will automatically share changes
		over the status of the destinations with the other 
		OpenSIPS instances that are part of a cluster. Whenever such a status 
		changes (following an MI command, a probing result, a script command),
		the module will replicate this status change to all the nodes in this 
		given cluster.
		</para>
		<para>
		The clustering with sharing tag support may be used to control which 
		node in the cluster will perform the pinging/probing to 
		destinations. See the
		<xref linkend="param_cluster_sharing_tag"/> option.
		</para>

			&clusterer_sync_cap_para;

		<para>
		For more info on how to define and populate a cluster (with OpenSIPS 
		nodes) see the <ulink url='clusterer'>clusterer</ulink> module.
		</para>
		<para>
		<emphasis>
			Default value is <quote>0 (none)</quote>.
		</emphasis>
		</para>
		<example>
		<title>Set <varname>cluster_id</varname> parameter</title>
		<programlisting format="linespecific">
...
# replicate destination status with all OpenSIPS in cluster ID 9
modparam("dispatcher", "cluster_id", 9)
...
</programlisting>
		</example>
	</section>

	<section id="param_cluster_sharing_tag" xreflabel="cluster_sharing_tag">
		<title><varname>cluster_sharing_tag</varname> (string)</title>
		<para>
		The name of the sharing tag (as defined per clusterer modules) to 
		control which node is responsible for perform the self-triggered
		actions in the module. Such actions may be the destination probing
		(see also the <xref linkend="param_cluster_probing_mode"/> parameter)
		or sharing the changes in the destination status.
		If defined, only the node with active status of this tag will 
		perform the actions (pinging and sharing status).
		</para>
		<para>
		The <xref linkend="param_cluster_id"/> must be defined for this option
		to work.
		</para>
		<para>
		This is an optional parameter. If not set, all the nodes in the cluster
		will share the status changes.
		</para>
		<para>
		<emphasis>
			Default value is <quote>empty (none)</quote>.
		</emphasis>
		</para>
		<example>
		<title>Set <varname>cluster_sharing_tag</varname> parameter</title>
		<programlisting format="linespecific">
...
# only the node with the active "vip" sharing tag will perform pinging
# and broadcast the status changes
modparam("dispatcher", "cluster_id", 9)
modparam("dispatcher", "cluster_sharing_tag", "vip")
...
</programlisting>
		</example>
	</section>

	<section id="param_cluster_probing_mode" xreflabel="cluster_probing_mode">
		<title><varname>cluster_probing_mode</varname> (string)</title>
		<para>
		This paramter controls how the probing/pinging should be done when
		using the clustering support. It is about which node in the cluster
		pings which gateway/destination.
		</para>
		<para>
		The <xref linkend="param_cluster_id"/> must be defined for this option
		to work.
		</para>
		<para>
		The supported probing modes are:
		</para>
		<itemizedlist>
		<listitem>
			<para>
			<emphasis role='bold'>"all"</emphasis> - all the nodes in the
			cluster will independetly ping all the defined destinations,
			an "all" pings "all" mode.
			</para>
		</listitem>
		<listitem>
			<para>
			<emphasis role='bold'>"by-shtag"</emphasis> - all the destinations
			are pinged by only one node in the cluster, the node having the
			<xref linkend="param_cluster_sharing_tag"/> active. By 
			activating the sharing tag on a different node, the pinging
			duty will be transfered to another node in the cluster.
			</para>
		</listitem>
		<listitem>
			<para>
			<emphasis role='bold'>"distributed"</emphasis> - the pinging
			effort is distributed across all the nodes in the cluster, so each
			node will ping a sub-set of the overall set of destinations. Still
			all the destinations will get pinged (and only once per pinging 
			cycle).
			The re-partitioning of the pinging effort over the available nodes
			in the cluster is automatically done when new nodes are joining or
			nodes are dropping out. Still there is no guaratee on which node
			will be responsible for pinging which destination.
			</para>
		</listitem>
		</itemizedlist>
		<para>
		<emphasis>
			Default value is <quote>"all"</quote>.
		</emphasis>
		</para>
		<example>
		<title>Set <varname>cluster_probing_mode</varname> parameter</title>
		<programlisting format="linespecific">
...
# only the node with the active "vip" sharing tag will perform pinging
modparam("dispatcher", "cluster_id", 9)
modparam("dispatcher", "cluster_sharing_tag", "vip")
modparam("dispatcher", "cluster_probing_mode", "by-shtag")
...
# the pinging effort is distributed across all the nodes
modparam("dispatcher", "cluster_id", 9)
modparam("dispatcher", "cluster_probing_mode", "distributed")
...
</programlisting>
		</example>
	</section>

	<section id="param_partition" xreflabel="partition">
		<title><varname>partition</varname> (string)</title>
		<para>
		Define a new partition (data source) with the following properties:
		"db_url", "table_name", "dst_avp", "grp_avp", "cnt_avp", "sock_avp",
		"attrs_avp", "script_attrs", "ds_define_blacklist".  All these
		properties are optional, having appropriate default values.
		</para>
		<para>
		The syntax is: "partition_name: param1 = value1; param2 = value2".
		Each value format is the same as the one used to define a specific
		parameter using modparam.
		</para>
		<para>
		This parameter may be set multiple times, thus defining as many
		partitions as needed.  The 'default' partition may also be defined
		using this parameter.
		</para>

		<example>
		<title> Define a new partition called 'voicemail' </title>
<programlisting format="linespecific">
...
modparam("dispatcher", "partition",
                "voicemail:
                    db_url = mysql://user:passwd@localhost/database;
                    table_name = dispatcher;
                    attrs_avp = $avp(ds_attr_vm);
                    ds_define_blacklist = list2 = 4,6")
...
</programlisting>
		</example>

		<example>
			<title> Define the 'trunks' partition and make it the 'default'
					partition, so we avoid loading the 'dispatcher' table
			</title>
<programlisting format="linespecific">
...
modparam("dispatcher", "partition",
                "trunks:
                    db_url = mysql://user:passwd@localhost/database;
                    table_name = dispatcher_trunks;
                    attrs_avp = $avp(ds_attr_trunks)")
modparam("dispatcher", "partition", "default: trunks")
...
</programlisting>
		</example>
	</section>

	<section id="param_table_name" xreflabel="table_name">
		<title><varname>table_name</varname> (string)</title>
		<para>
		The default name of the table from which to load dispatcher
		destinations.  Partitions which are missing the 'table_name' property
		will inherit their table name from this value.
		</para>
		<para>
		<emphasis>
			Default value is <quote>dispatcher</quote>.
		</emphasis>
		</para>
		<example>
		<title>Set the default table name</title>
<programlisting format="linespecific">
...
modparam("dispatcher", "table_name", "my_dispatcher")
...
</programlisting>
		</example>
	</section>

	<section id="param_setid_col" xreflabel="setid_col">
		<title><varname>setid_col</varname> (string)</title>
		<para>
			The column's name in the database storing the gateway's group id.
		</para>
		<para>
		<emphasis>
			Default value is <quote>setid</quote>.
		</emphasis>
		</para>
		<example>
		<title>Set <quote>setid_col</quote> parameter</title>
<programlisting format="linespecific">
...
modparam("dispatcher", "setid_col", "groupid")
...
</programlisting>
		</example>
	</section>

	<section id="param_destination_col" xreflabel="destination_col">
		<title><varname>destination_col</varname> (string)</title>
		<para>
			The column's name in the database storing the destination's
			sip uri.
		</para>
		<para>
		<emphasis>
			Default value is <quote>destination</quote>.
		</emphasis>
		</para>
		<example>
		<title>Set <quote>destination_col</quote> parameter</title>
<programlisting format="linespecific">
...
modparam("dispatcher", "destination_col", "uri")
...
</programlisting>
		</example>
	</section>

	<section id="param_state_col" xreflabel="state_col">
		<title><varname>state_col</varname> (string)</title>
		<para>
			The column's name in the database storing the state of the
			destination uri.
		</para>
		<para>
		<emphasis>
			Default value is <quote>state</quote>.
		</emphasis>
		</para>
		<example>
		<title>Set <quote>state_col</quote> parameter</title>
<programlisting format="linespecific">
...
modparam("dispatcher", "state_col", "dststate")
...
</programlisting>
		</example>
	</section>

	<section id="param_weight_col" xreflabel="weight_col">
		<title><varname>weight_col</varname> (string)</title>
		<para>
			The column's name in the database storing the weight for
			destination uri.
		</para>
		<para>
		<emphasis>
			Default value is <quote>weight</quote>.
		</emphasis>
		</para>
		<example>
		<title>Set <quote>weight_col</quote> parameter</title>
<programlisting format="linespecific">
...
modparam("dispatcher", "weight_col", "dstweight")
...
</programlisting>
		</example>
	</section>

	<section id="param_priority_col" xreflabel="priority_col">
		<title><varname>priority_col</varname> (string)</title>
		<para>
			The column's name in the database storing the priority for
			destination uri.
		</para>
		<para>
		<emphasis>
			Default value is <quote>priority</quote>.
		</emphasis>
		</para>
		<example>
		<title>Set <quote>priority_col</quote> parameter</title>
<programlisting format="linespecific">
...
modparam("dispatcher", "priority_col", "dstprio")
...
</programlisting>
		</example>
	</section>

	<section id="param_attrs_col" xreflabel="attrs_col">
		<title><varname>attrs_col</varname> (string)</title>
		<para>
			The column's name in the database storing the attributes (opaque
			string) for destination uri.
		</para>
		<para>
		<emphasis>
			Default value is <quote>attrs</quote>.
		</emphasis>
		</para>
		<example>
		<title>Set <quote>attrs_col</quote> parameter</title>
<programlisting format="linespecific">
...
modparam("dispatcher", "attrs_col", "dstattrs")
...
</programlisting>
		</example>
	</section>

	<section id="param_socket_col" xreflabel="socket_col">
		<title><varname>socket_col</varname> (string)</title>
		<para>
			The column's name in the database storing the socket (as
			string) for destination uri.
		</para>
		<para>
		<emphasis>
			Default value is <quote>socket</quote>.
		</emphasis>
		</para>
		<example>
		<title>Set <quote>socket_col</quote> parameter</title>
<programlisting format="linespecific">
...
modparam("dispatcher", "socket_col", "my_sock")
...
</programlisting>
		</example>
	</section>

	<section id="param_probe_mode_col" xreflabel="probe_mode_col">
		<title><varname>probe_mode_col</varname> (string)</title>
		<para>
			The column's name in the database storing the probe_mode (as
			string) for destination.
		</para>
		<para>
		<emphasis>
			Default value is <quote>probe_mode</quote>.
		</emphasis>
		</para>
		<example>
		<title>Set <quote>probe_mode_col</quote> parameter</title>
<programlisting format="linespecific">
...
modparam("dispatcher", "probe_mode_col", "probing")
...
</programlisting>
		</example>
	</section>

	<section id="param_fetch_freeswitch_stats" xreflabel="fetch_freeswitch_stats">
		<title><varname>fetch_freeswitch_stats</varname> (integer)</title>
		<para>
		If enabled, FreeSWITCH destinations may have dynamic dispatching weights,
		refreshed at runtime, using the FreeSWITCH Event Socket Layer.
		For these destinations, an Event Socket Layer URL must be provisioned
		into the "weight" column, instead of an integer string. Some example values:
		<emphasis>"fs://:password@freeswitch.example.com"</emphasis>
		or <emphasis>"fs://user:password@127.0.0.1:8021"</emphasis>.
		The default ESL port is 8021.
	</para>
		<para>
		OpenSIPS will establish a connection with the given socket and
		periodically calculate/update the weights of these destinations
		using statistics pushed by the FreeSWITCH box.
		</para>
	<para>
		The value for an automatically calculated weight ranges between
		<emphasis role='bold'>0 - 100</emphasis>.
		This is helpful when grouping normal destinations with
		FreeSWITCH ones.
		</para>
		<para>
		The dynamic weights are recalculated every
		<emphasis>event_heartbeat_interval</emphasis> seconds (see the
		"freeswitch" OpenSIPS module for more details regarding this setting),
		as the stats from FreeSWITCH are expected to arrive.  The update formula
		is shown below (FreeSWITCH stats are highlighted in bold):
	</para>
	<para>
		<emphasis>weight = 100 * (<emphasis role='bold'>Idle-CPU</emphasis> / 100) * (1 - <emphasis role='bold'>Session-Count</emphasis> / <emphasis role='bold'>Max-Sessions</emphasis>)</emphasis>
		</para>
		<para>
		<emphasis>
			Default value is <emphasis role='bold'>0</emphasis> (disabled).
		</emphasis>
		</para>
		<example>
		<title>Set the <varname>fetch_freeswitch_load</varname> parameter</title>
		<programlisting format="linespecific">
...
modparam("dispatcher", "fetch_freeswitch_stats", 1)
...
</programlisting>
		</example>
	</section>

	<section id="param_max_freeswitch_weight" xreflabel="max_freeswitch_weight">
		<title><varname>max_freeswitch_weight</varname> (integer)</title>
		<para>
		The maximum weight of a FreeSWITCH ESL-enabled destination. This value
		is also used during startup/reload, when no stats from FreeSWITCH are
		available yet.
		</para>
		<para>
		Important: When mixing normal destinations with FreeSWITCH-enabled ones in
		the same dispatching set, OpenSIPS will truncate any weight values that
		are larger than <emphasis role='bold'>max_freeswitch_weight</emphasis>
		to the value of this parameter!
		</para>
		<para>
		NOTE: OpenSIPS internally rounds weights to nearest integer, so larger
		max weight values will more accurately represent the current load on the
		FreeSWITCH boxes! For example, if you set this parameter to 1, the box
		will receive no traffic whenever either its CPU or session usage goes
		past 50%!
		</para>
		<para>
		<emphasis>
			Default value is <emphasis role='bold'>100</emphasis>.
		</emphasis>
		</para>
		<example>
		<title>Set the <varname>max_freeswitch_weight</varname> parameter</title>
		<programlisting format="linespecific">
...
modparam("dispatcher", "max_freeswitch_weight", 1000)
...
</programlisting>
		</example>
	</section>

	</section>


	<section id="exported_functions" xreflabel="exported_functions">
	<title>Exported Functions</title>
	<section id="func_ds_select_dst" xreflabel="ds_select_dst()">
		<title>
		<function moreinfo="none">ds_select_dst(set, alg, [flags], [partition], [max_res])</function>
		</title>
		<para>
		The method selects a destination from the given set of addresses. It will
		overwrite the destination URI (<emphasis>$du</emphasis>) of a SIP request.
		</para>
		<para>Meaning of the parameters is as follows:</para>
		<itemizedlist>
		<listitem>
			<para>
			<emphasis>set (int)</emphasis> - a set identifier from which to select destinations
			</para>
		</listitem>
		<listitem>
			<para>
			<emphasis>alg (int)</emphasis> - the algorithm used to select the
			destination address
			</para>
			<itemizedlist>
			<listitem>
				<para>
				<quote>0</quote> - hash over callid
				</para>
			</listitem>
			<listitem>
				<para>
				<quote>1</quote> - hash over from uri.
				</para>
			</listitem>
			<listitem>
				<para>
				<quote>2</quote> - hash over to uri.
				</para>
			</listitem>
			<listitem>
				<para>
				<quote>3</quote> - hash over request-uri.
				</para>
			</listitem>
			<listitem>
				<para>
				<quote>4</quote> - weighted round-robin (next destination).
				the destination's weight determines how many times it is chosen
				before going to the next one
				</para>
			</listitem>
			<listitem>
				<para>
				<quote>5</quote> - hash over authorization-username
				(Proxy-Authorization or "normal" authorization).
				If no username is found, weighted round-robin is used.
				</para>
			</listitem>
			<listitem>
				<para>
				<quote>6</quote> - random (using rand()).
				</para>
			</listitem>
			<listitem>
				<para>
				<quote>7</quote> - hash over the content of PVs string.
				Note: This works only when the parameter hash_pvar is set.
				</para>
			</listitem>
			<listitem>
				<para>
				<quote>8</quote> - the first entry in set is chosen.
				</para>
			</listitem>
			<listitem>
				<para>
				<quote>9</quote> - The <emphasis>pvar_algo_pattern</emphasis>
				parameter is used to determine the load on each server. If the
				parameter is not specified, then the first entry in the set is
				chosen.
				</para>
			</listitem>
			<listitem>
				<para>
				<quote>10</quote> - The <emphasis>algo_route</emphasis>
				OpenSIPS route is called for each dispatcher entry in 
				the setid, in order to decide the routing order.
				See the algo_route parameter for usage examples
				</para>
			</listitem>

			<listitem>
				<para>
				<quote>X</quote> - if the algorithm is not implemented, the
				first entry in set is chosen.
				</para>
			</listitem>
			</itemizedlist>
		</listitem>
		<listitem>
			<para>
			<emphasis>flags (string, optional)</emphasis> - a string of flag-settings
				which tweak the function's behavior:
			</para>
			<itemizedlist>
			<listitem>
				<para>'f' (failover support): causes the remaining
				addresses from the destination set to be stored within an
				internally managed AVP.  You may then use
				<xref linkend="func_ds_next_dst"/> to switch to the next
				address, thus achieving serial forking to all possible destinations
				</para>
			</listitem>

			<listitem>
				<para>'u' (user only): will specify that only the URI user part
					will be used for hashing</para>
			</listitem>


			<listitem>
				<para>'d' (use default): use the last address in destination
					set as last option to send the message</para>
			</listitem>

			<listitem>
				<para>'a' (append destinations): append any new destinations to
					the current destination list, rather than rewriting the list</para>
			</listitem>
			</itemizedlist>
			<para>
			The flags are being kept per partition.
			</para>
		</listitem>
		<listitem>
			<para>
			<emphasis>partition (string, optional)</emphasis> - name of a DB partition
			</para>
		</listitem>
		<listitem>
			<para>
			<emphasis>max_res (int, optional)</emphasis> - signifies that only a maximum
			number of destinations shall be included in the specified failover AVP. 
			This allows having multiple destinations while
			also preventing excessive failover attempts in case a number is
			bound to fail globally.
			</para>
		</listitem>
		</itemizedlist>
		<para>
		This function can be used from REQUEST_ROUTE, BRANCH_ROUTE and FAILURE_ROUTE.
		</para>
		<example>
		<title><function>ds_select_dst</function> usage</title>
<programlisting format="linespecific">
...
if (!ds_select_dst(1, 0)) {
	xlog("ERROR: no active destinations found!\n");
	send_reply(503, "Service Unavailable");
	exit;
}
...
ds_select_dst(1, 0, , "fs_boxes", 5);
...
ds_select_dst(1, 0, "fUD", "ask_boxes");
...
ds_select_dst(2, 0, "fud", "pstn_gws", 5);
ds_select_dst(3, 1, "fua", "pstn_gws", 2);
...
# using variables
$var(part) = "pstn_gws"
$var(setid) = 1;
$var(alg) = 4;
$var(flags) = "fdu";
$var(max_res) = 2;
ds_select_dst($var(setid), $var(alg), $var(flags), $var(part), $var(max_res));
...
</programlisting>
		</example>
	</section>
	<section id="func_ds_select_domain" xreflabel="ds_select_domain()">
		<title>
		<function moreinfo="none">ds_select_domain(set, alg, [flags], [partition], [max_res])</function>
		</title>
		<para>
		The method selects a destination from addresses set and rewrites the
		hostname and port parts of the Request-URI (<emphasis>$ru</emphasis>).
		Its parameters have same meaning as in <xref linkend="func_ds_select_dst"/>.
		</para>
		<para>
		If the "f" (failover support) flag is present, the rest of the
		addresses from the destination set will be stored in an internally
		managed AVP. You may then use <xref linkend="func_ds_next_domain"/> to
		switch to the next address in the list, thus achieving serial forking
		to all possible destinations.
		</para>
		<para>
		This function can be used from REQUEST_ROUTE, BRANCH_ROUTE and FAILURE_ROUTE.
		</para>
	</section>
	<section id="func_ds_next_dst" xreflabel="ds_next_dst()">
		<title>
		<function moreinfo="none">ds_next_dst([partition])</function>
		</title>
		<para>
		Takes the next destination address from the AVPs with id
		partition.'dst_avp_id' and sets the dst_uri (outbound proxy address).
		If "partition" is omitted, the default partition will be used.This
		function is using the flags set in ds_select_dst or ds_select_domain.
		</para>
		<para>
		This function can be used from REQUEST_ROUTE and FAILURE_ROUTE.
		</para>
	</section>
	<section id="func_ds_next_domain" xreflabel="ds_next_domain()">
		<title>
		<function moreinfo="none">ds_next_domain([partition])</function>
		</title>
		<para>
		Takes the next destination address from the AVPs with id
		partition.'dst_avp_id' and sets the domain part of the request uri.
		If "partition" is omitted, the default partition will be used.This
		function is using the flags set in ds_select_dst or ds_select_domain.
		</para>
		<para>
		This function can be used from REQUEST_ROUTE and FAILURE_ROUTE.
		</para>
	</section>
	<section id="func_ds_mark_dst" xreflabel="ds_mark_dst()">
		<title>
		<function moreinfo="none">ds_mark_dst([state], [partition])</function>
		</title>
		<para>
		Mark the last used address from partition's destination set as
		inactive ("i"/"I"/"0"), active ("a"/"A"/"1") or probing ("p"/"P"/"2").
		With this function, an automatic detection of failed gateways can be implemented.
		When an address is marked as inactive or probing, it will be ignored by
		<xref linkend="func_ds_select_dst"/> and <xref linkend="func_ds_select_domain"/>.
		If "partition" is omitted, the default partition will be used. This function
		is using the flags set in <xref linkend="func_ds_select_dst"/> or
		<xref linkend="func_ds_select_domain"/>.
		</para>
		<para>Possible parameters:</para>
		<itemizedlist>
		<listitem>
			<para>state (string, optional) - new state for the last attempted
				destination.  Possible values:</para>
			<itemizedlist>
			<listitem>
				<para><emphasis>"i", "I" or "0" (default)</emphasis> - the last
					destination should be set to inactive and will be ignored
					in future requests.</para>
			</listitem>
			<listitem>
				<para><emphasis>"a", "A" or "1"</emphasis> - the last
					destination should be set to active.</para>
			</listitem>
			<listitem>
				<para><emphasis>"p", "P" or "2"</emphasis> - the last
					destination will be set to probing. Note: You will need to
					call this function "threshold"-times, before it will be
					actually set to probing.</para>
			</listitem>
			</itemizedlist>
		</listitem>
		<listitem>
			<para>partition (string, optional) - name of a DB partition,
			otherwise the default one will be used</para>
		</listitem>
		</itemizedlist>

		<para>
		This function can be used from REQUEST_ROUTE and FAILURE_ROUTE.
		</para>
	</section>
	<section id="func_ds_count" xreflabel="ds_count()">
		<title>
		<function moreinfo="none">ds_count(set, state_filter, res_var, [partition])</function>
		</title>
		<para>
		Returns the number of active, inactive or probing destinations in a
		partition's set, or combinations between these properties.
		</para>
		<para>Meaning of the parameters:</para>
		<itemizedlist>
		<listitem>
			<para>
			<emphasis>set (int)</emphasis> - a set of dispatching destinations
			</para>
		</listitem>

		<listitem>
			<para><emphasis>state_filter (string)</emphasis> - which destinations should be
			counted. Either active ("a", "A" or "1"), inactive
			("i", "I" or "0"), probing ("p", "P" or "2") destinations or
			different combinations between these flags, such as
			"pI", "1i", "ipA"... </para>
		</listitem>

		<listitem>
			<para><emphasis>res_var (variable)</emphasis> - a variable
				which will hold the integer result</para>
		</listitem>

		<listitem>
			<para><emphasis>partition (string, optional)</emphasis> - name of a
				DB partition.  If omitted, the "default" partition
				will be used.</para>
		</listitem>
		</itemizedlist>
		<para>
		This function can be used from REQUEST_ROUTE, FAILURE_ROUTE, BRANCH_ROUTE,
		LOCAL_ROUTE, TIMER_ROUTE, EVENT_ROUTE
		</para>
		<example>
		<title><function>ds_count</function> usage</title>
<programlisting format="linespecific">
...
if (ds_count(1, "a", $avp(result))) {
	...
}
...
if (ds_count($avp(set), "ip", $avp(result), $avp(partition))) {
	...
}
...
</programlisting>
		</example>
	</section>

	<section id="func_ds_is_in_list" xreflabel="ds_is_in_list()">
		<title>
		<function moreinfo="none">ds_is_in_list(ip, port, [set], [partition], [active_only], [pattern])</function>
		</title>
		<para>
		This function returns <emphasis>true</emphasis> only if "ip" and "port" point to a
		host from the given dispatcher "set".
		</para>
		<para>
		Meaning of the parameters:
		</para>
		<itemizedlist>
		<listitem>
			<para><emphasis>ip (string)</emphasis> - an IPv4 or IPv6 address to
				test against the dispatcher "set"</para>
		</listitem>
		<listitem>
			<para><emphasis>port (int)</emphasis> - a port to test against the
			dispatcher list.  Use a <emphasis>0</emphasis> value in order to
			match any port</para>
		</listitem>
		<listitem>
			<para><emphasis>set (int, optional)</emphasis> - a dispatcher set
			identifier to test against.  If missing, all sets will be checked.
			The <emphasis>-1</emphasis> set is a special value, acting as a
			"check all sets" wildcard.
			</para>
		</listitem>
		<listitem>
			<para><emphasis>partition (string, optional)</emphasis> - name of
				a DB partition</para>
		</listitem>
		<listitem>
			<para><emphasis>active_only (int, optional)</emphasis> - specify
			a non-zero value in order to only search through the active
			destinations (ignore the ones in probing and inactive states)</para>
		</listitem>
		<listitem>
			<para><emphasis>pattern (string, optional)</emphasis> - a glob
			pattern used to match destination attributes. If the destination
			ip and port matches but the pattern does not match the destination's
			attribute, the function will fail.</para>
		</listitem>
		</itemizedlist>
		<para>
		This function can be used from REQUEST_ROUTE, FAILURE_ROUTE,
		BRANCH_ROUTE and ONREPLY_ROUTE.
		</para>
		<example>
		<title><function>ds_is_in_list</function> usage</title>
<programlisting format="linespecific">
...
if (ds_is_in_list($si, $sp)) {
	# source IP:PORT is in a dispatcher list
}
...
if (ds_is_in_list($rd, $rp, 2)) {
	# the R-URI (IP and port) is in the dispatcher set 2 of the "default" partition
}
...
if (ds_is_in_list($rd, $rp, 2, "part2")) {
	# the R-URI (IP and port) is in the dispatcher set 2 of the "part2" partition
}
...
</programlisting>
		</example>

	</section>

	<section id="func_ds_push_script_attrs" xreflabel="ds_push_script_attrs()">
		<title>
		<function moreinfo="none">ds_push_script_attrs(script_attr, ip, port, set, [partition])</function>
		</title>
		<para>
		Set the script attrs for the dispatcher entry defined by IP, Port, setid and partition.
		</para>
		<para>Meaning of the parameters:</para>
		<itemizedlist>
		<listitem>
			<para>
			<emphasis>script_attr (str or pvar)</emphasis> - The new script attributes
			</para>
		</listitem>

		<listitem>
			<para><emphasis>IP (string)</emphasis> -
			IP address for which we are pushing script attributes </para>
		</listitem>

		<listitem>
			<para><emphasis>port (int)</emphasis> Port for which we are pushing script attributes</para>
		</listitem>

		<listitem>
			<para><emphasis>setid (int)</emphasis> Setid for which we are pushing script attributes</para>
		</listitem>

		<listitem>
			<para><emphasis>partition (string, optional)</emphasis> - name of a
				DB partition.  If omitted, the "default" partition
				will be used.</para>
		</listitem>
		</itemizedlist>
		<para>
		This function can be used from REQUEST_ROUTE, FAILURE_ROUTE, BRANCH_ROUTE,
		LOCAL_ROUTE, TIMER_ROUTE, EVENT_ROUTE
		</para>
		<example>
		<title><function>ds_count</function> usage</title>
<programlisting format="linespecific">
...
if (ds_push_script_attrs($var(my_attributes),$si , $sp, 1, 'my_partition')) {
	...
}
...
</programlisting>
		</example>
	</section>

	<section id="func_ds_get_script_attrs" xreflabel="ds_get_script_attrs()">
		<title>
		<function moreinfo="none">ds_get_script_attrs(uri, set, [partition], out_attrs)</function>
		</title>
		<para>
		Get the script attrs for the dispatcher entry defined by the URI, setid and partition.
		</para>
		<para>Meaning of the parameters:</para>
		<itemizedlist>
		<listitem>
			<para><emphasis>URI (string)</emphasis> -
			URI address for which we are getting script attributes </para>
		</listitem>

		<listitem>
			<para><emphasis>setid (int)</emphasis> Setid for which we are pushing script attributes</para>
		</listitem>

		<listitem>
			<para><emphasis>partition (string, optional)</emphasis> - name of a
				DB partition.  If omitted, the "default" partition
				will be used.</para>
		</listitem>
		<listitem>
			<para><emphasis>out_atrs (pvar)</emphasis> - name of a
				variable where we will store the script attrs.</para>
		</listitem>
		</itemizedlist>
		<para>
		This function can be used from REQUEST_ROUTE, FAILURE_ROUTE, BRANCH_ROUTE,
		LOCAL_ROUTE, TIMER_ROUTE, EVENT_ROUTE
		</para>
		<example>
		<title><function>ds_count</function> usage</title>
<programlisting format="linespecific">
...
if (ds_push_script_attrs($var(my_attributes),$si , $sp, 1, 'my_partition')) {
	...
}
...
</programlisting>
		</example>
	</section>
	</section>

	<section id="exported_mi_functions" xreflabel="Exported MI Functions">
	<title>Exported MI Functions</title>
	<section id="mi_ds_set_state" xreflabel="ds_set_state">
		<title>
		<function moreinfo="none">ds_set_state</function>
		</title>
		<para>
		Sets the status for a destination address (can be use to mark the destination
		as active or inactive).
		</para>
		<para>
		Name: <emphasis>ds_set_state</emphasis>
		</para>
		<para>Parameters:</para>
		<itemizedlist>
			<listitem><para><emphasis>state</emphasis> : state of the destination address</para>
				<itemizedlist>
					<listitem><para> <quote>a</quote>: active </para></listitem>
					<listitem><para> <quote>i</quote>: inactive </para></listitem>
					<listitem><para> <quote>p</quote>: probing </para></listitem>
				</itemizedlist>
			</listitem>

			<listitem><para><emphasis>group</emphasis>: partition name followed by colon
			and destination group id. If the partition name is omitted,
			the default partition will be used</para></listitem>

			<listitem><para><emphasis>address</emphasis>: address of the destination in the group</para></listitem>
		</itemizedlist>
		<para>
		MI FIFO Command Format:
		</para>
<programlisting  format="linespecific">
opensips-cli -x mi ds_set_state a 2 sip:10.0.0.202
</programlisting>
	</section>
	<section id="mi_ds_list" xreflabel="ds_list">
		<title>
		<function moreinfo="none">ds_list</function>
		</title>
		<para>
		It lists the groups and included destinations of all the partitions.
		</para>
		<para>
		Name: <emphasis>ds_list</emphasis>
		</para>
		<para>Parameters:</para>
		 <itemizedlist>
			<listitem><para>
				<emphasis>full</emphasis> (optional) - adds the weight,
				priority and description fields to the listing
			</para></listitem>
			<listitem><para>
				<emphasis>partition</emphasis> (optional) - return only
				destinations and sets in the provided partition.
			</para></listitem>
		</itemizedlist>
		<para>
		MI FIFO Command Format:
		</para>
<programlisting  format="linespecific">
opensips-cli -x mi ds_list
</programlisting>
	</section>
	<section id="mi_ds_reload" xreflabel="ds_reload">
		<title>
		<function moreinfo="none">ds_reload</function>
		</title>
		<para>
		It reloads the groups and included destinations for a
		specified partition or all partitions.
		</para>
		<para>
		Name: <emphasis>ds_reload</emphasis>
		</para>
		<para>Parameters:</para>
		<itemizedlist>
			<listitem><para>
				<emphasis>partition</emphasis> (optional) - name of
				the partition to be reloaded. default partition is "default".
			</para></listitem>

			<listitem><para><emphasis>inherit_state</emphasis> (optional) : whether inherit old state of the destination , default is y. </para>
				<itemizedlist>
					<listitem><para> <quote>n</quote>: no inherit state </para></listitem>
					<listitem><para> <quote>y</quote>: inherit state </para></listitem>
				</itemizedlist>
			</listitem>
			
		</itemizedlist>
		<para>
		MI FIFO Command Format:
		</para>
<programlisting  format="linespecific">
opensips-cli -x mi ds_reload
opensips-cli -x mi ds_reload inherit_state=n
</programlisting>
	</section>

	<section id="mi_ds_push_script_attrs" xreflabel="ds_push_script_attrs">
		<title>
		<function moreinfo="none">ds_push_script_attrs</function>
		</title>
		<para>
		Pushes script attrs for the dispatcher entry defined by IP, Port, setid, and optionally partition. 
		</para>
		<para>
		Name: <emphasis>ds_push_script_attrs</emphasis>
		</para>
		<para>Parameters:</para>
		<itemizedlist>
			<listitem><para><emphasis>attrs</emphasis> : new attributes to be pushed</para>
			</listitem>

			<listitem><para><emphasis>ip</emphasis>: IP for which we are pushing script attributes</para></listitem>

			<listitem><para><emphasis>port</emphasis>: Port for which we are pushing script attributes</para></listitem>

			<listitem><para><emphasis>setid</emphasis>: Setid for which we are pushing script attributes</para></listitem>
			<listitem><para><emphasis>partition ( optional )</emphasis>: Partition for which we are pushing script attributes</para></listitem>
		</itemizedlist>
		<para>
		MI FIFO Command Format:
		</para>
<programlisting  format="linespecific">
#opensips-cli -x mi ds_push_script_attrs '{"ping":"30000","load":"50"}' '192.168.0.107' 5091 1 main
</programlisting>
	</section>

	</section>

	<section id="exported_events" xreflabel="Exported Events">
	<title>Exported Events</title>
	<section id="event_E_DISPATCHER_STATUS" xreflabel="E_DISPATCHER_STATUS">
		<title>
		<function moreinfo="none">E_DISPATCHER_STATUS</function>
		</title>
		<para>
			This event is raised when the dispatcher module marks a destination as
			activated or deactivated.
		</para>
		<para>Parameters:</para>
		<itemizedlist>
			<listitem><para>
				<emphasis>partition</emphasis> - the partition name of the destination.
			</para></listitem>
			<listitem><para>
				<emphasis>group</emphasis> - the group of the destination.
			</para></listitem>
			<listitem><para>
				<emphasis>address</emphasis> - the address of the destination.
			</para></listitem>
			<listitem><para>
				<emphasis>status</emphasis> - <emphasis>active</emphasis> if
				the destination gets activated or <emphasis>inactive</emphasis> if the
				destination is detected unresponsive.
			</para></listitem>
		</itemizedlist>
	</section>
	</section>


<section id="sr_identifiers" xreflabel="Status/Report Identifiers">
	<title>Exported Status/Report Identifiers</title>

	<para>
	The module provides the "dispatcher" Status/Report group, where each
	partition is defined as a separate SR identifier.
	</para>
	<section id="sr_id_partition_name" xreflabel="partition_name">
	<title><varname>[partition_name]</varname></title>
	<para>
	The status of these identifiers reflects the readiness/status of the 
	cached data (if available or not when being loaded from DB):
	</para>
	<itemizedlist>
		<listitem><para>
		<emphasis>-2</emphasis> - no data at all (initial status)
		</para></listitem>
		<listitem><para>
		<emphasis>-1</emphasis> - no data, initial loading in progress
		</para></listitem>
		<listitem><para>
		<emphasis>1</emphasis> - data loaded, partition ready
		</para></listitem>
		<listitem><para>
		<emphasis>2</emphasis> - data available, a reload in progress
		</para></listitem>
	</itemizedlist>

	<para>
	Reload reporting:
	</para>
	<para>
	In terms of date reloading, the following events will be reported:
	</para>
	<itemizedlist>
		<listitem><para>
		starting DB data loading
		</para></listitem>
		<listitem><para>
		DB data loading failed, discarding
		</para></listitem>
		<listitem><para>
		DB data loading successfully completed
		</para></listitem>
		<listitem><para>
		N destination loaded (N discarded)
		</para></listitem>
	</itemizedlist>
	<programlisting  format="linespecific">
        {
            "Name": "default",
            "Reports": [
                {
                    "Timestamp": 1652373212,
                    "Date": "Thu May 12 19:33:32 2022",
                    "Log": "starting DB data loading"
                },
                {
                    "Timestamp": 1652373212,
                    "Date": "Thu May 12 19:33:32 2022",
                    "Log": "DB data loading successfully completed"
                },
                {
                    "Timestamp": 1652373212,
                    "Date": "Thu May 12 19:33:32 2022",
                    "Log": "2 destinations loaded (0 discarded)"
                }
            ]
        }

	</programlisting>
	</section>

	<section id="sr_id_events" xreflabel="events">
	<title><varname>[partition_name];events</varname></title>
	<para>
	Destination switching reporting:
	</para>

	<para>
	For reporting events related to the state changes of the
	destinations, the module provides separate identifiers (still
	one per partition).
	Why separate ones? The reports on state changing may be verbose and there
	is the risk of loose/discard important reports on reloads due to the high
	number of logs on state changes;
	</para>
	<para>
	So, each partition will provide the identified "partition_name;events" for
	reporting state changes of destinations, along with the reason
	of the change. This identifiers have a 200 records history before 
	discarding the old ones.
	</para>
	<programlisting  format="linespecific">
        {
            "Name": "default;events",
            "Reports": [
                {
                    "Timestamp": 1652373308,
                    "Date": "Thu May 12 19:35:08 2022",
                    "Log": "DESTINATION &lt;sip:127.0.1.1&gt;, set 1 switched to [inactive] due to negative probing reply\n"
                },
                {
                    "Timestamp": 1652373308,
                    "Date": "Thu May 12 19:35:08 2022",
                    "Log": "DESTINATION &lt;sip:127.0.1.2&gt;, set 1 switched to [inactive] due to negative probing reply\n"
                }
            ]
        },

	</programlisting>
	</section>

	<para>
	For how to access and use the Status/Report information, please see
	<ulink url='>https://www.opensips.org/Documentation/Interface-StatusReport-3-3'>https://www.opensips.org/Documentation/Interface-StatusReport-3-3</ulink>.
	</para>

</section>


	<section>
	<title>Installation and Running</title>
		<section>
		<title>&osips; config file</title>
		<para>
		Next picture displays a sample usage of dispatcher.
		</para>
		<example>
		<title>&osips; config script - sample dispatcher usage</title>
<programlisting format="linespecific">
...
&dispatchercfg;
...
</programlisting>
		</example>
	</section>
	</section>
</chapter>
