Commit 19df22ab authored by Michal 'vorner' Vaner's avatar Michal 'vorner' Vaner
Browse files

Merge remote-tracking branch 'origin/trac1976-cont-3' into work/merge

parents 7d5399cb 3359259c
......@@ -221,10 +221,9 @@ private:
AuthSrvImpl(const AuthSrvImpl& source);
AuthSrvImpl& operator=(const AuthSrvImpl& source);
public:
AuthSrvImpl(const bool use_cache, AbstractXfroutClient& xfrout_client,
AuthSrvImpl(AbstractXfroutClient& xfrout_client,
BaseSocketSessionForwarder& ddns_forwarder);
~AuthSrvImpl();
isc::data::ConstElementPtr setDbFile(isc::data::ConstElementPtr config);
bool processNormalQuery(const IOMessage& io_message, Message& message,
OutputBuffer& buffer,
......@@ -247,10 +246,6 @@ public:
ModuleCCSession* config_session_;
AbstractSession* xfrin_session_;
/// In-memory data source. Currently class IN only for simplicity.
/// Hot spot cache
isc::datasrc::HotCache cache_;
/// Interval timer for periodic submission of statistics counters.
IntervalTimer statistics_timer_;
......@@ -313,8 +308,7 @@ private:
auth::Query query_;
};
AuthSrvImpl::AuthSrvImpl(const bool use_cache,
AbstractXfroutClient& xfrout_client,
AuthSrvImpl::AuthSrvImpl(AbstractXfroutClient& xfrout_client,
BaseSocketSessionForwarder& ddns_forwarder) :
config_session_(NULL),
xfrin_session_(NULL),
......@@ -324,10 +318,7 @@ AuthSrvImpl::AuthSrvImpl(const bool use_cache,
xfrout_connected_(false),
xfrout_client_(xfrout_client),
ddns_forwarder_("update", ddns_forwarder)
{
// enable or disable the cache
cache_.setEnabled(use_cache);
}
{}
AuthSrvImpl::~AuthSrvImpl() {
if (xfrout_connected_) {
......@@ -386,11 +377,10 @@ private:
AuthSrv* server_;
};
AuthSrv::AuthSrv(const bool use_cache,
isc::xfr::AbstractXfroutClient& xfrout_client,
AuthSrv::AuthSrv(isc::xfr::AbstractXfroutClient& xfrout_client,
isc::util::io::BaseSocketSessionForwarder& ddns_forwarder)
{
impl_ = new AuthSrvImpl(use_cache, xfrout_client, ddns_forwarder);
impl_ = new AuthSrvImpl(xfrout_client, ddns_forwarder);
checkin_ = new ConfigChecker(this);
dns_lookup_ = new MessageLookup(this);
dns_answer_ = new MessageAnswer(this);
......@@ -469,16 +459,6 @@ AuthSrv::getIOService() {
return (impl_->io_service_);
}
void
AuthSrv::setCacheSlots(const size_t slots) {
impl_->cache_.setSlots(slots);
}
size_t
AuthSrv::getCacheSlots() const {
return (impl_->cache_.getSlots());
}
void
AuthSrv::setXfrinSession(AbstractSession* xfrin_session) {
impl_->xfrin_session_ = xfrin_session;
......
......@@ -92,13 +92,11 @@ private:
public:
/// The constructor.
///
/// \param use_cache Whether to enable hot spot cache for lookup results.
/// \param xfrout_client Communication interface with a separate xfrout
/// process. It's normally a reference to an xfr::XfroutClient object,
/// but can refer to a local mock object for testing (or other
/// experimental) purposes.
AuthSrv(const bool use_cache,
isc::xfr::AbstractXfroutClient& xfrout_client,
AuthSrv(isc::xfr::AbstractXfroutClient& xfrout_client,
isc::util::io::BaseSocketSessionForwarder& ddns_forwarder);
~AuthSrv();
//@}
......@@ -187,26 +185,6 @@ public:
/// \brief Return pointer to the Checkin callback function
isc::asiolink::SimpleCallback* getCheckinProvider() const { return (checkin_); }
/// \brief Set or update the size (number of slots) of hot spot cache.
///
/// If the specified size is 0, it means the size will be unlimited.
/// The specified size is recorded even if the cache is disabled; the
/// new size will be effective when the cache is enabled.
///
/// This method never throws an exception.
///
/// \param slots The number of cache slots.
void setCacheSlots(const size_t slots);
/// \brief Get the current size (number of slots) of hot spot cache.
///
/// It always returns the recorded size regardless of the cache is enabled.
///
/// This method never throws an exception.
///
/// \return The current number of cache slots.
size_t getCacheSlots() const;
/// \brief Set the communication session with a separate process for
/// outgoing zone transfers.
///
......
......@@ -44,7 +44,6 @@
<refsynopsisdiv>
<cmdsynopsis>
<command>b10-auth</command>
<arg><option>-n</option></arg>
<arg><option>-v</option></arg>
</cmdsynopsis>
</refsynopsisdiv>
......@@ -79,18 +78,6 @@
<para>The arguments are as follows:</para>
<variablelist>
<varlistentry>
<term><option>-n</option></term>
<listitem><para>
Do not cache answers in memory.
The default is to use the cache for faster responses.
The cache keeps the most recent 30,000 answers (positive
and negative) in memory for 30 seconds (instead of querying
the data source, such as SQLite3 database, each time).
</para></listitem>
<!-- TODO: this is SQLite3 only -->
</varlistentry>
<varlistentry>
<term><option>-v</option></term>
<listitem><para>
......
......@@ -77,10 +77,9 @@ protected:
private:
typedef boost::shared_ptr<const IOEndpoint> IOEndpointPtr;
protected:
QueryBenchMark(const bool enable_cache,
const BenchQueries& queries, Message& query_message,
QueryBenchMark(const BenchQueries& queries, Message& query_message,
OutputBuffer& buffer) :
server_(new AuthSrv(enable_cache, xfrout_client, ddns_forwarder)),
server_(new AuthSrv(xfrout_client, ddns_forwarder)),
queries_(queries),
query_message_(query_message),
buffer_(buffer),
......@@ -119,17 +118,12 @@ private:
class Sqlite3QueryBenchMark : public QueryBenchMark {
public:
Sqlite3QueryBenchMark(const int cache_slots,
const char* const datasrc_file,
Sqlite3QueryBenchMark(const char* const datasrc_file,
const BenchQueries& queries,
Message& query_message,
OutputBuffer& buffer) :
QueryBenchMark(cache_slots >= 0 ? true : false, queries,
query_message, buffer)
QueryBenchMark(queries, query_message, buffer)
{
if (cache_slots >= 0) {
server_->setCacheSlots(cache_slots);
}
server_->updateConfig(Element::fromJSON("{\"database_file\": \"" +
string(datasrc_file) + "\"}"));
}
......@@ -142,7 +136,7 @@ public:
const BenchQueries& queries,
Message& query_message,
OutputBuffer& buffer) :
QueryBenchMark(false, queries, query_message, buffer)
QueryBenchMark(queries, query_message, buffer)
{
configureAuthServer(*server_,
Element::fromJSON(
......@@ -274,27 +268,9 @@ main(int argc, char* argv[]) {
switch (datasrc_type) {
case SQLITE3:
cout << "Benchmark enabling Hot Spot Cache with unlimited slots "
<< endl;
BenchMark<Sqlite3QueryBenchMark>(
iteration, Sqlite3QueryBenchMark(0, datasrc_file, queries,
message, buffer));
cout << "Benchmark enabling Hot Spot Cache with 10*#queries slots "
<< endl;
BenchMark<Sqlite3QueryBenchMark>(
iteration, Sqlite3QueryBenchMark(10 * queries.size(), datasrc_file,
queries, message, buffer));
cout << "Benchmark enabling Hot Spot Cache with #queries/2 slots "
<< endl;
BenchMark<Sqlite3QueryBenchMark>(
iteration, Sqlite3QueryBenchMark(queries.size() / 2, datasrc_file,
queries, message, buffer));
cout << "Benchmark disabling Hot Spot Cache" << endl;
cout << "Benchmark with SQLite3" << endl;
BenchMark<Sqlite3QueryBenchMark>(
iteration, Sqlite3QueryBenchMark(-1, datasrc_file, queries,
iteration, Sqlite3QueryBenchMark(datasrc_file, queries,
message, buffer));
break;
case MEMORY:
......
......@@ -143,74 +143,52 @@ public:
// Handle the "loadzone" command.
class LoadZoneCommand : public AuthCommand {
public:
LoadZoneCommand() :
zone_class_(RRClass::IN()), // We need to have something to compile
origin_(Name::ROOT_NAME())
{}
virtual void exec(AuthSrv& server, isc::data::ConstElementPtr args) {
// parse and validate the args.
if (!validate(args)) {
return;
if (args == NULL) {
isc_throw(AuthCommandError, "Null argument");
}
ConstElementPtr class_elem = args->get("class");
RRClass zone_class(class_elem ? RRClass(class_elem->stringValue()) :
RRClass::IN());
ConstElementPtr origin_elem = args->get("origin");
if (!origin_elem) {
isc_throw(AuthCommandError, "Zone origin is missing");
}
Name origin(origin_elem->stringValue());
const boost::shared_ptr<isc::datasrc::ConfigurableClientList>
list(server.getClientList(zone_class_));
list(server.getClientList(zone_class));
if (!list) {
isc_throw(AuthCommandError, "There's no client list for "
"class " << zone_class_);
"class " << zone_class);
}
switch (list->reload(origin_)) {
switch (list->reload(origin)) {
case ConfigurableClientList::ZONE_RELOADED:
// Everything worked fine.
LOG_DEBUG(auth_logger, DBG_AUTH_OPS, AUTH_LOAD_ZONE)
.arg(zone_class_).arg(origin_);
.arg(zone_class).arg(origin);
return;
case ConfigurableClientList::ZONE_NOT_FOUND:
isc_throw(AuthCommandError, "Zone " << origin_ << "/" <<
zone_class_ << " was not found in any configure "
isc_throw(AuthCommandError, "Zone " << origin << "/" <<
zone_class << " was not found in any configured "
"data source. Configure it first.");
case ConfigurableClientList::ZONE_NOT_CACHED:
isc_throw(AuthCommandError, "Zone " << origin_ << "/" <<
zone_class_ << " is not served from memory, but "
isc_throw(AuthCommandError, "Zone " << origin << "/" <<
zone_class << " is not served from memory, but "
"direcly from the data source. It is not possible "
"to reload into memory, configure it to be cached "
"to reload it into memory. Configure it to be cached "
"first.");
case ConfigurableClientList::CACHE_DISABLED:
// This is an internal error. Auth server must have the cache
// enabled.
isc_throw(isc::Unexpected, "Cache disabled in client list of "
"class " << zone_class_);
"class " << zone_class);
}
}
private:
// Parsed arguments
RRClass zone_class_;
Name origin_;
// A helper private method to parse and validate command parameters.
// On success, it sets 'old_zone_finder_' to the zone to be updated.
// It returns true if everything is okay; and false if the command is
// valid but there's no need for further process.
bool validate(isc::data::ConstElementPtr args) {
if (args == NULL) {
isc_throw(AuthCommandError, "Null argument");
}
ConstElementPtr class_elem = args->get("class");
zone_class_ = class_elem ? RRClass(class_elem->stringValue()) :
RRClass::IN();
ConstElementPtr origin_elem = args->get("origin");
if (!origin_elem) {
isc_throw(AuthCommandError, "Zone origin is missing");
}
origin_ = Name(origin_elem->stringValue());
return (true);
}
};
// The factory of command objects.
......
......@@ -85,9 +85,8 @@ my_command_handler(const string& command, ConstElementPtr args) {
void
usage() {
cerr << "Usage: b10-auth [-u user] [-nv]"
cerr << "Usage: b10-auth [-v]"
<< endl;
cerr << "\t-n: do not cache answers in memory" << endl;
cerr << "\t-v: verbose logging (debug-level)" << endl;
exit(1);
}
......@@ -97,14 +96,10 @@ usage() {
int
main(int argc, char* argv[]) {
int ch;
bool cache = true;
bool verbose = false;
while ((ch = getopt(argc, argv, ":nu:v")) != -1) {
switch (ch) {
case 'n':
cache = false;
break;
case 'v':
verbose = true;
break;
......@@ -143,7 +138,7 @@ main(int argc, char* argv[]) {
specfile = string(AUTH_SPECFILE_LOCATION);
}
auth_server = new AuthSrv(cache, xfrout_client, ddns_forwarder);
auth_server = new AuthSrv(xfrout_client, ddns_forwarder);
LOG_INFO(auth_logger, AUTH_SERVER_CREATED);
SimpleCallback* checkin = auth_server->getCheckinProvider();
......
......@@ -91,8 +91,7 @@ class AuthSrvTest : public SrvTestBase {
protected:
AuthSrvTest() :
dnss_(),
server(true, xfrout, ddns_forwarder),
rrclass(RRClass::IN()),
server(xfrout, ddns_forwarder),
// The empty string is expected value of the parameter of
// requestSocket, not the app_name (there's no fallback, it checks
// the empty string is passed).
......@@ -182,7 +181,6 @@ protected:
MockXfroutClient xfrout;
MockSocketSessionForwarder ddns_forwarder;
AuthSrv server;
const RRClass rrclass;
vector<uint8_t> response_data;
AddressList address_store_;
TestSocketRequestor sock_requestor_;
......@@ -1034,16 +1032,6 @@ TEST_F(AuthSrvTest,
opcode.getCode(), QR_FLAG | AA_FLAG, 1, 1, 1, 0);
}
TEST_F(AuthSrvTest, cacheSlots) {
// simple check for the get/set operations
server.setCacheSlots(10); // 10 = arbitrary choice
EXPECT_EQ(10, server.getCacheSlots());
// 0 is a valid size
server.setCacheSlots(0);
EXPECT_EQ(00, server.getCacheSlots());
}
// Submit UDP normal query and check query counter
TEST_F(AuthSrvTest, queryCounterUDPNormal) {
// The counter should be initialized to 0.
......@@ -1679,7 +1667,7 @@ TEST_F(AuthSrvTest, DDNSForwardPushFail) {
}
TEST_F(AuthSrvTest, DDNSForwardClose) {
scoped_ptr<AuthSrv> tmp_server(new AuthSrv(true, xfrout, ddns_forwarder));
scoped_ptr<AuthSrv> tmp_server(new AuthSrv(xfrout, ddns_forwarder));
UnitTestUtil::createRequestMessage(request_message, Opcode::UPDATE(),
default_qid, Name("example.com"),
RRClass::IN(), RRType::SOA());
......
......@@ -63,7 +63,7 @@ namespace {
class AuthCommandTest : public ::testing::Test {
protected:
AuthCommandTest() :
server_(false, xfrout_, ddns_forwarder_),
server_(xfrout_, ddns_forwarder_),
rcode_(-1),
expect_rcode_(0),
itimer_(server_.getIOService())
......@@ -311,7 +311,7 @@ TEST_F(AuthCommandTest,
result_ = execAuthServerCommand(server_, "loadzone",
Element::fromJSON(
"{\"origin\": \"example.org\"}"));
checkAnswer(0, "Successfull load");
checkAnswer(0, "Successful load");
// And now it should be present too.
EXPECT_EQ(ZoneFinder::SUCCESS, server_.getClientList(RRClass::IN())->
......
......@@ -54,7 +54,7 @@ protected:
AuthConfigTest() :
dnss_(),
rrclass(RRClass::IN()),
server(true, xfrout, ddns_forwarder),
server(xfrout, ddns_forwarder),
// The empty string is expected value of the parameter of
// requestSocket, not the app_name (there's no fallback, it checks
// the empty string is passed).
......
......@@ -47,7 +47,6 @@
<arg><option>-c <replaceable>config-filename</replaceable></option></arg>
<arg><option>-i</option></arg>
<arg><option>-m <replaceable>file</replaceable></option></arg>
<arg><option>-n</option></arg>
<arg><option>-p <replaceable>data_path</replaceable></option></arg>
<arg><option>-u <replaceable>user</replaceable></option></arg>
<arg><option>-v</option></arg>
......@@ -57,7 +56,6 @@
<arg><option>--config-file</option> <replaceable>config-filename</replaceable></arg>
<arg><option>--data-path</option> <replaceable>directory</replaceable></arg>
<arg><option>--msgq-socket-file <replaceable>file</replaceable></option></arg>
<arg><option>--no-cache</option></arg>
<arg><option>--no-kill</option></arg>
<arg><option>--pid-file</option> <replaceable>filename</replaceable></arg>
<arg><option>--pretty-name <replaceable>name</replaceable></option></arg>
......@@ -168,15 +166,6 @@
</listitem>
</varlistentry>
<varlistentry>
<term><option>-n</option>, <option>--no-cache</option></term>
<listitem>
<para>Disables the hot-spot caching used by the
<citerefentry><refentrytitle>b10-auth</refentrytitle><manvolnum>8</manvolnum></citerefentry>
daemon.</para>
</listitem>
</varlistentry>
<varlistentry>
<term><option>-i</option>, <option>--no-kill</option></term>
<listitem>
......
......@@ -168,7 +168,7 @@ class BoB:
"""Boss of BIND class."""
def __init__(self, msgq_socket_file=None, data_path=None,
config_filename=None, clear_config=False, nocache=False,
config_filename=None, clear_config=False,
verbose=False, nokill=False, setuid=None, setgid=None,
username=None, cmdctl_port=None, wait_time=10):
"""
......@@ -192,7 +192,6 @@ class BoB:
self.ccs = None
self.curproc = None
self.msgq_socket_file = msgq_socket_file
self.nocache = nocache
self.component_config = {}
# Some time in future, it may happen that a single component has
# multple processes (like a pipeline-like component). If so happens,
......@@ -568,8 +567,6 @@ class BoB:
if self.uid is not None and self.__started:
logger.warn(BIND10_START_AS_NON_ROOT_AUTH)
authargs = ['b10-auth']
if self.nocache:
authargs += ['-n']
if self.verbose:
authargs += ['-v']
......@@ -1052,8 +1049,6 @@ def parse_args(args=sys.argv[1:], Parser=OptionParser):
parser.add_option("-m", "--msgq-socket-file", dest="msgq_socket_file",
type="string", default=None,
help="UNIX domain socket file the b10-msgq daemon will use")
parser.add_option("-n", "--no-cache", action="store_true", dest="nocache",
default=False, help="disable hot-spot cache in authoritative DNS server")
parser.add_option("-i", "--no-kill", action="store_true", dest="nokill",
default=False, help="do not send SIGTERM and SIGKILL signals to modules during shutdown")
parser.add_option("-u", "--user", dest="user", type="string", default=None,
......@@ -1208,7 +1203,7 @@ def main():
# Go bob!
boss_of_bind = BoB(options.msgq_socket_file, options.data_path,
options.config_file, options.clear_config,
options.nocache, options.verbose, options.nokill,
options.verbose, options.nokill,
setuid, setgid, username, options.cmdctl_port,
options.wait_time)
startup_result = boss_of_bind.startup()
......
......@@ -349,7 +349,6 @@ class TestBoB(unittest.TestCase):
self.assertEqual(bob.runnable, False)
self.assertEqual(bob.uid, None)
self.assertEqual(bob.username, None)
self.assertEqual(bob.nocache, False)
self.assertIsNone(bob._socket_cache)
def test_set_creator(self):
......@@ -377,7 +376,6 @@ class TestBoB(unittest.TestCase):
self.assertEqual(bob.runnable, False)
self.assertEqual(bob.uid, None)
self.assertEqual(bob.username, None)
self.assertEqual(bob.nocache, False)
def test_command_handler(self):
class DummySession():
......
......@@ -8,10 +8,10 @@ datasrc.spec: datasrc.spec.pre
config_plugindir = @prefix@/share/@PACKAGE@/config_plugins
config_plugin_DATA = logging.spec tsig_keys.spec datasrc.spec
python_PYTHON = b10logging.py tsig_keys.py datasrc.py
python_PYTHON = b10logging.py tsig_keys.py datasrc_config_plugin.py
pythondir = $(config_plugindir)
CLEANFILES = b10logging.pyc tsig_keys.pyc
CLEANFILES = b10logging.pyc tsig_keys.pyc datasrc.spec
CLEANDIRS = __pycache__
clean-local:
......
......@@ -18,7 +18,7 @@ import sys
import os
sys.path.extend(os.environ["B10_TEST_PLUGIN_DIR"].split(':'))
import datasrc
import datasrc_config_plugin
import unittest
class DatasrcTest(unittest.TestCase):
......@@ -26,11 +26,11 @@ class DatasrcTest(unittest.TestCase):
"""
Checks the entry point returns the correct values.
"""
(spec, check) = datasrc.load()
(spec, check) = datasrc_config_plugin.load()
# It returns the checking function
self.assertEqual(check, datasrc.check)
self.assertEqual(check, datasrc_config_plugin.check)
# The plugin stores it's spec
self.assertEqual(spec, datasrc.spec)
self.assertEqual(spec, datasrc_config_plugin.spec)
if __name__ == '__main__':
unittest.main()
......@@ -1132,7 +1132,7 @@ class TestDDNSSession(unittest.TestCase):
num_rrsets = len(self.__req_message.get_section(SECTION_PREREQUISITE))
self.assertEqual(2, num_rrsets)
def check_session_msg(self, result, expect_recv=1, notify_auth=False):
def check_session_msg(self, result, expect_recv=2):
'''Check post update communication with other modules.'''
# iff the update succeeds, b10-ddns should tell interested other
# modules the information about the update zone. Possible modules
......@@ -1141,32 +1141,28 @@ class TestDDNSSession(unittest.TestCase):
# 'zone_class', <updated_zone_class>}]}
# for auth, it should be:
# {'command': ['loadzone', {'origin': <updated_zone_name>,
# 'class', <updated_zone_class>,
# 'datasrc', <datasrc type, should be
# "memory" in practice>}]}
# 'class', <updated_zone_class>}]}
# and expect an answer by calling group_recvmsg().
#
# expect_recv indicates the expected number of calls to
# group_recvmsg(), which is normally 1, but can be 0 if send fails;
# group_recvmsg(), which is normally 2, but can be 0 if send fails;
# if the message is to be sent
if result == UPDATE_SUCCESS:
expected_sentmsg = 2 if notify_auth else 1
expected_sentmsg = 2
self.assertEqual(expected_sentmsg,
len(self.__cc_session._sent_msg))
self.assertEqual(expect_recv, self.__cc_session._recvmsg_called)
msg_cnt = 0
if notify_auth:
sent_msg, sent_group = self.__cc_session._sent_msg[msg_cnt]
sent_cmd = sent_msg['command']
self.assertEqual('Auth', sent_group)
self.assertEqual('loadzone', sent_cmd[0])
self.assertEqual(3, len(sent_cmd[1]))
self.assertEqual(TEST_ZONE_NAME.to_text(),
sent_cmd[1]['origin'])
self.assertEqual(TEST_RRCLASS.to_text(),
sent_cmd[1]['class'])
self.assertEqual('memory', sent_cmd[1]['datasrc'])
msg_cnt += 1
sent_msg, sent_group = self.__cc_session._sent_msg[msg_cnt]
sent_cmd = sent_msg['command']
self.assertEqual('Auth', sent_group)
self.assertEqual('loadzone', sent_cmd[0])
self.assertEqual(2, len(sent_cmd[1]))
self.assertEqual(TEST_ZONE_NAME.to_text(),
sent_cmd[1]['origin'])
self.assertEqual(TEST_RRCLASS.to_text(),
sent_cmd[1]['class'])
msg_cnt += 1
sent_msg, sent_group = self.__cc_session._sent_msg[msg_cnt]
sent_cmd = sent_msg['command']
self.assertEqual('Xfrout', sent_group)
......@@ -1232,21 +1228,21 @@ class TestDDNSSession(unittest.TestCase):
[{'type': 'memory', 'class': 'IN', 'zones': [
{'origin': TEST_ZONE_NAME_STR, 'filetype': 'sqlite3'}]}]
self.check_session()
self.check_session_msg(UPDATE_SUCCESS, expect_recv=2, notify_auth=True)
self.check_session_msg(UPDATE_SUCCESS)
# Let sendmsg() raise an exception. The first exception shouldn't
# stop sending the second message. There's just no recv calls.
self.__cc_session.clear_msg()