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

<chapter>
	
	<title>&adminguide;</title>
	
	<section id="overview" xreflabel="Overview">
	<title>Overview</title>
	<para>
		This module is an implementation of a cache system designed to work with
		Cassandra servers.
		It uses the Key-Value interface exported from the core.
	</para>
	<para>
		The underlying client library is compatible with Cassandra versions 2.1+.
	</para>
	</section>


	<section>
	<title>Advantages</title>
	<para>
		<itemizedlist>
			<listitem>
			<para>
				<emphasis>memory costs are no longer on the server
				</emphasis>
			</para>
			</listitem>

			<listitem>
			<para>
				<emphasis>many servers can be used inside a cluster, so the memory
				is virtually unlimited</emphasis>
			</para>
			</listitem>

			<listitem>
			<para>
				<emphasis>the cache is 100% persistent. A restart
					of OpenSIPS server will not affect the DB. The Cassandra DB is also
				persistent so it can also be restarted without loss of information.</emphasis>
			</para>
			</listitem>

			<listitem>
			<para>
				<emphasis>Cassandra is an open-source project so
				it can be used to exchange data
				 with various other applications</emphasis>
			</para>
			</listitem>

			<listitem>
			<para>
				<emphasis>By creating a Cassandra Cluster, multiple OpenSIPS
				instances can easily share key-value information</emphasis>
			</para>
			</listitem>

		</itemizedlist>
	</para>
	<para>
	</para>
	</section>

	<section>
	<title>Limitations</title>
	
		
		<para>
			<itemizedlist>
			<listitem>
			<para>
			<emphasis>
		keys (in key:value pairs) may not contain spaces or control characters
		</emphasis>
			</para>
			</listitem>

		</itemizedlist>
		</para>
	</section>

	<section id="dependencies" xreflabel="Dependencies">
	<title>Dependencies</title>
	<section>
		<title>&osips; Modules</title>
		<para>
		None.
		</para>
	</section>
	
	<section>
		<title>External Libraries or Applications</title>
		<para>
		The following libraries or applications must be installed before running
		&osips; with this module loaded:
		</para>
			<itemizedlist>
			<listitem>
			<para> <emphasis>libuv</emphasis></para>
			</listitem>
			<listitem>
			<para><emphasis>cassandra-cpp-driver</emphasis></para>
			</listitem>
			</itemizedlist>
			<para>
				The DataStax C/C++ driver for Cassandra and the libuv dependency
				can be downloaded from: <ulink url="http://downloads.datastax.com/cpp-driver/"/>.
			</para>
	</section>
	</section>
	
	<section id="exported_parameters" xreflabel="Exported Parameters">
		<title>Exported Parameters</title>
		<section id="param_cachedb_url" xreflabel="cachedb_url">
		<title><varname>cachedb_url</varname> (string)</title>
		<para>
			The urls of the server groups that OpenSIPS will connect to in order
			to use the from script cache_store,cache_fetch, etc operations.
			It can be set more than one time.
			The prefix part of the URL will be the identifier that will be used
			from the script.
		</para>
		<para>
		Cassandra does not support regular columns in a table that contains any
		counter columns so in order to use the add()/sub()/get_counter() methods
		in the Key-Value Interface you can specify an extra table reserved
		only for counters.
		</para>
		<para>
		The database part of the URL needs to be in the format <emphasis>
		Keyspace.Table[.CountersTable]</emphasis>.
		</para>

		<example>
		<title>Set <varname>cachedb_url</varname> parameter</title>
		<programlisting format="linespecific">
...
modparam("cachedb_cassandra", "cachedb_url",
	"cassandra:group1://localhost:9042/keyspace1.users.counters");

# Defining multiple contact points for a Cassandra cluster
modparam("cachedb_cassandra", "cachedb_url",
	"cassandra:cluster1://10.0.0.10,10.0.0.15/keyspace2.keys.counters");
...
	</programlisting>
		</example>
		
		<example>
		<title>Use Cassandra servers </title>
		<programlisting format="linespecific">
...
cache_store("cassandra:group1","key","$ru value");
cache_fetch("cassandra:cluster1","key",$avp(10));
cache_remove("cassandra:cluster1","key");
...
	</programlisting>
		</example>
	</section>
	
		<section id="param_connect_timeout" xreflabel="connect_timeout">
		<title><varname>connect_timeout</varname> (int)</title>
		<para>
			The timeout in ms that will be triggered in case a connection attempt fails.
		</para>
		<para>
		<emphasis>Default value is <quote>5000</quote>.</emphasis>
		</para>
		
		<example>
		<title>Set <varname>connect_timeout</varname> parameter</title>
		<programlisting format="linespecific">
...
modparam("cachedb_cassandra", "connect_timeout",1000);
...
	</programlisting>
		</example>
		
	</section>

		<section id="param_query_timeout" xreflabel="query_timeout">
		<title><varname>query_timeout</varname> (int)</title>
		<para>
			The timeout in ms that will be triggered in case a Cassandra query takes too long.
		</para>
		<para>
		<emphasis>Default value is <quote>5000</quote>.</emphasis>
		</para>
		<example>
		<title>Set <varname>query_timeout</varname> parameter</title>
		<programlisting format="linespecific">
...
modparam("cachedb_cassandra", "query_timeout",1000);
...
	</programlisting>
		</example>
		
	</section>

		<section id="param_wr_consistency_level" xreflabel="wr_consistency_level">
		<title><varname>wr_consistency_level</varname> (int)</title>
		<para>
			The consistency level desired for write operations.
			Options are :
		<itemizedlist>
		<listitem>
			<para><emphasis>all</emphasis> - A write must be written to the commit log and memtable on all replica nodes in the cluster for that partition.
			</para>
		</listitem>
		<listitem>
			<para><emphasis>each_quorum</emphasis> - Strong consistency. A write must be written to the commit log and memtable on a quorum of replica nodes in each datacenter.
			</para>
		</listitem>
		<listitem>
			<para><emphasis>quorum</emphasis> - A write must be written to the commit log and memtable on a quorum of replica nodes across all datacenters.
			</para>
		</listitem>
		<listitem>
			<para><emphasis>local_quorum</emphasis> - Strong consistency. A write must be written to the commit log and memtable on a quorum of replica nodes in the same datacenter as the coordinator. Avoids latency of inter-datacenter communication.
			</para>
		</listitem>
		<listitem>
			<para><emphasis>one</emphasis> - A write must be written to the commit log and memtable of at least one replica node.
			</para>
		</listitem>
		<listitem>
			<para><emphasis>two</emphasis> - A write must be written to the commit log and memtable of at least two replica node. 
			</para>
		</listitem>
		<listitem>
			<para><emphasis>three</emphasis> - A write must be written to the commit log and memtable of at least three replica node.
			</para>
		</listitem>
		<listitem>
			<para><emphasis>local_one</emphasis> - A write must be sent to, and successfully acknowledged by, at least one replica node in the local datacenter.
			</para>
		</listitem>
		<listitem>
			<para><emphasis>any</emphasis> - A write must be written to at least one node. If all replica nodes for the given partition key are down, the write can still succeed after a hinted handoff has been written. If all replica nodes are down at write time, an ANY write is not readable until the replica nodes for that partition have recovered.
			</para>
		</listitem>
		</itemizedlist>

		Default value is <emphasis>one</emphasis>.
		</para>
		
		<example>
		<title>Set <varname>wr_consistency_level</varname> parameter</title>
		<programlisting format="linespecific">
...
modparam("cachedb_cassandra", "wr_consistency_level", "each_quorum");
...
	</programlisting>
		</example>
		
	</section>

		<section id="param_rd_consistency_level" xreflabel="rd_consistency_level">
		<title><varname>rd_consistency_level</varname> (int)</title>
		<para>
			The consistency level desired for write operations.
			Options are :
		<itemizedlist>
		<listitem>
			<para><emphasis>all</emphasis> - Returns the record after all replicas have responded. The read operation will fail if a replica does not respond.
			</para>
		</listitem>
		<listitem>
			<para><emphasis>quorum</emphasis> - Returns the record after a quorum of replicas from all datacenters has responded.
			</para>
		</listitem>
		<listitem>
			<para><emphasis>local_quorum</emphasis> - Returns the record after a quorum of replicas in the current datacenter as the coordinator has reported. Avoids latency of inter-datacenter communication.
			</para>
		</listitem>
		<listitem>
			<para><emphasis>one</emphasis> - Returns a response from the closest replica, as determined by the snitch. By default, a read repair runs in the background to make the other replicas consistent.
			</para>
		</listitem>
		<listitem>
			<para><emphasis>two</emphasis> - Returns the most recent data from two of the closest replicas.
			</para>
		</listitem>
		<listitem>
			<para><emphasis>three</emphasis> - Returns the most recent data from three of the closest replicas.
			</para>
		</listitem>
		<listitem>
			<para><emphasis>local_one</emphasis> - Returns a response from the closest replica in the local datacenter.
			</para>
		</listitem>
		<listitem>
			<para><emphasis>serial</emphasis> - Allows reading the current (and possibly uncommitted) state of data without proposing a new addition or update. If a SERIAL read finds an uncommitted transaction in progress, it will commit the transaction as part of the read. Similar to QUORUM.
			</para>
		</listitem>
		<listitem>
			<para><emphasis>local_serial</emphasis> - Same as SERIAL, but confined to the datacenter. Similar to LOCAL_QUORUM.
			</para>
		</listitem>
		</itemizedlist>

		Default value is <emphasis>one</emphasis>.
		</para>
		
		<example>
		<title>Set <varname>rd_consistency_level</varname> parameter</title>
		<programlisting format="linespecific">
...
modparam("cachedb_cassandra", "rd_consistency_level", "quorum");
...
	</programlisting>
		</example>
		
	</section>

		<section id="param_exec_threshold" xreflabel="exec_threshold">
		<title><varname>exec_threshold</varname> (int)</title>
		<para>
			A cassandra cache query that lasts more than this threshold will
			trigger a warning message to the log.
		</para>
		<para>
			This value, if set, only makes sense to be lower than the
			<xref linkend="param_query_timeout"/> since any query taking longer
			than that value will be dropped anyway.
		</para>
		<para>
		<emphasis>Default value is <quote>0 ( unlimited - no warnings )</quote>.
		</emphasis>
		</para>
		<example>
		<title>Set <varname>exec_threshold</varname> parameter</title>
		<programlisting format="linespecific">
...
modparam("cachedb_cassandra", "exec_threshold", 100000)
...
	</programlisting>
		</example>
	</section>
</section>

	<section id="exported_functions" xreflabel="exported_functions">
		<title>Exported Functions</title>
		<para>The module does not export functions to be used
		in configuration script.</para>
	</section>

	<section>
	<title>Table Schema</title>
	<para>
		The table required for supporting the cache_store()/cache_fetch()/cache_remove()
		functions of the Key-Value interface needs to have at least the following columns:
		<itemizedlist>
		<listitem>
		<para><emphasis>opensipskey</emphasis> - as the primary key with type "text"</para>
		</listitem>
		<listitem>
		<para><emphasis>opensipsval</emphasis> - with type "text"</para>
		</listitem>
		</itemizedlist>
	</para>
	<para>
		The table required for supporting the cache_add()/cache_sub()/cache_counter_fetch()
		functions of the Key-Value interface needs to have at least the following columns:
		<itemizedlist>
		<listitem>
		<para><emphasis>opensipskey</emphasis> - as the primary key with type "text"</para>
		</listitem>
		<listitem>
		<para><emphasis>opensipsval</emphasis> - with type "counter"</para>
		</listitem>
		</itemizedlist>
	</para>
	</section>

</chapter>

