/// @param host Pointer to the new @c Host object being added.
virtual void add(const HostPtr& host) = 0;
+ /// @brief Attempts to delete a host by (subnet-id, address)
+ ///
+ /// This method supports both v4 and v6.
+ ///
+ /// @param subnet_id subnet identfier.
+ /// @param addr specified address.
+ /// @return true if deletion was successful, false otherwise.
+ virtual bool del(const SubnetID& subnet_id, const asiolink::IOAddress& addr) = 0;
+
+ /// @brief Attempts to delete a host by (subnet-id4, identifier, identifier-type)
+ ///
+ /// This method supports both v4 hosts only.
+ ///
+ /// @param subnet_id IPv4 Subnet identifier.
+ /// @param identifier_type Identifier type.
+ /// @param identifier_begin Pointer to a beginning of a buffer containing
+ /// an identifier.
+ /// @param identifier_len Identifier length.
+ /// @return true if deletion was successful, false otherwise.
+ virtual bool del4(const SubnetID& subnet_id,
+ const Host::IdentifierType& identifier_type,
+ const uint8_t* identifier_begin, const size_t identifier_len) = 0;
+
+ /// @brief Attempts to delete a host by (subnet-id6, identifier, identifier-type)
+ ///
+ /// This method supports both v6 hosts only.
+ ///
+ /// @param subnet_id IPv6 Subnet identifier.
+ /// @param identifier_type Identifier type.
+ /// @param identifier_begin Pointer to a beginning of a buffer containing
+ /// an identifier.
+ /// @param identifier_len Identifier length.
+ /// @return true if deletion was successful, false otherwise.
+ virtual bool del6(const SubnetID& subnet_id,
+ const Host::IdentifierType& identifier_type,
+ const uint8_t* identifier_begin, const size_t identifier_len) = 0;
+
+
/// @brief Return backend type
///
/// Returns the type of the backend (e.g. "mysql", "memfile" etc.)
}
}
+bool
+CfgHosts::del(const SubnetID& subnet_id, const asiolink::IOAddress& addr) {
+ /// @todo: Implement host removal
+ isc_throw(NotImplemented, "sorry, not implemented");
+ return (false);
+}
+
+bool
+CfgHosts::del4(const SubnetID& subnet_id,
+ const Host::IdentifierType& identifier_type,
+ const uint8_t* identifier_begin, const size_t identifier_len) {
+ /// @todo: Implement host removal
+ isc_throw(NotImplemented, "sorry, not implemented");
+ return (false);
+}
+
+bool
+CfgHosts::del6(const SubnetID& subnet_id,
+ const Host::IdentifierType& identifier_type,
+ const uint8_t* identifier_begin, const size_t identifier_len) {
+ /// @todo: Implement host removal
+ isc_throw(NotImplemented, "sorry, not implemented");
+ return (false);
+}
+
ElementPtr
CfgHosts::toElement() const {
uint16_t family = CfgMgr::instance().getFamily();
/// has already been added to the IPv4 or IPv6 subnet.
virtual void add(const HostPtr& host);
+ /// @brief Attempts to delete a host by address.
+ ///
+ /// This method supports both v4 and v6.
+ /// @todo: Not implemented.
+ ///
+ /// @param subnet_id subnet identifier.
+ /// @param addr specified address.
+ virtual bool del(const SubnetID& subnet_id, const asiolink::IOAddress& addr);
+
+ /// @brief Attempts to delete a host by (subnet4-id, identifier, identifier-type)
+ ///
+ /// This method supports v4 only.
+ /// @todo: Not implemented.
+ ///
+ /// @param subnet_id IPv4 Subnet identifier.
+ /// @param identifier_type Identifier type.
+ /// @param identifier_begin Pointer to a beginning of a buffer containing
+ /// an identifier.
+ /// @param identifier_len Identifier length.
+ /// @return true if deletion was successful, false otherwise.
+ virtual bool del4(const SubnetID& subnet_id,
+ const Host::IdentifierType& identifier_type,
+ const uint8_t* identifier_begin, const size_t identifier_len);
+
+ /// @brief Attempts to delete a host by (subnet6-id, identifier, identifier-type)
+ ///
+ /// This method supports v6 only.
+ /// @todo: Not implemented.
+ ///
+ /// @param subnet_id IPv6 Subnet identifier.
+ /// @param identifier_type Identifier type.
+ /// @param identifier_begin Pointer to a beginning of a buffer containing
+ /// an identifier.
+ /// @param identifier_len Identifier length.
+ /// @return true if deletion was successful, false otherwise.
+ virtual bool del6(const SubnetID& subnet_id,
+ const Host::IdentifierType& identifier_type,
+ const uint8_t* identifier_begin, const size_t identifier_len);
+
/// @brief Return backend type
///
/// Returns the type of the backend (e.g. "mysql", "memfile" etc.)
alternate_source_->add(host);
}
+bool
+HostMgr::del(const SubnetID& subnet_id, const asiolink::IOAddress& addr) {
+ if (!alternate_source_) {
+ isc_throw(NoHostDataSourceManager, "unable to delete a host because there is "
+ "no alternate host data source present");
+ }
+
+ return (alternate_source_->del(subnet_id, addr));
+}
+
+bool
+HostMgr::del4(const SubnetID& subnet_id, const Host::IdentifierType& identifier_type,
+ const uint8_t* identifier_begin, const size_t identifier_len) {
+ if (!alternate_source_) {
+ isc_throw(NoHostDataSourceManager, "unable to delete a host because there is "
+ "no alternate host data source present");
+ }
+
+ return (alternate_source_->del4(subnet_id, identifier_type,
+ identifier_begin, identifier_len));
+}
+
+bool
+HostMgr::del6(const SubnetID& subnet_id, const Host::IdentifierType& identifier_type,
+ const uint8_t* identifier_begin, const size_t identifier_len) {
+ if (!alternate_source_) {
+ isc_throw(NoHostDataSourceManager, "unable to delete a host because there is "
+ "no alternate host data source present");
+ }
+
+ return (alternate_source_->del6(subnet_id, identifier_type,
+ identifier_begin, identifier_len));
+}
+
} // end of isc::dhcp namespace
} // end of isc namespace
alternate_source_ = source;
}
+ /// @brief Attempts to delete a host by address.
+ ///
+ /// This method supports both v4 and v6.
+ ///
+ /// @param subnet_id subnet identifier.
+ /// @param addr specified address.
+ /// @return true if deletion was successful, false otherwise.
+ virtual bool del(const SubnetID& subnet_id, const asiolink::IOAddress& addr);
+
+ /// @brief Attempts to delete a host by (subnet4-id, identifier, identifier-type)
+ ///
+ /// This method supports v4 only.
+ ///
+ /// @param subnet_id IPv4 Subnet identifier.
+ /// @param identifier_type Identifier type.
+ /// @param identifier_begin Pointer to a beginning of a buffer containing
+ /// an identifier.
+ /// @param identifier_len Identifier length.
+ /// @return true if deletion was successful, false otherwise.
+ virtual bool
+ del4(const SubnetID& subnet_id, const Host::IdentifierType& identifier_type,
+ const uint8_t* identifier_begin, const size_t identifier_len);
+
+ /// @brief Attempts to delete a host by (subnet6-id, identifier, identifier-type)
+ ///
+ /// This method supports v6 only.
+ ///
+ /// @param subnet_id IPv6 Subnet identifier.
+ /// @param identifier_type Identifier type.
+ /// @param identifier_begin Pointer to a beginning of a buffer containing
+ /// an identifier.
+ /// @param identifier_len Identifier length.
+ /// @return true if deletion was successful, false otherwise.
+ virtual bool
+ del6(const SubnetID& subnet_id, const Host::IdentifierType& identifier_type,
+ const uint8_t* identifier_begin, const size_t identifier_len);
+
private:
/// @brief Private default constructor.
INSERT_V6_RESRV, // Insert v6 reservation
INSERT_V4_OPTION, // Insert DHCPv4 option
INSERT_V6_OPTION, // Insert DHCPv6 option
+ DEL_HOST_ADDR4, // Delete v4 host (subnet-id, addr4)
+ DEL_HOST_SUBID4_ID, // Delete v4 host (subnet-id, ident.type, identifier)
+ DEL_HOST_SUBID6_ID, // Delete v6 host (subnet-id, ident.type, identifier)
NUM_STATEMENTS // Number of statements
};
void addStatement(MySqlHostDataSourceImpl::StatementIndex stindex,
std::vector<MYSQL_BIND>& bind);
+ /// @brief Executes statements that delete records.
+ ///
+ /// @param stindex Index of a statement being executed.
+ /// @param bind Vector of MYSQL_BIND objects to be used when making the
+ /// query.
+ /// @return true if any records were deleted, false otherwise
+ bool
+ delStatement(StatementIndex stindex, MYSQL_BIND* bind);
+
/// @brief Inserts IPv6 Reservation into ipv6_reservation table.
///
/// @param resv IPv6 Reservation to be added
{MySqlHostDataSourceImpl::INSERT_V6_OPTION,
"INSERT INTO dhcp6_options(option_id, code, value, formatted_value, space, "
"persistent, dhcp_client_class, dhcp6_subnet_id, host_id, scope_id) "
- " VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, 3)"}}
+ " VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, 3)"},
+
+ {MySqlHostDataSourceImpl::DEL_HOST_ADDR4,
+ "DELETE FROM hosts WHERE dhcp4_subnet_id = ? AND ipv4_address = ?"},
+
+ {MySqlHostDataSourceImpl::DEL_HOST_SUBID4_ID,
+ "DELETE FROM hosts WHERE dhcp4_subnet_id = ? AND dhcp_identifier_type=? "
+ "AND dhcp_identifier = ?"},
+
+ {MySqlHostDataSourceImpl::DEL_HOST_SUBID6_ID,
+ "DELETE FROM hosts WHERE dhcp6_subnet_id = ? AND dhcp_identifier_type=? "
+ "AND dhcp_identifier = ?"}
+
+ }
};
MySqlHostDataSourceImpl::
}
}
+bool
+MySqlHostDataSourceImpl::delStatement(StatementIndex stindex,
+ MYSQL_BIND* bind) {
+ // Bind the parameters to the statement
+ int status = mysql_stmt_bind_param(conn_.statements_[stindex], &bind[0]);
+ checkError(status, stindex, "unable to bind parameters");
+
+ // Execute the statement
+ status = mysql_stmt_execute(conn_.statements_[stindex]);
+
+ if (status != 0) {
+ checkError(status, stindex, "unable to execute");
+ }
+
+ // Let's check how many hosts were deleted.
+ my_ulonglong numrows = mysql_stmt_affected_rows(conn_.statements_[stindex]);
+ return (numrows != 0);
+}
+
void
MySqlHostDataSourceImpl::addResv(const IPv6Resrv& resv,
const HostID& id) {
transaction.commit();
}
+bool
+MySqlHostDataSource::del(const SubnetID& subnet_id, const asiolink::IOAddress& addr) {
+ // If operating in read-only mode, throw exception.
+ impl_->checkReadOnly();
+
+ if (addr.isV4()) {
+ // Set up the WHERE clause value
+ MYSQL_BIND inbind[2];
+
+ uint32_t subnet = subnet_id;
+ memset(inbind, 0, sizeof(inbind));
+ inbind[0].buffer_type = MYSQL_TYPE_LONG;
+ inbind[0].buffer = reinterpret_cast<char*>(&subnet);
+ inbind[0].is_unsigned = MLM_TRUE;
+
+ uint32_t addr4 = addr.toUint32();
+ inbind[1].buffer_type = MYSQL_TYPE_LONG;
+ inbind[1].buffer = reinterpret_cast<char*>(&addr4);
+ inbind[1].is_unsigned = MLM_TRUE;
+
+ ConstHostCollection collection;
+ return (impl_->delStatement(MySqlHostDataSourceImpl::DEL_HOST_ADDR4, inbind));
+ }
+
+ // v6
+ ConstHostPtr host = get6(subnet_id, addr);
+ if (!host) {
+ return (false);
+ }
+
+ // Ok, there is a host. Let's delete it.
+ return del6(subnet_id, host->getIdentifierType(), &host->getIdentifier()[0],
+ host->getIdentifier().size());
+}
+
+bool
+MySqlHostDataSource::del4(const SubnetID& subnet_id,
+ const Host::IdentifierType& identifier_type,
+ const uint8_t* identifier_begin, const size_t identifier_len) {
+ // If operating in read-only mode, throw exception.
+ impl_->checkReadOnly();
+
+ // Set up the WHERE clause value
+ MYSQL_BIND inbind[3];
+
+ // subnet-id
+ memset(inbind, 0, sizeof(inbind));
+ uint32_t subnet = static_cast<uint32_t>(subnet_id);
+ inbind[0].buffer_type = MYSQL_TYPE_LONG;
+ inbind[0].buffer = reinterpret_cast<char*>(&subnet);
+ inbind[0].is_unsigned = MLM_TRUE;
+
+ // identifier type
+ char identifier_type_copy = static_cast<char>(identifier_type);
+ inbind[1].buffer_type = MYSQL_TYPE_TINY;
+ inbind[1].buffer = reinterpret_cast<char*>(&identifier_type_copy);
+ inbind[1].is_unsigned = MLM_TRUE;
+
+ // identifier value
+ std::vector<char> identifier_vec(identifier_begin,
+ identifier_begin + identifier_len);
+ unsigned long length = identifier_vec.size();
+ inbind[2].buffer_type = MYSQL_TYPE_BLOB;
+ inbind[2].buffer = &identifier_vec[0];
+ inbind[2].buffer_length = length;
+ inbind[2].length = &length;
+
+ ConstHostCollection collection;
+ return (impl_->delStatement(MySqlHostDataSourceImpl::DEL_HOST_SUBID4_ID, inbind));
+}
+
+bool
+MySqlHostDataSource::del6(const SubnetID& subnet_id,
+ const Host::IdentifierType& identifier_type,
+ const uint8_t* identifier_begin, const size_t identifier_len) {
+ // If operating in read-only mode, throw exception.
+ impl_->checkReadOnly();
+
+ // Set up the WHERE clause value
+ MYSQL_BIND inbind[3];
+
+ // subnet-id
+ memset(inbind, 0, sizeof(inbind));
+ uint32_t subnet = static_cast<uint32_t>(subnet_id);
+ inbind[0].buffer_type = MYSQL_TYPE_LONG;
+ inbind[0].buffer = reinterpret_cast<char*>(&subnet);
+ inbind[0].is_unsigned = MLM_TRUE;
+
+ // identifier type
+ char identifier_type_copy = static_cast<char>(identifier_type);
+ inbind[1].buffer_type = MYSQL_TYPE_TINY;
+ inbind[1].buffer = reinterpret_cast<char*>(&identifier_type_copy);
+ inbind[1].is_unsigned = MLM_TRUE;
+
+ // identifier value
+ std::vector<char> identifier_vec(identifier_begin,
+ identifier_begin + identifier_len);
+ unsigned long length = identifier_vec.size();
+ inbind[2].buffer_type = MYSQL_TYPE_BLOB;
+ inbind[2].buffer = &identifier_vec[0];
+ inbind[2].buffer_length = length;
+ inbind[2].length = &length;
+
+ ConstHostCollection collection;
+ return (impl_->delStatement(MySqlHostDataSourceImpl::DEL_HOST_SUBID6_ID, inbind));
+}
+
ConstHostCollection
MySqlHostDataSource::getAll(const HWAddrPtr& hwaddr,
const DuidPtr& duid) const {
/// @param host Pointer to the new @c Host object being added.
virtual void add(const HostPtr& host);
+ /// @brief Attempts to delete a host by (subnet-id, address)
+ ///
+ /// This method supports both v4 and v6.
+ ///
+ /// @param subnet_id subnet identfier.
+ /// @param addr specified address.
+ /// @return true if deletion was successful, false otherwise.
+ virtual bool del(const SubnetID& subnet_id, const asiolink::IOAddress& addr);
+
+ /// @brief Attempts to delete a host by (subnet4-id, identifier type, identifier)
+ ///
+ /// This method supports v4 hosts only.
+ ///
+ /// @param subnet_id subnet identfier.
+ /// @param addr specified address.
+ /// @return true if deletion was successful, false otherwise.
+ virtual bool del4(const SubnetID& subnet_id,
+ const Host::IdentifierType& identifier_type,
+ const uint8_t* identifier_begin, const size_t identifier_len);
+
+ /// @brief Attempts to delete a host by (subnet6-id, identifier type, identifier)
+ ///
+ /// This method supports v6 hosts only.
+ ///
+ /// @param subnet_id subnet identfier.
+ /// @param addr specified address.
+ /// @return true if deletion was successful, false otherwise.
+ virtual bool del6(const SubnetID& subnet_id,
+ const Host::IdentifierType& identifier_type,
+ const uint8_t* identifier_begin, const size_t identifier_len);
+
/// @brief Return backend type
///
/// Returns the type of the backend (e.g. "mysql", "memfile" etc.)
/// DHCPv6 options.
///
/// The following are the basic functions of this class:
- /// - bind class members to specific columns in MySQL binding tables,
+ /// - bind class members to specific columns in PgSQL binding tables,
/// - set DHCP options specific column names,
/// - create instances of options retrieved from the database.
///
/// @brief Creates IPv6 reservation from the data contained in the
/// currently processed row.
///
- /// Called after the MYSQL_BIND array created by createBindForReceive().
- ///
/// @return IPv6Resrv object (containing IPv6 address or prefix reservation)
IPv6Resrv retrieveReservation(const PgSqlResult& r, int row) {
};
-/// @brief This class is used for storing IPv6 reservations in a MySQL database.
+/// @brief This class is used for storing IPv6 reservations in a PgSQL database.
///
/// This class is only used to insert IPv6 reservations into the
/// ipv6_reservations table. It is not used to retrieve IPv6 reservations. To
INSERT_V6_RESRV, // Insert v6 reservation
INSERT_V4_HOST_OPTION, // Insert DHCPv4 option
INSERT_V6_HOST_OPTION, // Insert DHCPv6 option
+ DEL_HOST_ADDR4, // Delete v4 host (subnet-id, addr4)
+ DEL_HOST_SUBID4_ID, // Delete v4 host (subnet-id, ident.type, identifier)
+ DEL_HOST_SUBID6_ID, // Delete v6 host (subnet-id, ident.type, identifier)
NUM_STATEMENTS // Number of statements
};
/// @brief Executes statements which insert a row into one of the tables.
///
/// @param stindex Index of a statement being executed.
- /// @param bind Vector of MYSQL_BIND objects to be used when making the
- /// query.
+ /// @param bind Vector of PgsqlBindArray objects to be used for the query
/// @param return_last_id flag indicating whether or not the insert
/// returns the primary key of from the row inserted via " RETURNING
/// <primary key> as pid" clause on the INSERT statement. The RETURNING
PsqlBindArrayPtr& bind,
const bool return_last_id = false);
+ /// @brief Executes statements that delete records.
+ ///
+ /// @param stindex Index of a statement being executed.
+ /// @param bind pointer to PsqlBindArray objects to be used for the query
+ /// @return true if any records were deleted, false otherwise
+ bool delStatement(PgSqlHostDataSourceImpl::StatementIndex stindex,
+ PsqlBindArrayPtr& bind);
+
/// @brief Inserts IPv6 Reservation into ipv6_reservation table.
///
/// @param resv IPv6 Reservation to be added
/// @param stindex Index of a statement being executed.
/// @param options_cfg An object holding a collection of options to be
/// inserted into the database.
- /// @param host_id Host identifier retrieved using @c mysql_insert_id.
+ /// @param host_id Host identifier retrieved using getColumnValue
+ /// in addStatement method
void addOptions(const StatementIndex& stindex,
const ConstCfgOptionPtr& options_cfg,
const uint64_t host_id);
/// @ref Host objects depends on the type of the exchange object.
///
/// @param stindex Statement index.
- /// @param bind Pointer to an array of MySQL bindings.
+ /// @param bind Pointer to an array of PgSQL bindings.
/// @param exchange Pointer to the exchange object used for the
/// particular query.
/// @param [out] result Reference to the collection of hosts returned.
/// or dhcp6_options table.
boost::shared_ptr<PgSqlOptionExchange> host_option_exchange_;
- /// @brief MySQL connection
+ /// @brief PgSQL connection
PgSqlConnection conn_;
/// @brief Indicates if the database is opened in read only mode.
},
// PgSqlHostDataSourceImpl::GET_VERSION
- // Retrieves MySQL schema version.
+ // Retrieves PgSQL schema version.
{0,
{ OID_NONE },
"get_version",
"INSERT INTO dhcp6_options(code, value, formatted_value, space, "
" persistent, host_id, scope_id) "
"VALUES ($1, $2, $3, $4, $5, $6, 3)"
+ },
+
+ // PgSqlHostDataSourceImpl::DEL_HOST_ADDR4
+ // Deletes a v4 host that matches (subnet-id, addr4)
+ {2,
+ { OID_INT4, OID_INT8 },
+ "del_host_addr4",
+ "DELETE FROM hosts WHERE dhcp4_subnet_id = $1 AND ipv4_address = $2"
+ },
+
+ // PgSqlHostDataSourceImpl::DEL_HOST_SUBID4_ID
+ // Deletes a v4 host that matches (subnet4-id, identifier-type, identifier)
+ {3,
+ { OID_INT4, OID_INT2, OID_BYTEA },
+ "del_host_subid4_id",
+ "DELETE FROM hosts WHERE dhcp4_subnet_id = $1 "
+ "AND dhcp_identifier_type = $2 "
+ "AND dhcp_identifier = $3"
+ },
+
+ // PgSqlHostDataSourceImpl::DEL_HOST_SUBID6_ID
+ // Deletes a v6 host that matches (subnet6-id, identifier-type, identifier)
+ {3,
+ { OID_INT4, OID_INT2, OID_BYTEA },
+ "del_host_subid6_id",
+ "DELETE FROM hosts WHERE dhcp6_subnet_id = $1 "
+ "AND dhcp_identifier_type = $2 "
+ "AND dhcp_identifier = $3"
}
}
};
}
+bool
+PgSqlHostDataSourceImpl::delStatement(StatementIndex stindex,
+ PsqlBindArrayPtr& bind_array) {
+ PgSqlResult r(PQexecPrepared(conn_, tagged_statements[stindex].name,
+ tagged_statements[stindex].nbparams,
+ &bind_array->values_[0],
+ &bind_array->lengths_[0],
+ &bind_array->formats_[0], 0));
+
+ int s = PQresultStatus(r);
+
+ if (s != PGRES_COMMAND_OK) {
+ // Connection determines if the error is fatal or not, and
+ // throws the appropriate exception
+ conn_.checkStatementError(r, tagged_statements[stindex]);
+ }
+
+ // Now check how many rows (hosts) were deleted. This should be either
+ // "0" or "1".
+ char* rows_deleted = PQcmdTuples(r);
+ if (!rows_deleted) {
+ isc_throw(DbOperationError,
+ "Could not retrieve the number of deleted rows.");
+ }
+ return (rows_deleted[0] != '0');
+}
+
void
PgSqlHostDataSourceImpl::addResv(const IPv6Resrv& resv,
const HostID& id) {
// the PgSqlTransaction class.
PgSqlTransaction transaction(impl_->conn_);
- // Create the MYSQL_BIND array for the host
+ // Create the PgSQL Bind array for the host
PsqlBindArrayPtr bind_array = impl_->host_exchange_->createBindForSend(host);
// ... and insert the host.
transaction.commit();
}
+bool
+PgSqlHostDataSource::del(const SubnetID& subnet_id, const asiolink::IOAddress& addr) {
+ // If operating in read-only mode, throw exception.
+ impl_->checkReadOnly();
+
+ if (addr.isV4()) {
+ PsqlBindArrayPtr bind_array(new PsqlBindArray());
+ bind_array->add(subnet_id);
+ bind_array->add(addr);
+ return (impl_->delStatement(PgSqlHostDataSourceImpl::DEL_HOST_ADDR4,
+ bind_array));
+ }
+
+ ConstHostPtr host = get6(subnet_id, addr);
+ if (!host) {
+ return (false);
+ }
+
+ return del6(subnet_id, host->getIdentifierType(), &host->getIdentifier()[0],
+ host->getIdentifier().size());
+}
+
+bool
+PgSqlHostDataSource::del4(const SubnetID& subnet_id,
+ const Host::IdentifierType& identifier_type,
+ const uint8_t* identifier_begin,
+ const size_t identifier_len) {
+
+ PsqlBindArrayPtr bind_array(new PsqlBindArray());
+
+ // Subnet-id
+ bind_array->add(subnet_id);
+
+ // identifier-type
+ bind_array->add(static_cast<uint8_t>(identifier_type));
+
+ // identifier
+ bind_array->add(identifier_begin, identifier_len);
+
+ return (impl_->delStatement(PgSqlHostDataSourceImpl::DEL_HOST_SUBID4_ID,
+ bind_array));
+
+}
+
+bool
+PgSqlHostDataSource::del6(const SubnetID& subnet_id,
+ const Host::IdentifierType& identifier_type,
+ const uint8_t* identifier_begin,
+ const size_t identifier_len) {
+ PsqlBindArrayPtr bind_array(new PsqlBindArray());
+
+ // Subnet-id
+ bind_array->add(subnet_id);
+
+ // identifier-type
+ bind_array->add(static_cast<uint8_t>(identifier_type));
+
+ // identifier
+ bind_array->add(identifier_begin, identifier_len);
+
+ return (impl_->delStatement(PgSqlHostDataSourceImpl::DEL_HOST_SUBID6_ID,
+ bind_array));
+
+}
+
ConstHostCollection
PgSqlHostDataSource::getAll(const HWAddrPtr& hwaddr,
const DuidPtr& duid) const {
/// @todo: Rethink the logic in BaseHostDataSource::get4(subnet, hwaddr, duid)
if (hwaddr && duid) {
- isc_throw(BadValue, "MySQL host data source get4() called with both"
+ isc_throw(BadValue, "PgSQL host data source get4() called with both"
" hwaddr and duid, only one of them is allowed");
}
if (!hwaddr && !duid) {
- isc_throw(BadValue, "MySQL host data source get4() called with "
+ isc_throw(BadValue, "PgSQL host data source get4() called with "
"neither hwaddr or duid specified, one of them is required");
}
/// @todo: Rethink the logic in BaseHostDataSource::get6(subnet, hwaddr, duid)
if (hwaddr && duid) {
- isc_throw(BadValue, "MySQL host data source get6() called with both"
+ isc_throw(BadValue, "PgSQL host data source get6() called with both"
" hwaddr and duid, only one of them is allowed");
}
if (!hwaddr && !duid) {
- isc_throw(BadValue, "MySQL host data source get6() called with "
+ isc_throw(BadValue, "PgSQL host data source get6() called with "
"neither hwaddr or duid specified, one of them is required");
}
/// violation
virtual void add(const HostPtr& host);
+ /// @brief Attempts to delete a host by (subnet-id, address)
+ ///
+ /// This method supports both v4 and v6.
+ ///
+ /// @param subnet_id subnet identfier.
+ /// @param addr specified address.
+ /// @return true if deletion was successful, false otherwise.
+ virtual bool del(const SubnetID& subnet_id, const asiolink::IOAddress& addr);
+
+ /// @brief Attempts to delete a host by (subnet4-id, identifier type, identifier)
+ ///
+ /// This method supports v4 hosts only.
+ ///
+ /// @param subnet_id subnet identfier.
+ /// @param addr specified address.
+ /// @return true if deletion was successful, false otherwise.
+ virtual bool del4(const SubnetID& subnet_id,
+ const Host::IdentifierType& identifier_type,
+ const uint8_t* identifier_begin, const size_t identifier_len);
+
+ /// @brief Attempts to delete a host by (subnet6-id, identifier type, identifier)
+ ///
+ /// This method supports v6 hosts only.
+ ///
+ /// @param subnet_id subnet identfier.
+ /// @param addr specified address.
+ /// @return true if deletion was successful, false otherwise.
+ virtual bool del6(const SubnetID& subnet_id,
+ const Host::IdentifierType& identifier_type,
+ const uint8_t* identifier_begin, const size_t identifier_len);
+
/// @brief Return backend type
///
/// Returns the type of database as the string "postgresql". This is
ASSERT_NO_FATAL_FAILURE(compareHosts(host, from_hds));
}
+void GenericHostDataSourceTest::testDeleteByAddr4() {
+ // Make sure we have a pointer to the host data source.
+ ASSERT_TRUE(hdsptr_);
+
+ // Let's create a v4 host...
+ HostPtr host1 = initializeHost4("192.0.2.1", Host::IDENT_HWADDR);
+ SubnetID subnet1 = host1->getIPv4SubnetID();
+
+ // ... and add it to the data source.
+ ASSERT_NO_THROW(hdsptr_->add(host1));
+
+ // And then try to retrieve it back.
+ ConstHostPtr before = hdsptr_->get4(subnet1, IOAddress("192.0.2.1"));
+
+ // Now try to delete it: del(subnet-id, addr4)
+ EXPECT_TRUE(hdsptr_->del(subnet1, IOAddress("192.0.2.1")));
+
+ // Check if it's still there.
+ ConstHostPtr after = hdsptr_->get4(subnet1, IOAddress("192.0.2.1"));
+
+ // Make sure the host was there before...
+ EXPECT_TRUE(before);
+
+ // ... and that it's gone after deletion.
+ EXPECT_FALSE(after);
+}
+
+void GenericHostDataSourceTest::testDeleteById4() {
+ // Make sure we have a pointer to the host data source.
+ ASSERT_TRUE(hdsptr_);
+
+ // Let's create a v4 host...
+ HostPtr host1 = initializeHost4("192.0.2.1", Host::IDENT_HWADDR);
+ SubnetID subnet1 = host1->getIPv4SubnetID();
+
+ // ... and add it to the data source.
+ ASSERT_NO_THROW(hdsptr_->add(host1));
+
+ // And then try to retrieve it back.
+ ConstHostPtr before = hdsptr_->get4(subnet1,
+ host1->getIdentifierType(),
+ &host1->getIdentifier()[0],
+ host1->getIdentifier().size());
+
+ // Now try to delete it: del4(subnet4-id, identifier-type, identifier)
+ EXPECT_TRUE(hdsptr_->del4(subnet1, host1->getIdentifierType(),
+ &host1->getIdentifier()[0],
+ host1->getIdentifier().size()));
+
+ // Check if it's still there.
+ ConstHostPtr after = hdsptr_->get4(subnet1,
+ host1->getIdentifierType(),
+ &host1->getIdentifier()[0],
+ host1->getIdentifier().size());
+
+ // Make sure the host was there before...
+ EXPECT_TRUE(before);
+
+ // ... and that it's gone after deletion.
+ EXPECT_FALSE(after);
+}
+
+void GenericHostDataSourceTest::testDeleteById6() {
+ // Make sure we have a pointer to the host data source.
+ ASSERT_TRUE(hdsptr_);
+
+ // Let's create a v6 host...
+ HostPtr host1 = initializeHost6("2001:db8::1", Host::IDENT_DUID, false);
+ SubnetID subnet1 = host1->getIPv6SubnetID();
+
+ // ... and add it to the data source.
+ ASSERT_NO_THROW(hdsptr_->add(host1));
+
+ // And then try to retrieve it back.
+ ConstHostPtr before = hdsptr_->get6(subnet1,
+ host1->getIdentifierType(),
+ &host1->getIdentifier()[0],
+ host1->getIdentifier().size());
+
+ // Now try to delete it: del4(subnet4-id, identifier-type, identifier)
+ EXPECT_TRUE(hdsptr_->del6(subnet1, host1->getIdentifierType(),
+ &host1->getIdentifier()[0],
+ host1->getIdentifier().size()));
+
+ // Check if it's still there.
+ ConstHostPtr after = hdsptr_->get6(subnet1,
+ host1->getIdentifierType(),
+ &host1->getIdentifier()[0],
+ host1->getIdentifier().size());
+
+ // Make sure the host was there before...
+ EXPECT_TRUE(before);
+
+ // ... and that it's gone after deletion.
+ EXPECT_FALSE(after);
+}
+
}; // namespace test
}; // namespace dhcp
}; // namespace isc
/// from a database for a host.
///
/// Uses gtest macros to report failures.
- ///
void testMessageFields4();
+ /// @brief Tests that delete(subnet-id, addr4) call works.
+ ///
+ /// Uses gtest macros to report failures.
+ void testDeleteByAddr4();
+
+ /// @brief Tests that delete(subnet4-id, identifier-type, identifier) works.
+ ///
+ /// Uses gtest macros to report failures.
+ void testDeleteById4();
+
+ /// @brief Tests that delete(subnet6-id, identifier-type, identifier) works.
+ ///
+ /// Uses gtest macros to report failures.
+ void testDeleteById6();
+
/// @brief Returns DUID with identical content as specified HW address
///
/// This method does not have any sense in real life and is only useful
-// Copyright (C) 2015-2016 Internet Systems Consortium, Inc. ("ISC")
+// Copyright (C) 2015-2017 Internet Systems Consortium, Inc. ("ISC")
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
testMessageFields4();
}
+// Check that delete(subnet-id, addr4) works.
+TEST_F(MySqlHostDataSourceTest, deleteByAddr4) {
+ testDeleteByAddr4();
+}
+
+// Check that delete(subnet4-id, identifier-type, identifier) works.
+TEST_F(MySqlHostDataSourceTest, deleteById4) {
+ testDeleteById4();
+}
+
+// Check that delete(subnet6-id, identifier-type, identifier) works.
+TEST_F(MySqlHostDataSourceTest, deleteById6) {
+ testDeleteById6();
+}
+
}; // Of anonymous namespace
-// Copyright (C) 2016 Internet Systems Consortium, Inc. ("ISC")
+// Copyright (C) 2016-2017 Internet Systems Consortium, Inc. ("ISC")
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
testMessageFields4();
}
+// Check that delete(subnet-id, addr4) works.
+TEST_F(PgSqlHostDataSourceTest, deleteByAddr4) {
+ testDeleteByAddr4();
+}
+
+// Check that delete(subnet4-id, identifier-type, identifier) works.
+TEST_F(PgSqlHostDataSourceTest, deleteById4) {
+ testDeleteById4();
+}
+
+// Check that delete(subnet6-id, identifier-type, identifier) works.
+TEST_F(PgSqlHostDataSourceTest, deleteById6) {
+ testDeleteById6();
+}
+
}; // Of anonymous namespace