Commit 6efa71b9 authored by Andrei Pavel's avatar Andrei Pavel

Cassandra Host Data Source stress test

It is part of the generic_host_data_source_unittest.cc, able to be
implemented for other HDS as well. It executes INSERT statements and
a certain SELECT statement which Cassandra struggles in performance
with since it has to do two queries instead of a join. All statement
executions are timed and repeated on an increasingly number of hosts.
It is placed last and DISABLED_ as you don't want to run this during
a usual make check.
parent 039622a4
......@@ -123,6 +123,7 @@ We have received the following contributions:
- Andrei Pavel, Qualitance
2016-10: Support for DHCPv6 options defined in RFC6603 and RFC7598
2016-12: Cassandra Host Data Source
- Vincent Legout
2016-11: Fixed serveral spelling mistakes
......@@ -131,7 +132,8 @@ Kea uses log4cplus (http://sourceforge.net/projects/log4cplus/) for logging,
Boost (http://www.boost.org/) library for almost everything, and can use Botan
(http://botan.randombit.net/) or OpenSSL (https://www.openssl.org/) for
cryptographic operations. It can also optionally use PostgreSQL
(http://www.postgresql.org/) and/or MySQL (http://www.mysql.com/) as a database.
(http://www.postgresql.org/) and/or MySQL (http://www.mysql.com/) and/or
Cassandra (http://cassandra.apache.org/) as a database.
Kea can use googletest for unit-tests (http://code.google.com/p/googletest/).
......
......@@ -1666,6 +1666,7 @@ AC_CONFIG_FILES([compatcheck/Makefile
src/share/database/scripts/pgsql/upgrade_1.0_to_2.0.sh
src/share/database/scripts/pgsql/upgrade_2.0_to_3.0.sh
src/share/database/scripts/cql/Makefile
src/share/database/scripts/cql/upgrade_1.0_to_2.0.sh
tools/Makefile
tools/path_replacer.sh
])
......
......@@ -72,7 +72,7 @@
<listitem>
<simpara>
<command>lease-init</command> &mdash;
Initializes a new lease database. This is useful during a new
Initializes a new lease database. This is useful during a new
Kea installation. The database is initialized to the
latest version supported by the version of the software being
installed.
......@@ -160,19 +160,19 @@
<para>
<table frame="all" id="backends">
<title>List of available backends</title>
<tgroup cols='2'>
<tgroup cols='5'>
<colspec colname='feature'/>
<colspec colname='memfile'/>
<colspec colname='mysql'/>
<colspec colname='pgsql'/>
<colspec colname='cql'/>
<colspec colname='cql' colwidth='1.5*'/>
<thead>
<row>
<entry>Feature</entry>
<entry>Memfile</entry>
<entry>MySQL</entry>
<entry>PostgreSQL</entry>
<entry>CQL(Cassandra)</entry>
<entry>CQL (Cassandra)</entry>
</row>
</thead>
<tbody>
......@@ -206,7 +206,7 @@
<entry>no</entry>
<entry>yes</entry>
<entry>yes</entry>
<entry>no</entry>
<entry>yes</entry>
</row>
<row>
......@@ -214,7 +214,7 @@
<entry>no</entry>
<entry>yes</entry>
<entry>yes</entry>
<entry>no</entry>
<entry>yes</entry>
</row>
</tbody>
......@@ -409,6 +409,8 @@ $ <userinput>kea-admin lease-upgrade mysql -u <replaceable>database-user</replac
<title>PostgreSQL</title>
<para>
PostgreSQL is able to store leases, host reservations and options
defined on a per host basis.
A PostgreSQL database must be set up if you want Kea to store
lease and other information in PostgreSQL. This step can be
safely ignored if you are using other database backends.
......@@ -590,10 +592,9 @@ $ <userinput>kea-admin lease-upgrade pgsql -u <replaceable>database-user</replac
<para>
Cassandra, or Cassandra Query Language (CQL), is the newest backend
added to Kea. Since it was added recently and has not undergone as much
testing as other backends, it is considered experimental: please use
with caution. The CQL backend is currently able to store leases only. The
ability to store host reservations will likely be added some time in the
future.
testing as other backends, it is considered experimental. Please use
with caution. The Casandra backend is currently able to store leases,
host reservations and options defined on a per host basis.
</para>
<para>
......
......@@ -477,8 +477,7 @@ If a timeout is given though, it should be an integer greater than zero.
purpose, be it lease or hosts information. This arrangement gives the most
flexibility. Kea can be used to keep leases and host reservations
separately, but can also point to the same database. Currently the
supported hosts database types are MySQL and PostgreSQL. The Cassandra
backend does not support host reservations yet.</para>
supported hosts database types are MySQL, PostgreSQL and CQL (Cassandra).</para>
<para>Please note that usage of hosts storage is optional. A user can define
all host reservations in the configuration file. That is the recommended way
......@@ -2973,13 +2972,13 @@ It is merely echoed by the server
with classification using expressions.</para>
</section>
<section id="reservations4-mysql-pgsql">
<title>Storing Host Reservations in MySQL or PostgreSQL</title>
<section id="reservations4-mysql-pgsql-cql">
<title>Storing Host Reservations in MySQL, PostgreSQL or CQL (Cassandra)</title>
<para>
It is possible to store host reservations in MySQL or PostgreSQL database. See
It is possible to store host reservations in MySQL, PostgreSQL or Cassandra. See
<xref linkend="hosts4-storage"/> for information on how to configure Kea to use
reservations stored in MySQL or PostgreSQL. Kea does not provide any dedicated
reservations stored in MySQL, PostgreSQL or Cassandra. Kea does not provide any dedicated
tools for managing reservations in a database. The Kea wiki <ulink
url="http://kea.isc.org/wiki/HostReservationsHowTo" /> provides detailed
information and examples of how reservations can be inserted into the
......@@ -2990,13 +2989,6 @@ It is merely echoed by the server
arbitrarily set to 4096 bytes.</simpara></note>
</section>
<section id="reservations4-cql">
<title>Storing host reservations in CQL (Cassandra)</title>
<para>Kea currently does not support storing reservations in
Cassandra (CQL).</para>
</section>
<section id="reservations4-tuning">
<title>Fine Tuning DHCPv4 Host Reservation</title>
......
......@@ -1156,7 +1156,7 @@ temporarily override a list of interface names and listen on all interfaces.
<row><entry>s46-br</entry><entry>90</entry><entry>ipv6-address</entry><entry>false</entry></row>
<row><entry>s46-dmr</entry><entry>91</entry><entry>ipv6-prefix</entry><entry>false</entry></row>
<row><entry>s46-v4v6bind</entry><entry>92</entry><entry>record (ipv4-address, ipv6-prefix)</entry><entry>false</entry></row>
<row><entry>s46-portparams</entry><entry>93</entry><entry>record(uint8, psid)</entry><entry>false</entry></row>
<row><entry>s46-portparams</entry><entry>93</entry><entry>record (uint8, psid)</entry><entry>false</entry></row>
<row><entry>s46-cont-mape</entry><entry>94</entry><entry>empty</entry><entry>false</entry></row>
<row><entry>s46-cont-mapt</entry><entry>95</entry><entry>empty</entry><entry>false</entry></row>
<row><entry>s46-cont-lw</entry><entry>96</entry><entry>empty</entry><entry>false</entry></row>
......@@ -2908,13 +2908,13 @@ should include options from the isc option space:
with classification using expressions.</para>
</section>
<section id="reservations6-mysql-pgsql">
<title>Storing Host Reservations in MySQL or PostgreSQL</title>
<section id="reservations6-mysql-pgsql-cql">
<title>Storing Host Reservations in MySQL, PostgreSQL or CQL (Cassandra)</title>
<para>
It is possible to store host reservations in MySQL or PostgreSQL. See <xref
linkend="hosts6-storage" /> for information on how to configure Kea to use
reservations stored in MySQL or PostgreSQL. Kea does not provide any dedicated
It is possible to store host reservations in MySQL, PostgreSQL or Cassandra. See
<xref linkend="hosts6-storage" /> for information on how to configure Kea to use
reservations stored in MySQL, PostgreSQL or Cassandra. Kea does not provide any dedicated
tools for managing reservations in a database. The Kea wiki <ulink
url="http://kea.isc.org/wiki/HostReservationsHowTo" /> provides detailed
information and examples of how reservations can be inserted into the
......@@ -2925,12 +2925,6 @@ should include options from the isc option space:
arbitrarily set to 4096 bytes.</simpara></note>
</section>
<section id="reservations6-cql">
<title>Storing Host Reservations in CQL (Cassandra)</title>
<para>Kea currently does not support storing reservations in
Cassandra (CQL).</para>
</section>
<section id="reservations6-tuning">
<title>Fine Tuning DHCPv6 Host Reservation</title>
......
......@@ -18,7 +18,7 @@
mysql_execute() {
QUERY=$1
shift
if [ $# -gt 1 ]; then
if [ $# -ge 1 ]; then
mysql -N -B $* -e "${QUERY}"
retcode=$?
else
......@@ -47,7 +47,7 @@ mysql_version() {
pgsql_execute() {
QUERY=$1
shift
if [ $# -gt 0 ]; then
if [ $# -ge 1 ]; then
echo $QUERY | psql --set ON_ERROR_STOP=1 -A -t -h localhost -q $*
retcode=$?
else
......@@ -71,7 +71,7 @@ pgsql_execute() {
pgsql_execute_script() {
file=$1
shift
if [ $# -gt 0 ]; then
if [ $# -ge 1 ]; then
psql --set ON_ERROR_STOP=1 -A -t -h localhost -q -f $file $*
retcode=$?
else
......@@ -90,8 +90,8 @@ pgsql_version() {
cql_execute() {
query=$1
shift
if [ $# -gt 1 ]; then
cqlsh $* -e "$query"
if [ $# -ge 1 ]; then
cqlsh "$@" -e "$query"
retcode=$?
else
cqlsh -u $db_user -p $db_password -k $db_name -e "$query"
......@@ -109,8 +109,8 @@ cql_execute() {
cql_execute_script() {
file=$1
shift
if [ $# -gt 1 ]; then
cqlsh $* -e "$file"
if [ $# -ge 1 ]; then
cqlsh "$@" -f "$file"
retcode=$?
else
cqlsh -u $db_user -p $db_password -k $db_name -f "$file"
......@@ -126,8 +126,9 @@ cql_execute_script() {
}
cql_version() {
version=`cql_execute "SELECT version, minor FROM schema_version" "$@"`
version=`echo "$version" | grep -A 1 "+" | grep -v "+" | tr -d ' ' | cut -d "|" -f 1-2 --output-delimiter="."`
echo $version
return $?
version=$(cql_execute "SELECT version, minor FROM schema_version" "$@")
error=$?
version=$(echo "$version" | grep -A 1 "+" | grep -v "+" | tr -d ' ' | cut -d "|" -f 1-2 --output-delimiter=".")
echo "$version"
return $error
}
......@@ -203,8 +203,8 @@ pgsql_init() {
cql_init() {
printf "Checking if there is a database initialized already... Please ignore errors.\n"
result=`cql_execute "USE $db_name; DESCRIBE tables;"`
if [ "$result"="<empty>" ]; then
result=$(cql_execute "DESCRIBE tables;")
if [ $(echo "$result" | grep "<empty>" | wc -w) -gt 0 ]; then
printf "Creating and initializing tables using script %s...\n" $scripts_dir/cql/dhcpdb_create.cql
cql_execute_script $scripts_dir/cql/dhcpdb_create.cql
else
......@@ -212,8 +212,8 @@ cql_init() {
exit 2
fi
version=`cql_version`
printf "Lease DB version reported after initialization: $version\n"
version=$(cql_version)
printf "Lease DB version reported after initialization: %s\n" "$version"
exit 0
}
......
......@@ -13,6 +13,7 @@ endif
if HAVE_CQL
SHTESTS += cql_tests.sh
endif
noinst_SCRIPTS = $(SHTESTS)
EXTRA_DIST = dhcpdb_create_1.0.mysql
......
......@@ -44,8 +44,7 @@ cql_lease_init_test() {
assert_eq 0 $? "lease4 table check failed, expected exit code: %d, actual: %d"
# Check lease6 table
cql_execute "SELECT address, duid, valid_lifetime, expire, subnet_id, pref_lifetime, lease_type, iaid, prefix_len, fqdn_fwd, fqdn_rev, hostname,\
state FROM lease6;"
cql_execute "SELECT address, duid, valid_lifetime, expire, subnet_id, pref_lifetime, lease_type, iaid, prefix_len, fqdn_fwd, fqdn_rev, hostname, state FROM lease6;"
assert_eq 0 $? "lease6 table check failed, expected exit code: %d, actual: %d"
# Check lease6_types table
......@@ -83,7 +82,7 @@ cql_lease_version_test() {
# Verfiy that kea-admin lease-version returns the correct version.
version=$($keaadmin lease-version cql -u $db_user -p $db_password -n $db_name)
assert_str_eq "1.0" $version "Expected kea-admin to return %s, returned value was %s"
assert_str_eq "2.0" $version "Expected kea-admin to return %s, returned value was %s"
# Wipe the database.
cql_execute_script $db_scripts_dir/cql/dhcpdb_drop.cql
......@@ -151,20 +150,20 @@ cql_lease4_dump_test() {
# 1430694930 corresponds to 2015-04-04 01:15:30
# 1433464245 corresponds to 2015-05-05 02:30:45
# 1436173267 corresponds to 2015-06-06 11:01:07
insert_sql="\
insert into lease4(address, hwaddr, client_id, valid_lifetime, expire, subnet_id,\
insert_cql="\
INSERT INTO lease4(address, hwaddr, client_id, valid_lifetime, expire, subnet_id,\
fqdn_fwd, fqdn_rev, hostname, state)\
values(-1073741302,textAsBlob('20'),textAsBlob('30'),40,1430694930,50,true,true,\
VALUES(-1073741302,textAsBlob('20'),textAsBlob('30'),40,1430694930,50,true,true,\
'one.example.com', 0);\
insert into lease4(address, hwaddr, client_id, valid_lifetime, expire, subnet_id,\
INSERT INTO lease4(address, hwaddr, client_id, valid_lifetime, expire, subnet_id,\
fqdn_fwd, fqdn_rev, hostname, state)\
values(-1073741301,NULL,textAsBlob('123'),40,1433464245,50,true,true,'', 1);\
insert into lease4(address, hwaddr, client_id, valid_lifetime, expire, subnet_id,\
VALUES(-1073741301,NULL,textAsBlob('123'),40,1433464245,50,true,true,'', 1);\
INSERT INTO lease4(address, hwaddr, client_id, valid_lifetime, expire, subnet_id,\
fqdn_fwd, fqdn_rev, hostname, state)\
values(-1073741300,textAsBlob('22'),NULL,40,1436173267,50,true,true,\
VALUES(-1073741300,textAsBlob('22'),NULL,40,1436173267,50,true,true,\
'three.example.com', 2);"
cql_execute "$insert_sql"
cql_execute "$insert_cql"
assert_eq 0 $? "insert into lease4 failed, expected exit code %d, actual %d"
# Dump lease4 to output_file.
......@@ -220,24 +219,24 @@ cql_lease6_dump_test() {
# 1430694930 corresponds to 2015-04-04 01:15:30
# 1433464245 corresponds to 2015-05-05 02:30:45
# 1436173267 corresponds to 2015-06-06 11:01:07
insert_sql="\
insert into lease6(address, duid, valid_lifetime, expire, subnet_id,\
insert_cql="\
INSERT INTO lease6(address, duid, valid_lifetime, expire, subnet_id,\
pref_lifetime, lease_type, iaid, prefix_len, fqdn_fwd, fqdn_rev, hostname,\
hwaddr, hwtype, hwaddr_source, state)\
values('2001:db8::10',textAsBlob('20'),30,1430694930,40,50,1,60,70,true,true,\
VALUES('2001:db8::10',textAsBlob('20'),30,1430694930,40,50,1,60,70,true,true,\
'one.example.com',textAsBlob('80'),90,16,0);\
insert into lease6(address, duid, valid_lifetime, expire, subnet_id,\
INSERT INTO lease6(address, duid, valid_lifetime, expire, subnet_id,\
pref_lifetime, lease_type, iaid, prefix_len, fqdn_fwd, fqdn_rev, hostname,\
hwaddr, hwtype, hwaddr_source, state)\
values('2001:db8::11',NULL,30,1433464245,40,50,1,60,70,true,true,\
VALUES('2001:db8::11',NULL,30,1433464245,40,50,1,60,70,true,true,\
'',textAsBlob('80'),90,1,1);\
insert into lease6(address, duid, valid_lifetime, expire, subnet_id,\
INSERT INTO lease6(address, duid, valid_lifetime, expire, subnet_id,\
pref_lifetime, lease_type, iaid, prefix_len, fqdn_fwd, fqdn_rev, hostname,\
hwaddr, hwtype, hwaddr_source, state)\
values('2001:db8::12',textAsBlob('21'),30,1436173267,40,50,1,60,70,true,true,\
VALUES('2001:db8::12',textAsBlob('21'),30,1436173267,40,50,1,60,70,true,true,\
'three.example.com',textAsBlob('80'),90,4,2);"
cql_execute "$insert_sql"
cql_execute "$insert_cql"
assert_eq 0 $? "insert into lease6 failed, expected exit code %d, actual %d"
# Dump lease4 to output_file.
......
......@@ -38,11 +38,14 @@
-- is initialized to 1.0, then upgraded to 2.0 etc. This may be somewhat
-- sub-optimal, but it ensues consistency with upgrade scripts. (It is much
-- easier to maintain init and upgrade scripts if they look the same).
-- Since initialization is done only once, it's perfromance is not an issue.
-- Since initialization is done only once, it's performance is not an issue.
-- This line starts database initialization to 1.0.
-- Holds the IPv4 leases.
-- -----------------------------------------------------
-- Table `lease4`
-- -----------------------------------------------------
CREATE TABLE lease4 (
address int,
hwaddr blob,
......@@ -61,11 +64,15 @@ CREATE TABLE lease4 (
CREATE INDEX lease4index1 ON lease4 (client_id);
CREATE INDEX lease4index2 ON lease4 (subnet_id);
CREATE INDEX lease4index3 ON lease4 (hwaddr);
CREATE INDEX lease4index4 ON lease4 (state);
CREATE INDEX lease4index4 ON lease4 (expire);
CREATE INDEX lease4index5 ON lease4 (state);
-- Holds the IPv6 leases.
-- N.B. The use of a VARCHAR for the address is temporary for development:
-- it will eventually be replaced by BINARY(16).
-- -----------------------------------------------------
-- Table `lease6`
-- -----------------------------------------------------
CREATE TABLE lease6 (
address varchar,
duid blob,
......@@ -91,13 +98,17 @@ CREATE INDEX lease6index1 ON lease6 (lease_type);
CREATE INDEX lease6index2 ON lease6 (duid);
CREATE INDEX lease6index3 ON lease6 (iaid);
CREATE INDEX lease6index4 ON lease6 (subnet_id);
CREATE INDEX lease6index5 ON lease6 (state);
CREATE INDEX lease6index5 ON lease6 (expire);
CREATE INDEX lease6index6 ON lease6 (state);
-- ... and a definition of lease6 types. This table is a convenience for
-- users of the database - if they want to view the lease table and use the
-- type names, they can join this table with the lease6 table.
-- Make sure those values match Lease6::LeaseType enum (see src/bin/dhcpsrv/
-- lease_mgr.h)
-- -----------------------------------------------------
-- Table `lease6_types`
-- -----------------------------------------------------
CREATE TABLE lease6_types (
lease_type int, -- Lease type code.
name varchar, -- Name of the lease type
......@@ -107,13 +118,15 @@ INSERT INTO lease6_types (lease_type, name) VALUES (0, 'IA_NA'); -- Non-tempor
INSERT INTO lease6_types (lease_type, name) VALUES (1, 'IA_TA'); -- Temporary v6 addresses
INSERT INTO lease6_types (lease_type, name) VALUES (2, 'IA_PD'); -- Prefix delegations
-- Kea keeps track of the hardware/MAC address source, i.e. how the address
-- was obtained. Depending on the technique and your network topology, it may
-- be more or less trustworthy. This table is a convenience for
-- users of the database - if they want to view the lease table and use the
-- type names, they can join this table with the lease6 table. For details,
-- see constants defined in src/lib/dhcp/dhcp/pkt.h for detailed explanation.
-- -----------------------------------------------------
-- Table `lease_hwaddr_source`
-- -----------------------------------------------------
CREATE TABLE lease_hwaddr_source (
hwaddr_source int,
name varchar,
......@@ -141,47 +154,12 @@ INSERT INTO lease_hwaddr_source (hwaddr_source, name) VALUES (32, 'HWADDR_SOURCE
-- Hardware address extracted from docsis options
INSERT INTO lease_hwaddr_source (hwaddr_source, name) VALUES (64, 'HWADDR_SOURCE_DOCSIS_CMTS');
-- -----------------------------------------------------
-- Table `dhcp4_options`
-- -----------------------------------------------------
CREATE TABLE dhcp4_options (
option_id int,
code int,
value blob,
formatted_value varchar,
space varchar,
persistent int,
dhcp_client_class varchar,
dhcp4_subnet_id int,
host_id int,
PRIMARY KEY (option_id)
);
-- Create search indexes for dhcp4_options table
CREATE INDEX dhcp4_optionsindex1 ON dhcp4_options (host_id);
-- -----------------------------------------------------
-- Table `dhcp6_options`
-- -----------------------------------------------------
CREATE TABLE dhcp6_options (
option_id int,
code int,
value blob,
formatted_value varchar,
space varchar,
persistent int,
dhcp_client_class varchar,
dhcp6_subnet_id int,
host_id int,
PRIMARY KEY (option_id)
);
-- Create search indexes for dhcp6_options table
CREATE INDEX dhcp6_optionsindex1 ON dhcp6_options (host_id);
-- Create table holding mapping of the lease states to their names.
-- This is not used in queries from the DHCP server but rather in
-- direct queries from the lease database management tools.
-- -----------------------------------------------------
-- Table `lease_state`
-- -----------------------------------------------------
CREATE TABLE lease_state (
state int,
name varchar,
......@@ -199,9 +177,15 @@ INSERT INTO lease_state (state, name) VALUES (2, 'expired-reclaimed');
-- first column is called "version" and not "major".
-- Note: This MUST be kept in step with src/share/database/scripts/cassandra/dhcpdb_create.cql,
-- which defines the schema for the unit tests.
-- -----------------------------------------------------
-- Table `schema_version`
-- -----------------------------------------------------
CREATE TABLE schema_version (
version int,
minor int,
PRIMARY KEY (version)
);
INSERT INTO schema_version (version, minor) VALUES (1, 0);
-- This line concludes database initalization to version 1.0.
......@@ -124,6 +124,7 @@ libkea_dhcpsrv_la_SOURCES += logging.cc logging.h
libkea_dhcpsrv_la_SOURCES += logging_info.cc logging_info.h
libkea_dhcpsrv_la_SOURCES += memfile_lease_mgr.cc memfile_lease_mgr.h
libkea_dhcpsrv_la_SOURCES += memfile_lease_storage.h
libkea_dhcpsrv_la_SOURCES += sql_common.h
if HAVE_MYSQL
libkea_dhcpsrv_la_SOURCES += mysql_lease_mgr.cc mysql_lease_mgr.h
......@@ -139,10 +140,14 @@ libkea_dhcpsrv_la_SOURCES += pgsql_exchange.cc pgsql_exchange.h
libkea_dhcpsrv_la_SOURCES += pgsql_host_data_source.cc pgsql_host_data_source.h
libkea_dhcpsrv_la_SOURCES += pgsql_lease_mgr.cc pgsql_lease_mgr.h
endif
if HAVE_CQL
libkea_dhcpsrv_la_SOURCES += cql_lease_mgr.cc cql_lease_mgr.h
libkea_dhcpsrv_la_SOURCES += cql_connection.cc cql_connection.h
libkea_dhcpsrv_la_SOURCES += cql_exchange.cc cql_exchange.h
libkea_dhcpsrv_la_SOURCES += cql_host_data_source.cc cql_host_data_source.h
libkea_dhcpsrv_la_SOURCES += cql_lease_mgr.cc cql_lease_mgr.h
endif
libkea_dhcpsrv_la_SOURCES += pool.cc pool.h
libkea_dhcpsrv_la_SOURCES += srv_config.cc srv_config.h
libkea_dhcpsrv_la_SOURCES += subnet.cc subnet.h
......@@ -236,5 +241,3 @@ libkea_dhcpsrv_include_HEADERS = \
install-data-local:
$(mkinstalldirs) $(DESTDIR)$(dhcp_data_dir)
......@@ -164,9 +164,9 @@ CfgOption::mergeInternal(const OptionSpaceContainer<OptionContainer,
// If there is no such option in the destination container,
// add one.
if (std::distance(range.first, range.second) == 0) {
dest_container.addItem(OptionDescriptor(src_opt->option_,
src_opt->persistent_),
*it);
dest_container.addItem(OptionDescriptor(
src_opt->option_, src_opt->persistent_,
src_opt->formatted_value_), *it);
}
}
}
......
......@@ -14,22 +14,27 @@
// See the License for the specific language governing permissions and
// limitations under the License.
#include <config.h>
#include <dhcpsrv/cql_connection.h>
#include <string>
#include <dhcpsrv/cql_exchange.h>
#include <boost/shared_ptr.hpp>
using namespace std;
namespace isc {
namespace dhcp {
CqlConnection::CqlConnection(const ParameterMap& parameters) :
DatabaseConnection(parameters), cluster_(NULL), session_(NULL),
tagged_statements_(NULL) {
CqlConnection::CqlConnection(const ParameterMap& parameters)
: DatabaseConnection(parameters), cluster_(NULL), session_(NULL),
force_consistency_(true), consistency_(CASS_CONSISTENCY_QUORUM),
tagged_statements_(NULL) {
}
CqlConnection::~CqlConnection() {
// Free up the prepared statements, ignoring errors.
// Session and connection resources are deallocated.
// Free up the prepared statements, ignoring errors. Session and connection
// resources are deallocated.
CassError rc = CASS_OK;
std::string error;
......@@ -43,7 +48,8 @@ CqlConnection::~CqlConnection() {
if (session_) {
CassFuture* close_future = cass_session_close(session_);
cass_future_wait(close_future);
checkStatementError(error, close_future, "could not close connection to DB");
checkStatementError(error, close_future, "could not close connection to"
" DB");
rc = cass_future_error_code(close_future);
cass_future_free(close_future);
cass_session_free(session_);
......@@ -55,10 +61,9 @@ CqlConnection::~CqlConnection() {
cluster_ = NULL;
}
// We're closing the connection anyway. Let's not throw at this
// stage
if (rc != CASS_OK) {
isc_throw(DbOpenError, error);
// We're closing the connection anyway. Let's not throw at this stage.
LOG_ERROR(dhcpsrv_logger, DHCPSRV_CQL_DEALLOC_ERROR).arg(error);
}
}
......@@ -67,25 +72,25 @@ CqlConnection::openDatabase() {
CassError rc;
// Set up the values of the parameters
const char* contact_points = "127.0.0.1";
string scontact_points;
std::string scontact_points;
try {
scontact_points = getParameter("contact_points");
contact_points = scontact_points.c_str();
} catch (...) {
// No host. Fine, we'll use "localhost".
// No host. Fine, we'll use "127.0.0.1".
}
const char* port = NULL;
string sport;
std::string sport;
try {
sport = getParameter("port");
port = sport.c_str();
} catch (...) {
// No port. Fine, we'll use "default".
// No port. Fine, we'll use the default "9042".
}
const char* user = NULL;
string suser;
std::string suser;
try {
suser = getParameter("user");
user = suser.c_str();
......@@ -94,7 +99,7 @@ CqlConnection::openDatabase() {
}
const char* password = NULL;
string spassword;
std::string spassword;
try {
spassword = getParameter("password");
password = spassword.c_str();
......@@ -103,36 +108,170 @@ CqlConnection::openDatabase() {
}
const char* keyspace = "keatest";
string skeyspace;
std::string skeyspace;
try {
skeyspace = getParameter("keyspace");
keyspace = skeyspace.c_str();
} catch (...) {
// No keyspace name. Fine, we'll use default "keatest".
// No keyspace name. Fine, we'll use "keatest".
}
const char* reconnect_wait_time = NULL;
std::string sreconnect_wait_time;
try {
sreconnect_wait_time = getParameter("reconnect-wait-time");
reconnect_wait_time = sreconnect_wait_time.c_str();
} catch (...) {
// No reconnect wait time. Fine, we'll use the default "2000".
}
const char* connect_timeout = NULL;
std::string sconnect_timeout;
try {
sconnect_timeout = getParameter("connect-timeout");
connect_timeout = sconnect_timeout.c_str();
} catch (...) {
// No connect timeout. Fine, we'll use the default "5000".
}
const char* request_timeout = NULL;
std::string srequest_timeout;
try {
srequest_timeout = getParameter("request-timeout");
request_timeout = srequest_timeout.c_str();
} catch (...) {
// No request timeout. Fine, we'll use the default "12000".
}
const char* tcp_keepalive = NULL;
std::string stcp_keepalive;
try {
stcp_keepalive = getParameter("tcp-keepalive");
tcp_keepalive = stcp_keepalive.c_str();
} catch (...) {
// No tcp-keepalive. Fine, we'll not use TCP keepalive.
}
std::string stcp_nodelay;
try {
stcp_nodelay = getParameter("tcp-nodelay");
} catch (...) {
// No tcp-nodelay. Fine, we'll use the default false.
}
cluster_ = cass_cluster_new();
cass_cluster_set_contact_points(cluster_, contact_points);
if (user != NULL && password != NULL) {
if (user && password) {
cass_cluster_set_credentials(cluster_, user, password);
}
if (port != NULL) {
if (port) {
int port_number;
try {
port_number = boost::lexical_cast<int>(port);
} catch (const std::exception& ex) {
isc_throw(DbOperationError, "Invalid int data: " << port
<< " : " << ex.what());
if (port_number < 1 || port_number > 65535) {
isc_throw(
DbOperationError,
"Port outside of range, expected 1-65535, instead got "
<< port);
}
} catch (const boost::bad_lexical_cast& ex) {
isc_throw(DbOperationError,
"Invalid port, castable to int expected, instead got \""
<< port << "\", " << ex.what());
}
cass_cluster_set_port(cluster_, port_number);
}
if (reconnect_wait_time) {
int reconnect_wait_time_number;
try {
reconnect_wait_time_number =
boost::lexical_cast<int>(reconnect_wait_time);
if (reconnect_wait_time_number < 0) {
isc_throw(DbOperationError,
"Invalid reconnect wait time, positive number "
"expected, instead got "