return $retcode
}
+cql_execute_script() {
+ file=$1
+ shift
+ if [ $# -gt 1 ]; then
+ cqlsh $* -e "$file"
+ retcode=$?
+ else
+ cqlsh -u $db_user -p $db_password -k $db_name -f "$file"
+ retcode=$?
+ fi
+
+ if [ $retcode -ne 0 ]; then
+ printf "cqlsh returned with exit status $retcode\n"
+ exit $retcode
+ fi
+
+ return $retcode
+}
+
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="."`
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
- printf "Tables are already created.\n"
+ log_error "Expected empty database $db_name, but the following tables are present \n$result. Aborting."
+ exit 2
fi
version=`cql_version`
# Fetch the correct SQL text. Note this function will exit
# if it fails.
- get_dump_query $version
+
+ select_where_clause=""
+ if [ $dump_type -eq 4 ]; then
+ dump_qry="SELECT address,hwaddr,client_id,valid_lifetime,expire,subnet_id,fqdn_fwd,fqdn_rev,hostname,state FROM keatest.lease4"
+ select_where_clause=" WHERE address = 0" # invalid address
+ elif [ $dump_type -eq 6 ]; then
+ dump_qry="SELECT address,duid,valid_lifetime,expire,subnet_id,pref_lifetime,lease_type,iaid,prefix_len,fqdn_fwd,fqdn_rev,hostname,hwaddr,hwtype,hwaddr_source,state FROM keatest.lease6"
+ select_where_clause=" WHERE address = ::" # invalid address
+ fi
# Make sure they specified a file
if [ "$dump_file" = "" ]; then
log_error "you must specify an output file for lease-dump"
usage
exit 1
-
fi
# If output file exists, notify user, allow them a chance to bail
check_file_overwrite $dump_file
- # Check the temp file too
- tmp_file="$dump_file.tmp"
- check_file_overwrite $tmp_file
-
- # Run the sql to output tab-delimited lease data to a temp file.
- # By using a temp file we can check for MySQL errors before using
- # 'tr' to translate tabs to commas. We do not use MySQL's output
- # to file as that requires linux superuser privileges to execute
- # the select.
- cql_execute "${dump_qry}" > $tmp_file
- retcode=$?
- if [ $retcode -ne 0 ]; then
+ cql_execute "${dump_qry}${select_where_clause}" | head -n 2 | tail -n 1 | sed -e 's/\s*//g' | sed -e 's/|/,/g' > $dump_file
+ if [ $? -ne 0 ]; then
log_error "lease-dump: cql_execute failed, exit code $retcode";
exit 1
fi
- # Now translate tabs to commas.
- cat $tmp_file | tr '\t' ',' >$dump_file
+ cql_execute "${dump_qry}" | tail -n +4 | head -n -2 | sed -e 's/\s*//g' | sed -e 's/|/,/g' | sort -r >> $dump_file
if [ $? -ne 0 ]; then
- log_error "lease-dump: reformatting failed";
+ log_error "lease-dump: cql_execute failed, exit code $retcode";
exit 1
fi
- # delete the tmp file on success
- rm $tmp_file
echo lease$dump_type successfully dumped to $dump_file
exit 0
}
# Set location of the kea-admin.
keaadmin=@abs_top_builddir@/src/bin/admin/kea-admin
-cql_init_test() {
+cql_lease_init_test() {
test_start "cql.init"
# Wipe the database.
cql_execute "SELECT state, name FROM lease_state;"
assert_eq 0 $? "lease_state table check failed, expected exit code: %d, actual: %d"
- # Trying to create it again should fail. This verifies the db present
+ # Trying to create it again should fail. This verifies the db present
# check
echo ""
echo "Making sure keyspace creation fails the second time..."
test_finish 0
}
-cql_version_test() {
+cql_lease_version_test() {
test_start "cql.version"
# Wipe the database.
cql_execute_script $db_scripts_dir/cql/dhcpdb_drop.cql
assert_eq 0 $? "drop table query failed, exit code %d, expected %d"
- # Create the database
+ # Create the database.
$keaadmin lease-init cql -u $db_user -p $db_password -n $db_name -d $db_scripts_dir
assert_eq 0 $? "kea-admin lease-init cql failed, expected exit code: %d, actual: %d"
- # Verfiy that kea-admin lease-version returns the correct version
+ # 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"
test_finish 0
}
-cql_init_test
-cql_version_test
+cql_lease4_dump_test() {
+ test_start "cql.lease4_dump_test"
+
+ test_dir="@abs_top_srcdir@/src/bin/admin/tests"
+ output_dir="@abs_top_builddir@/src/bin/admin/tests"
+ script_dir="@abs_top_srcdir@/src/bin/admin/scripts"
+
+ output_file="$output_dir/data/cql.lease4_dump_test.output.csv"
+ tmp_file="$output_file.tmp"
+
+ ref_file="$test_dir/data/cql.lease4_dump_test.reference.csv"
+
+ # Wipe out any residuals from prior failed runs.
+ if [ -e $output_file ]
+ then
+ rm $output_file
+ fi
+
+ if [ -e $tmp_file ]
+ then
+ rm $tmp_file
+ fi
+
+ # Wipe the database.
+ cql_execute_script $db_scripts_dir/cql/dhcpdb_drop.cql
+ assert_eq 0 $? "drop table query failed, exit code %d, expected %d"
+
+ # Create the database
+ $keaadmin lease-init cql -u $db_user -p $db_password -n $db_name -d $db_scripts_dir
+ assert_eq 0 $? "kea-admin lease-init cql failed, expected exit code: %d, actual: %d"
+
+ # Insert the reference record.
+ # -1073741302 corresponds to 192.0.2.10
+ # -1073741301 corresponds to 192.0.2.11
+ # -1073741300 corresponds to 192.0.2.12
+ # 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,\
+ fqdn_fwd, fqdn_rev, hostname, state)\
+ 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,\
+ 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,\
+ fqdn_fwd, fqdn_rev, hostname, state)\
+ values(-1073741300,textAsBlob('22'),NULL,40,1436173267,50,true,true,\
+ 'three.example.com', 2);"
+
+ cql_execute "$insert_sql"
+ assert_eq 0 $? "insert into lease4 failed, expected exit code %d, actual %d"
+
+ # Dump lease4 to output_file.
+ $keaadmin lease-dump cql -4 -u $db_user -p $db_password -n $db_name -d $db_scripts_dir -o $output_file
+ assert_eq 0 $? "kea-admin lease-dump -4 failed, expected exit code %d, actual %d"
+
+ # Compare the dump output to reference file, they should be identical.
+ cmp -s $output_file $ref_file
+ assert_eq 0 $? "dump file does not match reference file, expected exit code %d, actual %d"
+
+ # remove the output file.
+ rm $output_file
+
+ # Wipe the database.
+ cql_execute_script $db_scripts_dir/cql/dhcpdb_drop.cql
+ assert_eq 0 $? "drop table query failed, exit code %d, expected %d"
+
+ test_finish 0
+}
+
+cql_lease6_dump_test() {
+ test_start "cql.lease6_dump_test"
+
+ test_dir="@abs_top_srcdir@/src/bin/admin/tests"
+ output_dir="@abs_top_builddir@/src/bin/admin/tests"
+ script_dir="@abs_top_srcdir@/src/bin/admin/scripts"
+
+ output_file="$output_dir/data/cql.lease6_dump_test.output.csv"
+ tmp_file="$output_file.tmp"
+
+ ref_file="$test_dir/data/cql.lease6_dump_test.reference.csv"
+
+ # Wipe out any residuals from prior failed runs.
+ if [ -e $output_file ]
+ then
+ rm $output_file
+ fi
+
+ if [ -e $tmp_file ]
+ then
+ rm $tmp_file
+ fi
+
+ # Wipe the database.
+ cql_execute_script $db_scripts_dir/cql/dhcpdb_drop.cql
+ assert_eq 0 $? "drop table query failed, exit code %d, expected %d"
+
+ # Create the database.
+ $keaadmin lease-init cql -u $db_user -p $db_password -n $db_name -d $db_scripts_dir
+ assert_eq 0 $? "could not create database, expected exit code %d, actual %d"
+
+ # Insert the reference record.
+ # 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,\
+ 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,\
+ 'one.example.com',textAsBlob('80'),90,16,0);\
+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,\
+ '',textAsBlob('80'),90,1,1);\
+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,\
+ 'three.example.com',textAsBlob('80'),90,4,2);"
+
+ cql_execute "$insert_sql"
+ assert_eq 0 $? "insert into lease6 failed, expected exit code %d, actual %d"
+
+ # Dump lease4 to output_file.
+ $keaadmin lease-dump cql -6 -u $db_user -p $db_password -n $db_name -d $db_scripts_dir -o $output_file
+ assert_eq 0 $? "kea-admin lease-dump -6 failed, status code %d"
+
+ # Compare the dump output to reference file, they should be identical.
+ cmp -s $output_file $ref_file
+ assert_eq 0 $? "dump file does not match reference file, expected exit code %d, actual %d"
+
+ # remove the output file.
+ rm $output_file
+
+ # Wipe the database.
+ cql_execute_script $db_scripts_dir/cql/dhcpdb_drop.cql
+ assert_eq 0 $? "drop table query failed, exit code %d, expected %d"
+
+ test_finish 0
+}
+
+# Run tests.
+cql_lease_init_test
+cql_lease_version_test
cql_upgrade_test
+cql_lease4_dump_test
+cql_lease6_dump_test
-address,hwaddr,client_id,valid_lifetime,expire,subnet_id,fqdn_fwd,fqdn_rev,hostname
-0.0.0.10,3230,3330,40,2015-01-01 01:15:30,50,1,1,one.example.com
-0.0.0.11,,313233,40,2015-02-02 02:30:45,50,1,1,
-0.0.0.12,3232,,40,2015-03-03 11:01:07,50,1,1,three.example.com
+address,hwaddr,client_id,valid_lifetime,expire,subnet_id,fqdn_fwd,fqdn_rev,hostname,state
+-1073741302,0x3230,0x3330,40,1430694930,50,True,True,one.example.com,0
+-1073741301,null,0x313233,40,1433464245,50,True,True,,1
+-1073741300,0x3232,null,40,1436173267,50,True,True,three.example.com,2
-address,duid,valid_lifetime,expire,subnet_id,pref_lifetime,lease_type,iaid,prefix_len,fqdn_fwd,fqdn_rev,hostname,hwaddr,hwtype,hwaddr_source
-10,3230,30,2015-04-04 01:15:30,40,50,IA_TA,60,70,1,1,one.example.com,3830,90,100
-11,,30,2015-05-05 02:30:45,40,50,IA_TA,60,70,1,1,,3830,90,100
-12,3231,30,2015-06-06 11:01:07,40,50,IA_TA,60,70,1,1,three.example.com,3830,90,100
+address,duid,valid_lifetime,expire,subnet_id,pref_lifetime,lease_type,iaid,prefix_len,fqdn_fwd,fqdn_rev,hostname,hwaddr,hwtype,hwaddr_source,state
+2001:db8::12,0x3231,30,1436173267,40,50,1,60,70,True,True,three.example.com,0x3830,90,4,2
+2001:db8::11,null,30,1433464245,40,50,1,60,70,True,True,,0x3830,90,1,1
+2001:db8::10,0x3230,30,1430694930,40,50,1,60,70,True,True,one.example.com,0x3830,90,16,0
-- This table is only modified during schema upgrades. For historical reasons
-- (related to the names of the columns in the BIND 10 DNS database file), the
-- 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.
CREATE TABLE schema_version (
version int,
minor int,
) ENGINE = INNODB;
-# Create search indexes for lease4 table
+# Create search indexes for lease4 table.
# index by hwaddr and subnet_id
CREATE INDEX lease4_by_hwaddr_subnet_id ON lease4 (hwaddr, subnet_id);
) ENGINE = INNODB;
-# Create search indexes for lease4 table
-# index by iaid, subnet_id, and duid
+# Create search indexes for lease4 table.
+# index by iaid, subnet_id, and duid
CREATE INDEX lease6_by_iaid_subnet_id_duid ON lease6 (iaid, subnet_id, duid);
# ... and a definition of lease6 types. This table is a convenience for
# This table is only modified during schema upgrades. For historical reasons
# (related to the names of the columns in the BIND 10 DNS database file), the
# first column is called "version" and not "major".
-#
-# NOTE: this MUST be kept in step with src/lib/dhcpsrv/tests/schema_copy.h,
-# which defines the schema for the unit tests. If you are updating
-# the version number, the schema has changed: please ensure that
-# schema_copy.h has been updated as well.
+# Note: This MUST be kept in step with src/share/database/scripts/mysql/dhcpdb_create.mysql,
+# which defines the schema for the unit tests.
CREATE TABLE schema_version (
version INT PRIMARY KEY NOT NULL, # Major version number
minor INT # Minor version number
-- This table is only modified during schema upgrades. For historical reasons
-- (related to the names of the columns in the BIND 10 DNS database file), the
-- first column is called "version" and not "major".
-
--- NOTE: this MUST be kept in step with src/lib/dhcpsrv/tests/schema_copy.h,
--- which defines the schema for the unit tests. If you are updating
--- the version number, the schema has changed: please ensure that
--- schema_copy.h has been updated as well.
+-- Note: This MUST be kept in step with src/share/database/scripts/pgsql/dhcpdb_create.pgsql,
+-- which defines the schema for the unit tests.
CREATE TABLE schema_version (
version INT PRIMARY KEY NOT NULL, -- Major version number
minor INT -- Minor version number
printf "Wiping whole database %s\n" $db_name
export PGPASSWORD=$db_password
- cat $db_scripts_dir/pgsql/dhcpdb_drop.pgsql | psql --set ON_ERROR_STOP=1 -A -t -q -U keatest -d keatest >/dev/null 2>&1
+ cat $db_scripts_dir/pgsql/dhcpdb_drop.pgsql | psql --set ON_ERROR_STOP=1 -A -t -h localhost -q -U keatest -d keatest >/dev/null 2>&1
assert_eq 0 $? "pgsql_wipe drop failed, expected exit code: %d, actual: %d"
}
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),
+ tagged_statements_(NULL) {
}
CqlConnection::~CqlConnection() {
+ // Free up the prepared statements, ignoring errors.
+ // Session and connection resources are deallocated.
CassError rc;
- for (int i = 0; i < statements_.size(); i++)
- {
+ for (int i = 0; i < statements_.size(); i++) {
if (statements_[i]) {
cass_prepared_free(statements_[i]);
}
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 "localhost".
}
const char* port = NULL;
sport = getParameter("port");
port = sport.c_str();
} catch (...) {
- // No port. Fine, we'll use "default"
+ // No port. Fine, we'll use "default".
}
const char* user = NULL;
suser = getParameter("user");
user = suser.c_str();
} catch (...) {
- // No user. Fine, we'll use NULL
+ // No user. Fine, we'll use NULL.
}
const char* password = NULL;
spassword = getParameter("password");
password = spassword.c_str();
} catch (...) {
- // No password. Fine, we'll use NULL
+ // No password. Fine, we'll use NULL.
}
const char* keyspace = "keatest";
skeyspace = getParameter("keyspace");
keyspace = skeyspace.c_str();
} catch (...) {
- // No database name. Fine, we'll use default 'keatest'
+ // No database name. Fine, we'll use default "keatest".
}
cluster_ = cass_cluster_new();
void
CqlConnection::checkStatementError(std::string& error, CassFuture* future,
- uint32_t stindex, const char* what) const
-{
+ uint32_t stindex, const char* what) const {
CassError rc;
const char* errorMessage;
size_t errorMessageSize;
if (rc != CASS_OK) {
stream.str(std::string());
- stream << what << " for: " << tagged_statements_[stindex].name_ << " reason: " <<
- errorMessage << " error code: " << rc;
+ stream << what << " for: " << tagged_statements_[stindex].name_ <<
+ " reason: " << errorMessage << " error code: " << rc;
}
error = stream.str();
}
void
-CqlConnection::checkStatementError(std::string& error, CassFuture* future, const char* what) const
-{
+CqlConnection::checkStatementError(std::string& error, CassFuture* future,
+ const char* what) const {
CassError rc;
const char* errorMessage;
size_t errorMessageSize;
namespace dhcp {
/// @brief Defines a single query
+///
+/// @param params_ Bind parameter names
+/// @param name_ Short name of the query.
+/// @param text_ Text representation of the actual query.
struct CqlTaggedStatement {
- /// Param name.
const char** params_;
-
- /// Short name of the query.
const char* name_;
-
- /// Text representation of the actual query.
const char* text_;
};
-/// Defines CQL backend version: 1.0
-const uint32_t CQL_CURRENT_VERSION = 1;
-const uint32_t CQL_CURRENT_MINOR = 0;
+// Defines CQL backend version: 2.3
+const uint32_t CQL_CURRENT_VERSION = CASS_VERSION_MAJOR;
+const uint32_t CQL_CURRENT_MINOR = CASS_VERSION_MINOR;
class CqlConnection : public DatabaseConnection {
public:
/// @brief Prepare statements
///
- /// Creates the prepared statements for all of the SQL statements used
+ /// Creates the prepared statements for all of the CQL statements used
/// by the CQL backend.
///
/// @throw isc::dhcp::DbOperationError An operation on the open database has
/// failed.
- /// @throw isc::InvalidParameter 'index' is not valid for the vector. This
+ /// @throw isc::InvalidParameter 'index' is not valid for the vector. This
/// represents an internal error within the code.
void prepareStatements(CqlTaggedStatement *statements);
/// @brief Open Database
///
/// Opens the database using the information supplied in the parameters
- /// passed to the constructor.
+ /// passed to the constructor. If no parameters are supplied, the default
+ /// values will be used (keyspace keatest).
///
- /// @throw NoDatabaseName Mandatory database name not given
/// @throw DbOpenError Error opening the database
void openDatabase();
/// @brief Return backend type
///
- /// Returns the type of the backend (e.g. "mysql", "memfile" etc.)
- ///
/// @return Type of the backend.
virtual std::string getType() const {
return (std::string("cql"));
/// @brief Returns backend version.
///
- /// @return Version number as a pair of unsigned integers. "first" is the
+ /// @return Version number as a pair of unsigned integers. "first" is the
/// major version number, "second" the minor number.
///
/// @throw isc::dhcp::DbOperationError An operation on the open database has
void checkStatementError(std::string& error, CassFuture* future,
const char* what) const;
- /// CQL connection handle
+ /// @brief CQL connection handle
CassCluster* cluster_;
+
+ /// @brief CQL session handle
CassSession* session_;
- std::vector<const CassPrepared*> statements_; ///< Prepared statements
+
+ /// @brief CQL prepared statements - used for faster statement execution using
+ /// bind functionality
+ std::vector<const CassPrepared*> statements_;
+
+ /// @brief Pointer to external array of tagged statements containing statement
+ /// name, array of names of bind parameters and text query
CqlTaggedStatement* tagged_statements_;
};
static const size_t HOSTNAME_MAX_LEN = 255;
static const size_t ADDRESS6_TEXT_MAX_LEN = 39;
+/// @name CqlBind auxiliary methods for binding data into Cassandra format:
+/// @{
static CassError CqlBindNone(CassStatement* statement, size_t index, void*) {
return cass_statement_bind_null(statement, index);
}
-static CassError CqlBindBool(CassStatement* statement, size_t index, void* value) {
- return cass_statement_bind_bool(statement, index, *(static_cast<cass_bool_t*>(value)));
+static CassError CqlBindBool(CassStatement* statement, size_t index,
+ void* value) {
+ return cass_statement_bind_bool(statement, index,
+ *(static_cast<cass_bool_t*>(value)));
}
-static CassError CqlBindInt32(CassStatement* statement, size_t index, void* value) {
- return cass_statement_bind_int32(statement, index, *(static_cast<cass_int32_t*>(value)));
+static CassError CqlBindInt32(CassStatement* statement, size_t index,
+ void* value) {
+ return cass_statement_bind_int32(statement, index,
+ *(static_cast<cass_int32_t*>(value)));
}
-static CassError CqlBindInt64(CassStatement* statement, size_t index, void* value) {
- return cass_statement_bind_int64(statement, index, *(static_cast<cass_int64_t*>(value)));
+static CassError CqlBindInt64(CassStatement* statement, size_t index,
+ void* value) {
+ return cass_statement_bind_int64(statement, index,
+ *(static_cast<cass_int64_t*>(value)));
}
-static CassError CqlBindTimestamp(CassStatement* statement, size_t index, void* value) {
- return cass_statement_bind_int64(statement, index, *(static_cast<cass_int64_t*>(value)));
+static CassError CqlBindTimestamp(CassStatement* statement, size_t index,
+ void* value) {
+ return cass_statement_bind_int64(statement, index,
+ *(static_cast<cass_int64_t*>(value)));
}
-static CassError CqlBindString(CassStatement* statement, size_t index, void* value) {
- return cass_statement_bind_string(statement, index, (static_cast<const char*>(value)));
+static CassError CqlBindString(CassStatement* statement, size_t index,
+ void* value) {
+ return cass_statement_bind_string(statement, index,
+ (static_cast<const char*>(value)));
}
-static CassError CqlBindBytes(CassStatement* statement, size_t index, void* value) {
- return cass_statement_bind_bytes(statement, index, &(*(static_cast<std::vector<cass_byte_t>*>(value)))[0],
- static_cast<std::vector<cass_byte_t>*>(value)->size());
+static CassError CqlBindBytes(CassStatement* statement, size_t index,
+ void* value) {
+ return cass_statement_bind_bytes(statement, index,
+ static_cast<std::vector<cass_byte_t>*>(value)->data(),
+ static_cast<std::vector<cass_byte_t>*>(value)->size());
}
+/// @}
static CassError CqlGetNone(const CassValue*, void*, size_t*) {
return CASS_OK;
return cass_value_get_int64(value, static_cast<cass_int64_t*>(data));
}
-static CassError CqlGetString(const CassValue* value, void* data, size_t* size) {
+static CassError CqlGetString(const CassValue* value, void* data,
+ size_t* size) {
return cass_value_get_string(value, static_cast<const char**>(data), size);
}
static CassError CqlGetBytes(const CassValue* value, void* data, size_t* size) {
- return cass_value_get_bytes(value, static_cast<const cass_byte_t**>(data), size);
+ return cass_value_get_bytes(value, static_cast<const cass_byte_t**>(data),
+ size);
}
-typedef CassError (*CqlBindFunction)(CassStatement* statement, size_t index, void* value);
-typedef CassError (*CqlGetFunction)(const CassValue* value, void* data, size_t* size);
+typedef CassError (*CqlBindFunction)(CassStatement* statement, size_t index,
+ void* value);
+typedef CassError (*CqlGetFunction)(const CassValue* value, void* data,
+ size_t* size);
struct CqlFunctionData {
CqlBindFunction sqlBindFunction_;
{CqlBindBytes, CqlGetBytes}
};
-/// @brief Catalog of all the SQL statements currently supported. Note
+/// @brief Catalog of all the SQL statements currently supported. Note
/// that the order columns appear in statement body must match the order they
-/// that the occur in the table. This does not apply to the where clause.
+/// that the occur in the table. This does not apply to the where clause.
static const char* delete_lease4_params[] = {
static_cast<const char*>("address"),
static_cast<const char*>("limit"),
NULL };
static const char* get_version_params[] = {
- static_cast<const char*>("version"),
NULL };
static const char* insert_lease4_params[] = {
static_cast<const char*>("address"),
"valid_lifetime, expire, subnet_id, "
"fqdn_fwd, fqdn_rev, hostname, state "
"FROM lease4 "
- //"WHERE state != ? AND expire < ? ORDER BY expire ASC "
"WHERE state = ? AND expire < ? "
"LIMIT ? ALLOW FILTERING" },
{ insert_lease4_params,
"insert_lease4",
"INSERT INTO lease4(address, hwaddr, client_id, "
- "valid_lifetime, expire, subnet_id, fqdn_fwd, fqdn_rev, hostname, state) "
+ "valid_lifetime, expire, subnet_id, fqdn_fwd, fqdn_rev, hostname, "
+ "state) "
"VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?) "
},
"insert_lease6",
"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) "
+ "lease_type, iaid, prefix_len, fqdn_fwd, fqdn_rev, hostname, hwaddr, "
+ "hwtype, hwaddr_source, state) "
"VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) "
},
{ NULL, NULL, NULL }
};
-
-/// @brief Common CQL and Lease Data Methods
-///
-/// The CqlLease4Exchange and CqlLease6Exchange classes provide the
-/// functionality to set up binding information between variables in the
-/// program and data extracted from the database. This class is the common
-/// base to both of them, containing some common methods.
-
class CqlExchange : public virtual SqlExchange {
public:
// Time conversion methods.
static void
convertToDatabaseTime(const time_t& cltt,
- const uint32_t& valid_lifetime,
- uint64_t& expire) {
- // Calculate expiry time. Store it in the 64-bit value so as we can detect
- // overflows.
+ const uint32_t& valid_lifetime,
+ uint64_t& expire) {
+ // Calculate expiry time. Store it in the 64-bit value so as we can
+ // detect overflows.
int64_t expire_time = static_cast<int64_t>(cltt) +
static_cast<int64_t>(valid_lifetime);
static void
convertFromDatabaseTime(const uint64_t& expire,
- const uint32_t& valid_lifetime,
- time_t& cltt) {
+ const uint32_t& valid_lifetime,
+ time_t& cltt) {
// Convert to local time
cltt = expire - static_cast<int64_t>(valid_lifetime);
}
};
+/// @brief Common CQL and Lease Data Methods
+///
+/// The CqlLease4Exchange and CqlLease6Exchange classes provide the
+/// functionality to set up binding information between variables in the
+/// program and data extracted from the database. This class is the common
+/// base to both of them, containing some common methods.
class CqlLeaseExchange : public CqlExchange {
public:
- CqlLeaseExchange() : hwaddr_length_(0), expire_(0),
- subnet_id_(0), valid_lifetime_(0),
- fqdn_fwd_(false), fqdn_rev_(false), hostname_length_(0), state_(0) {
+ CqlLeaseExchange() : hwaddr_length_(0), expire_(0), subnet_id_(0),
+ valid_lifetime_(0), fqdn_fwd_(false), fqdn_rev_(false),
+ hostname_length_(0), state_(0) {
memset(hwaddr_buffer_, 0, sizeof(hwaddr_buffer_));
memset(hostname_buffer_, 0, sizeof(hostname_buffer_));
}
};
+class CqlVersionExchange : public virtual CqlExchange {
+public:
+ /// @brief Constructor
+ ///
+ /// The initialization of the variables here is only to satisfy cppcheck -
+ /// all variables are initialized/set in the methods before they are used.
+ CqlVersionExchange() {
+ const size_t MAX_COLUMNS = 2;
+ // Set the column names (for error messages)
+ size_t offset = 0;
+ BOOST_ASSERT(2 == MAX_COLUMNS);
+ parameters_.resize(MAX_COLUMNS);
+ parameters_[offset++] = ExchangeColumnInfo("version",
+ EXCHANGE_DATA_TYPE_IO_IN_OUT, EXCHANGE_DATA_TYPE_INT32);
+ parameters_[offset++] = ExchangeColumnInfo("minor",
+ EXCHANGE_DATA_TYPE_IO_IN_OUT, EXCHANGE_DATA_TYPE_INT32);
+ BOOST_ASSERT(offset == MAX_COLUMNS);
+ }
+};
+
+
/// @brief Exchange CQL and Lease4 Data
///
/// On any CQL operation, arrays of CQL BIND structures must be built to
-/// describe the parameters in the prepared statements. Where information is
+/// describe the parameters in the prepared statements. Where information is
/// inserted or retrieved - INSERT, UPDATE, SELECT - a large amount of that
-/// structure is identical. This class handles the creation of that array.
+/// structure is identical. This class handles the creation of that array.
///
/// Owing to the CQL API, the process requires some intermediate variables
-/// to hold things like data length etc. This object holds those variables.
+/// to hold things like data length etc. This object holds those variables.
///
-/// @note There are no unit tests for this class. It is tested indirectly
+/// @note There are no unit tests for this class. It is tested indirectly
/// in all CqlLeaseMgr::xxx4() calls where it is used.
class CqlLease4Exchange : public CqlLeaseExchange {
/// all variables are initialized/set in the methods before they are used.
CqlLease4Exchange() : addr4_(0), client_id_length_(0),
client_id_null_(false) {
+ const size_t MAX_COLUMNS = 11;
memset(client_id_buffer_, 0, sizeof(client_id_buffer_));
// Set the column names (for error messages)
- uint32_t size;
- uint32_t offset = 0;
- size = 12;
- parameters_.resize(size);
- parameters_[offset++] = ExchangeColumnInfo("address", EXCHANGE_DATA_TYPE_IO_IN_OUT, EXCHANGE_DATA_TYPE_INT32);
- parameters_[offset++] = ExchangeColumnInfo("hwaddr", EXCHANGE_DATA_TYPE_IO_IN_OUT, EXCHANGE_DATA_TYPE_BYTES);
- parameters_[offset++] = ExchangeColumnInfo("client_id", EXCHANGE_DATA_TYPE_IO_IN_OUT, EXCHANGE_DATA_TYPE_BYTES);
- parameters_[offset++] = ExchangeColumnInfo("valid_lifetime", EXCHANGE_DATA_TYPE_IO_IN_OUT, EXCHANGE_DATA_TYPE_INT64);
- parameters_[offset++] = ExchangeColumnInfo("expire", EXCHANGE_DATA_TYPE_IO_IN_OUT, EXCHANGE_DATA_TYPE_TIMESTAMP);
- parameters_[offset++] = ExchangeColumnInfo("subnet_id", EXCHANGE_DATA_TYPE_IO_IN_OUT, EXCHANGE_DATA_TYPE_INT32);
- parameters_[offset++] = ExchangeColumnInfo("fqdn_fwd", EXCHANGE_DATA_TYPE_IO_IN_OUT, EXCHANGE_DATA_TYPE_BOOL);
- parameters_[offset++] = ExchangeColumnInfo("fqdn_rev", EXCHANGE_DATA_TYPE_IO_IN_OUT, EXCHANGE_DATA_TYPE_BOOL);
- parameters_[offset++] = ExchangeColumnInfo("hostname", EXCHANGE_DATA_TYPE_IO_IN_OUT, EXCHANGE_DATA_TYPE_STRING);
- parameters_[offset++] = ExchangeColumnInfo("state", EXCHANGE_DATA_TYPE_IO_IN_OUT, EXCHANGE_DATA_TYPE_INT32);
- parameters_[offset++] = ExchangeColumnInfo("limit", EXCHANGE_DATA_TYPE_IO_IN_OUT, EXCHANGE_DATA_TYPE_INT32);
- parameters_[offset++] = ExchangeColumnInfo("version", EXCHANGE_DATA_TYPE_IO_IN_OUT, EXCHANGE_DATA_TYPE_NONE);
+ size_t offset = 0;
+ BOOST_STATIC_ASSERT(11 == MAX_COLUMNS);
+ parameters_.resize(MAX_COLUMNS);
+ parameters_[offset++] = ExchangeColumnInfo("address",
+ EXCHANGE_DATA_TYPE_IO_IN_OUT, EXCHANGE_DATA_TYPE_INT32);
+ parameters_[offset++] = ExchangeColumnInfo("hwaddr",
+ EXCHANGE_DATA_TYPE_IO_IN_OUT, EXCHANGE_DATA_TYPE_BYTES);
+ parameters_[offset++] = ExchangeColumnInfo("client_id",
+ EXCHANGE_DATA_TYPE_IO_IN_OUT, EXCHANGE_DATA_TYPE_BYTES);
+ parameters_[offset++] = ExchangeColumnInfo("valid_lifetime",
+ EXCHANGE_DATA_TYPE_IO_IN_OUT, EXCHANGE_DATA_TYPE_INT64);
+ parameters_[offset++] = ExchangeColumnInfo("expire",
+ EXCHANGE_DATA_TYPE_IO_IN_OUT, EXCHANGE_DATA_TYPE_TIMESTAMP);
+ parameters_[offset++] = ExchangeColumnInfo("subnet_id",
+ EXCHANGE_DATA_TYPE_IO_IN_OUT, EXCHANGE_DATA_TYPE_INT32);
+ parameters_[offset++] = ExchangeColumnInfo("fqdn_fwd",
+ EXCHANGE_DATA_TYPE_IO_IN_OUT, EXCHANGE_DATA_TYPE_BOOL);
+ parameters_[offset++] = ExchangeColumnInfo("fqdn_rev",
+ EXCHANGE_DATA_TYPE_IO_IN_OUT, EXCHANGE_DATA_TYPE_BOOL);
+ parameters_[offset++] = ExchangeColumnInfo("hostname",
+ EXCHANGE_DATA_TYPE_IO_IN_OUT, EXCHANGE_DATA_TYPE_STRING);
+ parameters_[offset++] = ExchangeColumnInfo("state",
+ EXCHANGE_DATA_TYPE_IO_IN_OUT, EXCHANGE_DATA_TYPE_INT32);
+ parameters_[offset++] = ExchangeColumnInfo("limit",
+ EXCHANGE_DATA_TYPE_IO_IN_OUT, EXCHANGE_DATA_TYPE_INT32);
+ BOOST_ASSERT(offset == MAX_COLUMNS);
}
/// @brief Create CQL_BIND objects for Lease4 Pointer
try {
// address: uint32_t
- // The address in the Lease structure is an IOAddress object. Convert
- // this to an integer for storage.
+ // The address in the Lease structure is an IOAddress object.
+ // Convert this to an integer for storage.
addr4_ = static_cast<uint32_t>(lease_->addr_);
data.add(&addr4_);
// expire: timestamp
// The lease structure holds the client last transmission time (cltt_)
// For convenience for external tools, this is converted to lease
- // expiry time (expire). The relationship is given by:
+ // expiry time (expire). The relationship is given by:
//
// expire = cltt_ + valid_lft_
- CqlLeaseExchange::convertToDatabaseTime(lease_->cltt_, lease_->valid_lft_, expire_);
+ CqlLeaseExchange::convertToDatabaseTime(lease_->cltt_,
+ lease_->valid_lft_, expire_);
data.add(&expire_);
// subnet_id: unsigned int
// hostname: varchar(255)
hostname_length_ = lease_->hostname_.length();
if (hostname_length_ >= sizeof(hostname_buffer_)) {
- isc_throw(BadValue, "hostname value is too large: " << lease_->hostname_.c_str());
+ isc_throw(BadValue, "hostname value is too large: " <<
+ lease_->hostname_.c_str());
}
if (hostname_length_) {
- memcpy(hostname_buffer_, lease_->hostname_.c_str(), hostname_length_);
+ memcpy(hostname_buffer_, lease_->hostname_.c_str(),
+ hostname_length_);
}
hostname_buffer_[hostname_length_] = '\0';
data.add(hostname_buffer_);
hwaddr_.assign(hwaddr_buffer, hwaddr_buffer + hwaddr_length_);
// client_id: varbinary(128)
- client_id_.assign(client_id_buffer, client_id_buffer + client_id_length_);
+ client_id_.assign(client_id_buffer, client_id_buffer +
+ client_id_length_);
if (client_id_length_ >= sizeof(client_id_buffer_)) {
- isc_throw(BadValue, "client id value is too large: " << client_id_buffer);
+ isc_throw(BadValue, "client id value is too large: " <<
+ client_id_buffer);
}
if (client_id_length_) {
memcpy(client_id_buffer_, client_id_buffer, client_id_length_);
// hostname: varchar(255)
if (hostname_length_ >= sizeof(hostname_buffer_)) {
- isc_throw(BadValue, "hostname value is too large: " << hostname_buffer);
+ isc_throw(BadValue, "hostname value is too large: " <<
+ hostname_buffer);
}
if (hostname_length_) {
memcpy(hostname_buffer_, hostname_buffer, hostname_length_);
hostname_buffer_[hostname_length_] = '\0';
time_t cltt = 0;
- CqlLeaseExchange::convertFromDatabaseTime(expire_, valid_lifetime_, cltt);
+ CqlLeaseExchange::convertFromDatabaseTime(expire_, valid_lifetime_,
+ cltt);
// Recreate the hardware address.
HWAddrPtr hwaddr(new HWAddr(hwaddr_, HTYPE_ETHER));
std::string hostname(hostname_buffer_,
hostname_buffer_ + hostname_length_);
- Lease4Ptr result(new Lease4(addr4_, hwaddr,
- client_id_buffer_, client_id_length_,
- valid_lifetime_, 0, 0, cltt,
- subnet_id_, fqdn_fwd_, fqdn_rev_,
- hostname));
+ Lease4Ptr result(new Lease4(addr4_, hwaddr, client_id_buffer_,
+ client_id_length_, valid_lifetime_, 0,
+ 0, cltt, subnet_id_, fqdn_fwd_,
+ fqdn_rev_, hostname));
result->state_ = state_;
bool client_id_null_; ///< Is Client ID null?
};
-
-
/// @brief Exchange CQL and Lease6 Data
///
/// On any CQL operation, arrays of CQL BIND structures must be built to
-/// describe the parameters in the prepared statements. Where information is
+/// describe the parameters in the prepared statements. Where information is
/// inserted or retrieved - INSERT, UPDATE, SELECT - a large amount of that
-/// structure is identical. This class handles the creation of that array.
+/// structure is identical. This class handles the creation of that array.
///
/// Owing to the CQL API, the process requires some intermediate variables
-/// to hold things like data length etc. This object holds those variables.
+/// to hold things like data length etc. This object holds those variables.
///
-/// @note There are no unit tests for this class. It is tested indirectly
+/// @note There are no unit tests for this class. It is tested indirectly
/// in all CqlLeaseMgr::xxx6() calls where it is used.
class CqlLease6Exchange : public CqlLeaseExchange {
iaid_(0), lease_type_(0), prefixlen_(0),
pref_lifetime_(0), hwaddr_null_(false), hwtype_(0),
hwaddr_source_(0) {
+ const size_t MAX_COLUMNS = 17;
memset(addr6_buffer_, 0, sizeof(addr6_buffer_));
memset(duid_buffer_, 0, sizeof(duid_buffer_));
// Set the column names (for error messages)
- uint32_t size;
- uint32_t offset = 0;
- size = 18;
- parameters_.resize(size);
- parameters_[offset++] = ExchangeColumnInfo("address", EXCHANGE_DATA_TYPE_IO_IN_OUT, EXCHANGE_DATA_TYPE_STRING);
- parameters_[offset++] = ExchangeColumnInfo("duid", EXCHANGE_DATA_TYPE_IO_IN_OUT, EXCHANGE_DATA_TYPE_BYTES);
- parameters_[offset++] = ExchangeColumnInfo("valid_lifetime", EXCHANGE_DATA_TYPE_IO_IN_OUT, EXCHANGE_DATA_TYPE_INT64);
- parameters_[offset++] = ExchangeColumnInfo("expire", EXCHANGE_DATA_TYPE_IO_IN_OUT, EXCHANGE_DATA_TYPE_TIMESTAMP);
- parameters_[offset++] = ExchangeColumnInfo("subnet_id", EXCHANGE_DATA_TYPE_IO_IN_OUT, EXCHANGE_DATA_TYPE_INT32);
- parameters_[offset++] = ExchangeColumnInfo("pref_lifetime", EXCHANGE_DATA_TYPE_IO_IN_OUT, EXCHANGE_DATA_TYPE_INT64);
- parameters_[offset++] = ExchangeColumnInfo("lease_type", EXCHANGE_DATA_TYPE_IO_IN_OUT, EXCHANGE_DATA_TYPE_INT32);
- parameters_[offset++] = ExchangeColumnInfo("iaid", EXCHANGE_DATA_TYPE_IO_IN_OUT, EXCHANGE_DATA_TYPE_INT32);
- parameters_[offset++] = ExchangeColumnInfo("prefix_len", EXCHANGE_DATA_TYPE_IO_IN_OUT, EXCHANGE_DATA_TYPE_INT32);
- parameters_[offset++] = ExchangeColumnInfo("fqdn_fwd", EXCHANGE_DATA_TYPE_IO_IN_OUT, EXCHANGE_DATA_TYPE_BOOL);
- parameters_[offset++] = ExchangeColumnInfo("fqdn_rev", EXCHANGE_DATA_TYPE_IO_IN_OUT, EXCHANGE_DATA_TYPE_BOOL);
- parameters_[offset++] = ExchangeColumnInfo("hostname", EXCHANGE_DATA_TYPE_IO_IN_OUT, EXCHANGE_DATA_TYPE_STRING);
- parameters_[offset++] = ExchangeColumnInfo("hwaddr", EXCHANGE_DATA_TYPE_IO_IN_OUT, EXCHANGE_DATA_TYPE_BYTES);
- parameters_[offset++] = ExchangeColumnInfo("hwtype", EXCHANGE_DATA_TYPE_IO_IN_OUT, EXCHANGE_DATA_TYPE_INT32);
- parameters_[offset++] = ExchangeColumnInfo("hwaddr_source", EXCHANGE_DATA_TYPE_IO_IN_OUT, EXCHANGE_DATA_TYPE_INT32);
- parameters_[offset++] = ExchangeColumnInfo("state", EXCHANGE_DATA_TYPE_IO_IN_OUT, EXCHANGE_DATA_TYPE_INT32);
- parameters_[offset++] = ExchangeColumnInfo("limit", EXCHANGE_DATA_TYPE_IO_IN_OUT, EXCHANGE_DATA_TYPE_INT32);
- parameters_[offset++] = ExchangeColumnInfo("version", EXCHANGE_DATA_TYPE_IO_IN_OUT, EXCHANGE_DATA_TYPE_NONE);
+ size_t offset = 0;
+ BOOST_STATIC_ASSERT(17 == MAX_COLUMNS);
+ parameters_.resize(MAX_COLUMNS);
+ parameters_[offset++] = ExchangeColumnInfo("address",
+ EXCHANGE_DATA_TYPE_IO_IN_OUT, EXCHANGE_DATA_TYPE_STRING);
+ parameters_[offset++] = ExchangeColumnInfo("duid",
+ EXCHANGE_DATA_TYPE_IO_IN_OUT, EXCHANGE_DATA_TYPE_BYTES);
+ parameters_[offset++] = ExchangeColumnInfo("valid_lifetime",
+ EXCHANGE_DATA_TYPE_IO_IN_OUT, EXCHANGE_DATA_TYPE_INT64);
+ parameters_[offset++] = ExchangeColumnInfo("expire",
+ EXCHANGE_DATA_TYPE_IO_IN_OUT, EXCHANGE_DATA_TYPE_TIMESTAMP);
+ parameters_[offset++] = ExchangeColumnInfo("subnet_id",
+ EXCHANGE_DATA_TYPE_IO_IN_OUT, EXCHANGE_DATA_TYPE_INT32);
+ parameters_[offset++] = ExchangeColumnInfo("pref_lifetime",
+ EXCHANGE_DATA_TYPE_IO_IN_OUT, EXCHANGE_DATA_TYPE_INT64);
+ parameters_[offset++] = ExchangeColumnInfo("lease_type",
+ EXCHANGE_DATA_TYPE_IO_IN_OUT, EXCHANGE_DATA_TYPE_INT32);
+ parameters_[offset++] = ExchangeColumnInfo("iaid",
+ EXCHANGE_DATA_TYPE_IO_IN_OUT, EXCHANGE_DATA_TYPE_INT32);
+ parameters_[offset++] = ExchangeColumnInfo("prefix_len",
+ EXCHANGE_DATA_TYPE_IO_IN_OUT, EXCHANGE_DATA_TYPE_INT32);
+ parameters_[offset++] = ExchangeColumnInfo("fqdn_fwd",
+ EXCHANGE_DATA_TYPE_IO_IN_OUT, EXCHANGE_DATA_TYPE_BOOL);
+ parameters_[offset++] = ExchangeColumnInfo("fqdn_rev",
+ EXCHANGE_DATA_TYPE_IO_IN_OUT, EXCHANGE_DATA_TYPE_BOOL);
+ parameters_[offset++] = ExchangeColumnInfo("hostname",
+ EXCHANGE_DATA_TYPE_IO_IN_OUT, EXCHANGE_DATA_TYPE_STRING);
+ parameters_[offset++] = ExchangeColumnInfo("hwaddr",
+ EXCHANGE_DATA_TYPE_IO_IN_OUT, EXCHANGE_DATA_TYPE_BYTES);
+ parameters_[offset++] = ExchangeColumnInfo("hwtype",
+ EXCHANGE_DATA_TYPE_IO_IN_OUT, EXCHANGE_DATA_TYPE_INT32);
+ parameters_[offset++] = ExchangeColumnInfo("hwaddr_source",
+ EXCHANGE_DATA_TYPE_IO_IN_OUT, EXCHANGE_DATA_TYPE_INT32);
+ parameters_[offset++] = ExchangeColumnInfo("state",
+ EXCHANGE_DATA_TYPE_IO_IN_OUT, EXCHANGE_DATA_TYPE_INT32);
+ parameters_[offset++] = ExchangeColumnInfo("limit",
+ EXCHANGE_DATA_TYPE_IO_IN_OUT, EXCHANGE_DATA_TYPE_INT32);
+ BOOST_ASSERT(offset == MAX_COLUMNS);
}
/// @brief Create CQL_BIND objects for Lease6 Pointer
}
// Store lease object to ensure it remains valid.
lease_ = lease;
+
// Set up the structures for the various components of the lease4
// structure.
-
try {
// address: varchar(39)
std::string text_buffer = lease_->addr_.toText();
addr6_length_ = text_buffer.size();
if (addr6_length_ >= sizeof(addr6_buffer_)) {
- isc_throw(BadValue, "address value is too large: " << text_buffer);
+ isc_throw(BadValue, "address value is too large: " <<
+ text_buffer);
}
if (addr6_length_) {
memcpy(addr6_buffer_, text_buffer.c_str(), addr6_length_);
// duid: varchar(128)
if (!lease_->duid_) {
- isc_throw(DbOperationError, "lease6 for address " << addr6_buffer_
- << " is missing mandatory client-id.");
+ isc_throw(DbOperationError, "lease6 for address " <<
+ addr6_buffer_ << " is missing mandatory client-id.");
}
duid_ = lease_->duid_->getDuid();
duid_length_ = duid_.size();
// expire: timestamp
// The lease structure holds the client last transmission time (cltt_)
// For convenience for external tools, this is converted to lease
- // expiry time (expire). The relationship is given by:
+ // expiry time (expire). The relationship is given by:
//
// expire = cltt_ + valid_lft_
- CqlLeaseExchange::convertToDatabaseTime(lease_->cltt_, lease_->valid_lft_, expire_);
+ CqlLeaseExchange::convertToDatabaseTime(lease_->cltt_,
+ lease_->valid_lft_, expire_);
data.add(&expire_);
// subnet_id: unsigned int
// hostname: varchar(255)
hostname_length_ = lease_->hostname_.length();
if (hostname_length_ >= sizeof(hostname_buffer_)) {
- isc_throw(BadValue, "hostname value is too large: " << lease_->hostname_.c_str());
+ isc_throw(BadValue, "hostname value is too large: " <<
+ lease_->hostname_.c_str());
}
if (hostname_length_) {
- memcpy(hostname_buffer_, lease_->hostname_.c_str(), hostname_length_);
+ memcpy(hostname_buffer_, lease_->hostname_.c_str(),
+ hostname_length_);
}
hostname_buffer_[hostname_length_] = '\0';
data.add(hostname_buffer_);
// address: varchar(39)
if (addr6_length_ >= sizeof(addr6_buffer_)) {
- isc_throw(BadValue, "address value is too large: " << address_buffer);
+ isc_throw(BadValue, "address value is too large: " <<
+ address_buffer);
}
if (addr6_length_) {
memcpy(addr6_buffer_, address_buffer, addr6_length_);
// hostname: varchar(255)
if (hostname_length_ >= sizeof(hostname_buffer_)) {
- isc_throw(BadValue, "hostname value is too large: " << hostname_buffer);
+ isc_throw(BadValue, "hostname value is too large: " <<
+ hostname_buffer);
}
if (hostname_length_) {
memcpy(hostname_buffer_, hostname_buffer, hostname_length_);
// Create the lease and set the cltt (after converting from the
// expire time retrieved from the database).
- Lease6Ptr result(new Lease6(static_cast<Lease::Type>(lease_type_), addr, duid, iaid_,
- pref_lifetime_, valid_lifetime_, 0, 0,
- subnet_id_, fqdn_fwd_, fqdn_rev_,
- hostname, hwaddr, prefixlen_));
+ Lease6Ptr result(new Lease6(static_cast<Lease::Type>(lease_type_),
+ addr, duid, iaid_, pref_lifetime_,
+ valid_lifetime_, 0, 0, subnet_id_,
+ fqdn_fwd_, fqdn_rev_, hostname, hwaddr,
+ prefixlen_));
time_t cltt = 0;
- CqlLeaseExchange::convertFromDatabaseTime(expire_, valid_lifetime_, cltt);
+ CqlLeaseExchange::convertFromDatabaseTime(expire_, valid_lifetime_,
+ cltt);
result->cltt_ = cltt;
result->state_ = state_;
CqlLeaseMgr::CqlLeaseMgr(const DatabaseConnection::ParameterMap& parameters)
: LeaseMgr(), dbconn_(parameters), exchange4_(new CqlLease4Exchange()),
- exchange6_(new CqlLease6Exchange()) {
+ exchange6_(new CqlLease6Exchange()), versionExchange_(new CqlVersionExchange()) {
dbconn_.openDatabase();
dbconn_.prepareStatements(CqlLeaseMgr::tagged_statements_);
}
CqlLeaseMgr::~CqlLeaseMgr() {
+ // There is no need to close the database in this destructor: it is
+ // closed in the destructor of the dbconn_ member variable.
}
std::string
}
void
-CqlLeaseMgr::getDataType(const StatementIndex stindex, int pindex, const SqlExchange& exchange, ExchangeDataType& type) {
+CqlLeaseMgr::getDataType(const StatementIndex stindex, int pindex,
+ const SqlExchange& exchange, ExchangeDataType& type) {
if (CqlLeaseMgr::tagged_statements_[stindex].params_ &&
CqlLeaseMgr::tagged_statements_[stindex].params_[pindex]) {
for (int i = 0; exchange.parameters_.size(); i++) {
- if (!strcmp(CqlLeaseMgr::tagged_statements_[stindex].params_[pindex], exchange.parameters_[i].column_)) {
+ if (!strcmp(CqlLeaseMgr::tagged_statements_[stindex].params_[pindex],
+ exchange.parameters_[i].column_)) {
type = exchange.parameters_[i].type_;
return;
}
}
void
-CqlLeaseMgr::bindData(CassStatement* statement, const StatementIndex stindex, CqlDataArray& data, const SqlExchange& exchange) {
+CqlLeaseMgr::bindData(CassStatement* statement, const StatementIndex stindex,
+ CqlDataArray& data, const SqlExchange& exchange) {
if (CqlLeaseMgr::tagged_statements_[stindex].params_ == NULL) {
return;
}
}
void
-CqlLeaseMgr::getData(const CassRow* row, int pindex, CqlDataArray& data, CqlDataArray& size, const SqlExchange& exchange) {
+CqlLeaseMgr::getData(const CassRow* row, int pindex, CqlDataArray& data,
+ CqlDataArray& size, const SqlExchange& exchange) {
const CassValue* value;
if (pindex >= exchange.parameters_.size()) {
return;
}
value = cass_row_get_column_by_name(row, exchange.parameters_[pindex].column_);
- CqlFunctions[exchange.parameters_[pindex].type_].sqlGetFunction_(value, data.values_[pindex], reinterpret_cast<size_t *>(size.values_[pindex]));
+ if (NULL == value) {
+ isc_throw(BadValue, "Column name "
+ << exchange.parameters_[pindex].column_ << "doesn't exist");
+ }
+ CqlFunctions[exchange.parameters_[pindex].type_].sqlGetFunction_(value,
+ data.values_[pindex], reinterpret_cast<size_t *>(size.values_[pindex]));
}
bool
int rowCount = 0;
while (cass_iterator_next(rows)) {
rowCount++;
- if (single && rowCount > 1)
- {
+ if (single && rowCount > 1) {
result.clear();
break;
}
CqlLeaseMgr::getLease(StatementIndex stindex, CqlDataArray& data,
Lease4Ptr& result) const {
// Create appropriate collection object and get all leases matching
- // the selection criteria. The "single" parameter is true to indicate
+ // the selection criteria. The "single" parameter is true to indicate
// that the called method should throw an exception if multiple
// matching records are found: this particular method is called when only
// one or zero matches is expected.
CqlLeaseMgr::getLease(StatementIndex stindex, CqlDataArray& data,
Lease6Ptr& result) const {
// Create appropriate collection object and get all leases matching
- // the selection criteria. The "single" parameter is true to indicate
+ // the selection criteria. The "single" parameter is true to indicate
// that the called method should throw an exception if multiple
// matching records are found: this particular method is called when only
// one or zero matches is expected.
}
}
-// Basic lease access methods. Obtain leases from the database using various
+// Basic lease access methods. Obtain leases from the database using various
// criteria.
Lease4Ptr
}
Lease4Ptr
-CqlLeaseMgr::getLease4(const ClientId& clientid, const HWAddr& hwaddr, SubnetID subnet_id) const {
+CqlLeaseMgr::getLease4(const ClientId& clientid, const HWAddr& hwaddr,
+ SubnetID subnet_id) const {
/// This function is currently not implemented because allocation engine
/// searches for the lease using HW address or client identifier.
/// It never uses both parameters in the same time. We need to
uint32_t limit = max_leases > 0 ? static_cast<uint32_t>(max_leases) :
std::numeric_limits<uint32_t>::max();
- for (uint32_t state = Lease::STATE_DEFAULT; state <= Lease::STATE_EXPIRED_RECLAIMED; state++) {
+ for (uint32_t state = Lease::STATE_DEFAULT;
+ state <= Lease::STATE_EXPIRED_RECLAIMED; state++) {
if (state == keepState) {
continue;
}
typedef typename LeaseCollection::iterator LeaseCollectionIt;
- for (LeaseCollectionIt it = tempCollection.begin(); it != tempCollection.end(); ++it) {
+ for (LeaseCollectionIt it = tempCollection.begin();
+ it != tempCollection.end(); ++it) {
expired_leases.push_back((*it));
}
}
}
uint64_t
-CqlLeaseMgr::deleteExpiredReclaimedLeasesCommon(const uint32_t secs, StatementIndex statement_index) {
+CqlLeaseMgr::deleteExpiredReclaimedLeasesCommon(const uint32_t secs,
+ StatementIndex statement_index) {
// Set up the WHERE clause value
//"WHERE state = ? AND expire < ? ALLOW FILTERING"
data.add(&state);
// Expiration timestamp.
- uint64_t expiration = static_cast<int64_t>(time(NULL) - static_cast<time_t>(secs));
+ uint64_t expiration = static_cast<int64_t>(time(NULL) -
+ static_cast<time_t>(secs));
data.add(&expiration);
// Get the data
default:
break;
}
- for (Lease4Collection::iterator it = result4Leases.begin(); it != result4Leases.end(); ++it) {
+ for (Lease4Collection::iterator it = result4Leases.begin();
+ it != result4Leases.end(); ++it) {
if (deleteLease((*it)->addr_)) {
result++;
}
}
- for (Lease6Collection::iterator it = result6Leases.begin(); it != result6Leases.end(); ++it) {
+ for (Lease6Collection::iterator it = result6Leases.begin();
+ it != result6Leases.end(); ++it) {
if (deleteLease((*it)->addr_)) {
result++;
}
CqlLeaseMgr::getVersion() const {
LOG_DEBUG(dhcpsrv_logger, DHCPSRV_DBG_TRACE_DETAIL,
DHCPSRV_CQL_GET_VERSION);
+ uint32_t version;
+ uint32_t minor;
+ CassError rc;
+ CassStatement* statement = NULL;
+ CassFuture* future = NULL;
+
+ statement = cass_prepared_bind(dbconn_.statements_[GET_VERSION]);
+
+ future = cass_session_execute(dbconn_.session_, statement);
+ cass_future_wait(future);
+ std::string error;
+ dbconn_.checkStatementError(error, future, "unable to GET");
+ rc = cass_future_error_code(future);
+ if (rc != CASS_OK) {
+ cass_future_free(future);
+ cass_statement_free(statement);
+ isc_throw(DbOperationError, error);
+ }
- uint32_t version = CASS_VERSION_MAJOR;
- uint32_t minor = CASS_VERSION_MINOR;
+ const CassResult* resultCollection = cass_future_get_result(future);
+ CassIterator* rows = cass_iterator_from_result(resultCollection);
+ CqlDataArray data;
+ CqlDataArray size;
+ int rowCount = 0;
+ while (cass_iterator_next(rows)) {
+ rowCount++;
+ const CassRow* row = cass_iterator_get_row(rows);
+ // version: uint32_t
+ data.add(reinterpret_cast<void*>(&version));
+ size.add(NULL);
+ // minor: uint32_t
+ data.add(reinterpret_cast<void*>(&minor));
+ size.add(NULL);
+
+ for (int i = 0; i < 2; i++) {
+ CqlLeaseMgr::getData(row, i, data, size, *versionExchange_);
+ }
+ }
+
+ cass_iterator_free(rows);
+ cass_result_free(resultCollection);
+ cass_future_free(future);
+ cass_statement_free(statement);
return make_pair<uint32_t, uint32_t>(version, minor);
}
/// CQL execute call.
///
/// Note that the data values are stored as pointers. These pointers need to
-/// valid for the duration of the CQL statement execution. In other
+/// valid for the duration of the CQL statement execution. In other
/// words populating them with pointers to values that go out of scope before
/// statement is executed is a bad idea.
values_.push_back(value);
}
void remove(int index) {
+ if (values_.size() <= index) {
+ isc_throw(BadValue, "Index " << index << " out of bounds: [0, " <<
+ (values_.size() - 1) << "]");
+ }
values_.erase(values_.begin() + index);
}
};
-class CqlExchange;
+class CqlVersionExchange;
class CqlLeaseExchange;
class CqlLease4Exchange;
class CqlLease6Exchange;
/// @brief Cassandra Lease Manager
///
-/// This class provides the \ref isc::dhcp::LeaseMgr interface to the CQL - Cassandra
-/// database. Use of this backend presupposes that a CQL database is
-/// available and that the Kea schema has been created within it.
+/// This class provides the \ref isc::dhcp::LeaseMgr interface to the Cassandra
+/// database. Use of this backend presupposes that a CQL database is available
+/// and that the Kea schema has been created within it.
class CqlLeaseMgr : public LeaseMgr {
public:
/// @brief Deletes a lease.
///
- /// @param addr Address of the lease to be deleted. This can be an IPv4
+ /// @param addr Address of the lease to be deleted. This can be an IPv4
/// address or an IPv6 address.
///
/// @return true if deletion was successful, false if no such lease exists
/// @brief Return backend type
///
- /// Returns the type of the backend (e.g. "mysql", "memfile" etc.)
- ///
/// @return Type of the backend.
virtual std::string getType() const {
return (std::string("cql"));
/// @brief Returns backend version.
///
- /// @return Version number as a pair of unsigned integers. "first" is the
+ /// @return Version number as a pair of unsigned integers. "first" is the
/// major version number, "second" the minor number.
///
/// @throw isc::dhcp::DbOperationError An operation on the open database has
/// @brief Commit Transactions
///
- /// Commits all pending database operations.
- ///
- /// @throw DbOperationError If the commit failed.
+ /// This is a no-op for Cassandra.
virtual void commit();
/// @brief Rollback Transactions
///
- /// Rolls back all pending database operations.
- ///
- /// @throw DbOperationError If the rollback failed.
+ /// This is a no-op for Cassandra.
virtual void rollback();
UPDATE_LEASE6, // Update a Lease6 entry
NUM_STATEMENTS // Number of statements
};
- static void bindData(CassStatement* statement, const StatementIndex stindex, CqlDataArray& data, const SqlExchange& exchange);
- static void getDataType(const StatementIndex stindex, int param, const SqlExchange& exchange, ExchangeDataType& type);
+ /// @brief TODO
+ ///
+ /// TODO
+ ///
+ /// @param statement TODO
+ /// @param stindex Index of statement being executed
+ /// @param data array that has been created for the type of lease in question.
+ /// @param exchange Exchange object to use
+ static void bindData(CassStatement* statement, const StatementIndex stindex,
+ CqlDataArray& data, const SqlExchange& exchange);
+
+ /// @brief TODO
+ ///
+ /// TODO
+ ///
+ /// @param stindex Index of statement being executed
+ /// @param param TODO
+ /// @param exchange Exchange object to use
+ /// @param type TODO
+ static void getDataType(const StatementIndex stindex, int param,
+ const SqlExchange& exchange, ExchangeDataType& type);
- static void getData(const CassRow* row, int pindex, CqlDataArray& data, CqlDataArray& size, const SqlExchange& exchange);
+ /// @brief TODO
+ ///
+ /// TODO
+ ///
+ /// @param row TODO
+ /// @param pindex Index of statement being executed
+ /// @param data array that has been created for the type of lease in question.
+ /// @param data size TODO
+ /// @param exchange Exchange object to use
+ static void getData(const CassRow* row, int pindex, CqlDataArray& data,
+ CqlDataArray& size, const SqlExchange& exchange);
private:
/// @brief Add Lease Common Code
///
/// This method performs the common actions for both flavours (V4 and V6)
- /// of the addLease method. It binds the contents of the lease object to
+ /// of the addLease method. It binds the contents of the lease object to
/// the prepared statement and adds it to the database.
///
/// @param stindex Index of statement being executed
/// @param data array that has been created for the type
/// of lease in question.
+ /// @param exchange Exchange object to use
///
/// @return true if the lease was added, false if it was not added because
/// a lease with that address already exists in the database.
///
/// @throw isc::dhcp::DbOperationError An operation on the open database has
/// failed.
- bool addLeaseCommon(StatementIndex stindex, CqlDataArray& data, CqlLeaseExchange& exchange);
+ bool addLeaseCommon(StatementIndex stindex, CqlDataArray& data,
+ CqlLeaseExchange& exchange);
/// @brief Get Lease Collection Common Code
///
/// @brief Gets Lease4 Collection
///
- /// Gets a collection of Lease4 objects. This is just an interface to
+ /// Gets a collection of Lease4 objects. This is just an interface to
/// the get lease collection common code.
///
/// @param stindex Index of statement being executed
/// @param data array containing the where clause input parameters
- /// @param lease LeaseCollection object returned. Note that any leases in
+ /// @param result LeaseCollection object returned. Note that any leases in
/// the collection when this method is called are not erased: the
/// new data is appended to the end.
///
/// @brief Get Lease6 Collection
///
- /// Gets a collection of Lease6 objects. This is just an interface to
+ /// Gets a collection of Lease6 objects. This is just an interface to
/// the get lease collection common code.
///
/// @param stindex Index of statement being executed
/// @param data array containing input parameters for the query
- /// @param lease LeaseCollection object returned. Note that any existing
+ /// @param result LeaseCollection object returned. Note that any existing
/// data in the collection is erased first.
///
/// @throw isc::dhcp::BadValue Data retrieved from the database was invalid.
/// @brief Get Lease4 Common Code
///
/// This method performs the common actions for the various getLease4()
- /// methods. It acts as an interface to the getLeaseCollection() method,
+ /// methods. It acts as an interface to the getLeaseCollection() method,
/// but retrieveing only a single lease.
///
/// @param stindex Index of statement being executed
/// @brief Get Lease6 Common Code
///
/// This method performs the common actions for the various getLease4()
- /// methods. It acts as an interface to the getLeaseCollection() method,
+ /// methods. It acts as an interface to the getLeaseCollection() method,
/// but retrieveing only a single lease.
///
/// @param stindex Index of statement being executed
/// @brief Update lease common code
///
- /// Holds the common code for updating a lease. It binds the parameters
+ /// Holds the common code for updating a lease. It binds the parameters
/// to the prepared statement, executes it, then checks how many rows
/// were affected.
///
/// @brief Delete lease common code
///
- /// Holds the common code for deleting a lease. It binds the parameters
+ /// Holds the common code for deleting a lease. It binds the parameters
/// to the prepared statement, executes the statement and checks to
/// see how many rows were deleted.
///
///
/// @throw isc::dhcp::DbOperationError An operation on the open database has
/// failed.
- bool deleteLeaseCommon(StatementIndex stindex, CqlDataArray& data, CqlLeaseExchange& exchange);
+ bool deleteLeaseCommon(StatementIndex stindex, CqlDataArray& data,
+ CqlLeaseExchange& exchange);
/// @brief Delete expired-reclaimed leases.
///
uint64_t deleteExpiredReclaimedLeasesCommon(const uint32_t secs,
StatementIndex statement_index);
+ /// TODO
static CqlTaggedStatement tagged_statements_[];
/// Database connection object
CqlConnection dbconn_;
/// The exchange objects are used for transfer of data to/from the database.
/// They are pointed-to objects as the contents may change in "const" calls,
- /// while the rest of this object does not. (At alternative would be to
+ /// while the rest of this object does not. (At alternative would be to
/// declare them as "mutable".)
boost::scoped_ptr<CqlLease4Exchange> exchange4_; ///< Exchange object
boost::scoped_ptr<CqlLease6Exchange> exchange6_; ///< Exchange object
+ boost::scoped_ptr<CqlVersionExchange> versionExchange_; ///< Exchange object
};
}; // end of isc::dhcp namespace
namespace isc {
namespace dhcp {
+/// @brief Used to map server data types with internal backend storage data
+/// types.
enum ExchangeDataType {
EXCHANGE_DATA_TYPE_NONE,
EXCHANGE_DATA_TYPE_BOOL,
EXCHANGE_DATA_TYPE_BYTES
};
+/// @brief Used to specify the direction of the data exchange between the
+/// database and the server.
enum ExchangeDataTypeIO {
EXCHANGE_DATA_TYPE_IO_IN,
EXCHANGE_DATA_TYPE_IO_OUT,
EXCHANGE_DATA_TYPE_IO_IN_OUT
};
+/// @brief Used to map the column name with internal backend storage data types.
struct ExchangeColumnInfo {
ExchangeColumnInfo () : column_(NULL), type_io_(EXCHANGE_DATA_TYPE_IO_IN), type_(EXCHANGE_DATA_TYPE_NONE) {};
ExchangeColumnInfo (const char *column, ExchangeDataTypeIO type_io, ExchangeDataType type) : column_(column), type_io_(type_io), type_(type) {};
namespace {
-
/// @brief Test fixture class for testing Cassandra Lease Manager
///
/// Opens the database prior to each test and closes it afterwards.
/// @brief Destructor
///
- /// Rolls back all pending transactions. The deletion of lmptr_ will close
- /// the database. Then reopen it and delete everything created by the test.
+ /// Rolls back all pending transactions. The deletion of lmptr_ will close
+ /// the database. Then reopen it and delete everything created by the test.
virtual ~CqlLeaseMgrTest() {
lmptr_->rollback();
LeaseMgrFactory::destroy();
/// @brief Reopen the database
///
- /// Closes the database and re-open it. Anything committed should be
+ /// Closes the database and re-open it. Anything committed should be
/// visible.
///
/// Parameter is ignored for CQL backend as the v4 and v6 leases share
/// @brief Check that database can be opened
///
-/// This test checks if the CqlLeaseMgr can be instantiated. This happens
-/// only if the database can be opened. Note that this is not part of the
-/// CqlLeaseMgr test fixure set. This test checks that the database can be
+/// This test checks if the CqlLeaseMgr can be instantiated. This happens
+/// only if the database can be opened. Note that this is not part of the
+/// CqlLeaseMgr test fixure set. This test checks that the database can be
/// opened: the fixtures assume that and check basic operations.
TEST(CqlOpenTest, OpenDatabase) {
}
// Check that lease manager open the database opens correctly with a longer
- // timeout. If it fails, print the error message.
+ // timeout. If it fails, print the error message.
try {
string connection_string = validCqlConnectionString() + string(" ") +
string(VALID_TIMEOUT);
/// @brief Check conversion functions
///
-/// The server works using cltt and valid_filetime. In the database, the
+/// The server works using cltt and valid_filetime. In the database, the
/// information is stored as expire_time and valid-lifetime, which are
/// related by
///
/// This test checks that the conversion is correct.
TEST_F(CqlLeaseMgrTest, checkTimeConversion) {
const time_t cltt = time(NULL);
+ const uint32_t valid_lft = 86400; // 1 day
+ uint64_t cql_expire;
+
+ // Convert to the database time
+ CqlExchange::convertToDatabaseTime(cltt, valid_lft, cql_expire);
+ // Convert back
time_t converted_cltt = 0;
+ CqlExchange::convertFromDatabaseTime(cql_expire, valid_lft, converted_cltt);
EXPECT_EQ(cltt, converted_cltt);
}
-
/// @brief Check getName() returns correct database name
TEST_F(CqlLeaseMgrTest, getName) {
EXPECT_EQ(std::string("keatest"), lmptr_->getName());
/// will fail. The output of stderr is suppressed unless the parameter,
/// show_err is true.
///
-/// @param force_wipe forces wipe of the database, even if KEA_TEST_CASSANDRA_WIPE
-/// is set.
+/// @param force_wipe forces wipe of the database, even if
+/// KEA_TEST_CASSANDRA_WIPE is set.
/// @param show_err flag which governs whether or not stderr is suppressed.
void destroyCqlSchema(bool force_wipe, bool show_err = false);
/// will fail. The output of stderr is suppressed unless the parameter,
/// show_err is true.
///
-/// @param force_wipe forces wipe of the database, even if KEA_TEST_CASSANDRA_WIPE
-/// is set.
+/// @param force_wipe forces wipe of the database, even if
+/// KEA_TEST_CASSANDRA_WIPE is set.
/// @param show_err flag which governs whether or not stderr is suppressed.
void createCqlSchema(bool force_wipe, bool show_err = false);
/// @brief Run a CQL script against the CQL unit test database
///
/// Submits the given SQL script to CQL via cqlsh CLI. The output of
-/// stderr is suppressed unless the parameter, show_err is true. The is done
+/// stderr is suppressed unless the parameter, show_err is true. The is done
/// to suppress warnings that might otherwise make test output needlessly
-/// noisy. A gtest assertion occurs if the script fails to execute.
+/// noisy. A gtest assertion occurs if the script fails to execute.
///
/// @param path - path (if not blank) of the script to execute
/// @param script_name - file name of the path to execute
name varchar, -- Name of the lease type
PRIMARY KEY (lease_type)
);
---START TRANSACTION;
INSERT INTO lease6_types (lease_type, name) VALUES (0, 'IA_NA'); -- Non-temporary v6 addresses
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
---COMMIT;
-- 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
-- This table is only modified during schema upgrades. For historical reasons
-- (related to the names of the columns in the BIND 10 DNS database file), the
-- first column is called "version" and not "major".
-
--- NOTE: this MUST be kept in step with src/lib/dhcpsrv/tests/schema_copy.h,
--- which defines the schema for the unit tests. If you are updating
--- the version number, the schema has changed: please ensure that
--- schema_copy.h has been updated as well.
CREATE TABLE schema_version (
version int,
minor int,
PRIMARY KEY (version)
);
---START TRANSACTION;
INSERT INTO schema_version (version, minor) VALUES (1, 0);
---COMMIT;
# This table is only modified during schema upgrades. For historical reasons
# (related to the names of the columns in the BIND 10 DNS database file), the
# first column is called "version" and not "major".
-#
-# NOTE: this MUST be kept in step with src/lib/dhcpsrv/tests/schema_copy.h,
-# which defines the schema for the unit tests. If you are updating
-# the version number, the schema has changed: please ensure that
-# schema_copy.h has been updated as well.
CREATE TABLE schema_version (
version INT PRIMARY KEY NOT NULL, # Major version number
minor INT # Minor version number
-- This table is only modified during schema upgrades. For historical reasons
-- (related to the names of the columns in the BIND 10 DNS database file), the
-- first column is called "version" and not "major".
-
--- NOTE: this MUST be kept in step with src/lib/dhcpsrv/tests/schema_copy.h,
--- which defines the schema for the unit tests. If you are updating
--- the version number, the schema has changed: please ensure that
--- schema_copy.h has been updated as well.
CREATE TABLE schema_version (
version INT PRIMARY KEY NOT NULL, -- Major version number
minor INT -- Minor version number