BIND 10 trac3186, updated. 14918661a10e2f9c3367f668261656db1ee4bfed [3186] Added support for loading user data from file
BIND 10 source code commits
bind10-changes at lists.isc.org
Mon Oct 14 15:54:45 UTC 2013
The branch, trac3186 has been updated
via 14918661a10e2f9c3367f668261656db1ee4bfed (commit)
from f0edd52c244689cd370853d520bc6e97d23a3bb2 (commit)
Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.
- Log -----------------------------------------------------------------
commit 14918661a10e2f9c3367f668261656db1ee4bfed
Author: Thomas Markwalder <tmark at isc.org>
Date: Mon Oct 14 11:52:46 2013 -0400
[3186] Added support for loading user data from file
Added UserFile derivation of UserDataSource which allows the UserRegistry
to be populated from a JSON formatted file.
-----------------------------------------------------------------------
Summary of changes:
configure.ac | 1 +
src/hooks/dhcp/user_chk/Makefile.am | 3 +-
src/hooks/dhcp/user_chk/tests/Makefile.am | 3 +
.../user_chk/tests/test_data_files_config.h.in} | 4 +-
src/hooks/dhcp/user_chk/tests/test_users_1.txt | 3 +
.../dhcp/user_chk/tests/user_file_unittests.cc | 111 ++++++++++++++++
.../dhcp/user_chk/tests/user_registry_unittests.cc | 73 ++++++++++-
src/hooks/dhcp/user_chk/tests/user_unittests.cc | 18 +--
src/hooks/dhcp/user_chk/tests/userid_unittests.cc | 26 +++-
src/hooks/dhcp/user_chk/user.cc | 21 ++-
src/hooks/dhcp/user_chk/user.h | 20 ++-
src/hooks/dhcp/user_chk/user_data_source.cc | 10 +-
src/hooks/dhcp/user_chk/user_data_source.h | 8 +-
src/hooks/dhcp/user_chk/user_file.cc | 136 ++++++++++++++++++++
.../user_chk/{user_data_source.h => user_file.h} | 39 ++++--
src/hooks/dhcp/user_chk/user_registry.cc | 43 +++++--
src/hooks/dhcp/user_chk/user_registry.h | 9 ++
17 files changed, 466 insertions(+), 62 deletions(-)
copy src/{lib/config/tests/data_def_unittests_config.h.in => hooks/dhcp/user_chk/tests/test_data_files_config.h.in} (84%)
create mode 100644 src/hooks/dhcp/user_chk/tests/test_users_1.txt
create mode 100644 src/hooks/dhcp/user_chk/tests/user_file_unittests.cc
create mode 100644 src/hooks/dhcp/user_chk/user_file.cc
copy src/hooks/dhcp/user_chk/{user_data_source.h => user_file.h} (55%)
-----------------------------------------------------------------------
diff --git a/configure.ac b/configure.ac
index e464d2c..4bed0c6 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1472,6 +1472,7 @@ AC_OUTPUT([doc/version.ent
src/bin/d2/spec_config.h.pre
src/bin/d2/tests/test_data_files_config.h
src/bin/tests/process_rename_test.py
+ src/hooks/dhcp/user_chk/tests/test_data_files_config.h
src/lib/config/tests/data_def_unittests_config.h
src/lib/dhcpsrv/tests/test_libraries.h
src/lib/python/isc/config/tests/config_test
diff --git a/src/hooks/dhcp/user_chk/Makefile.am b/src/hooks/dhcp/user_chk/Makefile.am
index 898067a..f5bd13a 100644
--- a/src/hooks/dhcp/user_chk/Makefile.am
+++ b/src/hooks/dhcp/user_chk/Makefile.am
@@ -32,8 +32,9 @@ CLEANFILES = *.gcno *.gcda
lib_LTLIBRARIES = libdhcp_user_chk.la
libdhcp_user_chk_la_SOURCES =
libdhcp_user_chk_la_SOURCES += load_unload.cc
-libdhcp_user_chk_la_SOURCES += user.cc user.h
+libdhcp_user_chk_la_SOURCES += user.cc user.h
libdhcp_user_chk_la_SOURCES += user_data_source.cc user_data_source.h
+libdhcp_user_chk_la_SOURCES += user_file.cc user_file.h
libdhcp_user_chk_la_SOURCES += user_registry.cc user_registry.h
libdhcp_user_chk_la_SOURCES += version.cc
diff --git a/src/hooks/dhcp/user_chk/tests/Makefile.am b/src/hooks/dhcp/user_chk/tests/Makefile.am
index 51e0ebf..3ee9d09 100644
--- a/src/hooks/dhcp/user_chk/tests/Makefile.am
+++ b/src/hooks/dhcp/user_chk/tests/Makefile.am
@@ -32,11 +32,13 @@ TESTS += libdhcp_user_chk_unittests
libdhcp_user_chk_unittests_SOURCES =
libdhcp_user_chk_unittests_SOURCES += ../user.cc ../user.h
libdhcp_user_chk_unittests_SOURCES += ../user_data_source.cc ../user_data_source.h
+libdhcp_user_chk_unittests_SOURCES += ../user_file.cc ../user_file.h
libdhcp_user_chk_unittests_SOURCES += ../user_registry.cc ../user_registry.h
libdhcp_user_chk_unittests_SOURCES += run_unittests.cc
libdhcp_user_chk_unittests_SOURCES += userid_unittests.cc
libdhcp_user_chk_unittests_SOURCES += user_unittests.cc
libdhcp_user_chk_unittests_SOURCES += user_registry_unittests.cc
+libdhcp_user_chk_unittests_SOURCES += user_file_unittests.cc
libdhcp_user_chk_unittests_CPPFLAGS = $(AM_CPPFLAGS) $(GTEST_INCLUDES) $(LOG4CPLUS_INCLUDES)
@@ -54,6 +56,7 @@ libdhcp_user_chk_unittests_LDADD = $(top_builddir)/src/lib/log/libb10-log.la
libdhcp_user_chk_unittests_LDADD += $(top_builddir)/src/lib/util/libb10-util.la
libdhcp_user_chk_unittests_LDADD += $(top_builddir)/src/lib/dhcp/libb10-dhcp++.la
libdhcp_user_chk_unittests_LDADD += $(top_builddir)/src/lib/exceptions/libb10-exceptions.la
+libdhcp_user_chk_unittests_LDADD += $(top_builddir)/src/lib/cc/libb10-cc.la
#libdhcp_user_chk_unittests_LDADD += $(top_builddir)/src/hooks/dhcp/user_chk/libdhcp_user_chk.la
libdhcp_user_chk_unittests_LDADD += ${BOTAN_LIBS} ${BOTAN_RPATH}
libdhcp_user_chk_unittests_LDADD += $(GTEST_LDADD)
diff --git a/src/hooks/dhcp/user_chk/tests/test_data_files_config.h.in b/src/hooks/dhcp/user_chk/tests/test_data_files_config.h.in
new file mode 100644
index 0000000..019104b
--- /dev/null
+++ b/src/hooks/dhcp/user_chk/tests/test_data_files_config.h.in
@@ -0,0 +1,16 @@
+// Copyright (C) 2009 Internet Systems Consortium, Inc. ("ISC")
+//
+// Permission to use, copy, modify, and/or distribute this software for any
+// purpose with or without fee is hereby granted, provided that the above
+// copyright notice and this permission notice appear in all copies.
+//
+// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+// AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+// PERFORMANCE OF THIS SOFTWARE.
+
+/// @brief Path to local dir so tests can locate test data files
+#define USER_CHK_TEST_DIR "@abs_top_srcdir@/src/hooks/dhcp/user_chk/tests"
diff --git a/src/hooks/dhcp/user_chk/tests/test_users_1.txt b/src/hooks/dhcp/user_chk/tests/test_users_1.txt
new file mode 100644
index 0000000..fd60fe7
--- /dev/null
+++ b/src/hooks/dhcp/user_chk/tests/test_users_1.txt
@@ -0,0 +1,3 @@
+{ "type" : "HW_ADDR", "id" : "01AC00F03344", "opt1" : "true" }
+{ "type" : "CLIENT_ID", "id" : "0899e0cc0707", "opt1" : "false" }
+{ "type" : "DUID", "id" : "225060de0a0b", "opt1" : "true" }
diff --git a/src/hooks/dhcp/user_chk/tests/user_file_unittests.cc b/src/hooks/dhcp/user_chk/tests/user_file_unittests.cc
new file mode 100644
index 0000000..4659e03
--- /dev/null
+++ b/src/hooks/dhcp/user_chk/tests/user_file_unittests.cc
@@ -0,0 +1,111 @@
+// Copyright (C) 2013 Internet Systems Consortium, Inc. ("ISC")
+//
+// Permission to use, copy, modify, and/or distribute this software for any
+// purpose with or without fee is hereby granted, provided that the above
+// copyright notice and this permission notice appear in all copies.
+//
+// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+// AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+// PERFORMANCE OF THIS SOFTWARE.
+
+#include <exceptions/exceptions.h>
+#include <test_data_files_config.h>
+#include <user_file.h>
+
+#include <boost/function.hpp>
+#include <boost/bind.hpp>
+#include <boost/shared_ptr.hpp>
+#include <gtest/gtest.h>
+
+using namespace std;
+
+namespace {
+
+std::string testFilePath(const std::string& name) {
+ return (std::string(USER_CHK_TEST_DIR) + "/" + name);
+}
+
+TEST(UserFile, construction) {
+ ASSERT_THROW(UserFile(""), UserFileError);
+
+ ASSERT_NO_THROW(UserFile("someName"));
+}
+
+TEST(UserFile, openFile) {
+ UserFilePtr user_file;
+
+ // Construct a user file that refers to a non existant file.
+ ASSERT_NO_THROW(user_file.reset(new UserFile("NoSuchFile")));
+ EXPECT_FALSE(user_file->isOpen());
+
+ // Verify a non-existant file fails to open
+ ASSERT_THROW(user_file->open(), UserFileError);
+ EXPECT_FALSE(user_file->isOpen());
+
+ // Construct a user file that should exist.
+ ASSERT_NO_THROW(user_file.reset(new
+ UserFile(testFilePath("test_users_1.txt"))));
+ EXPECT_FALSE(user_file->isOpen());
+
+ // Verify that we can open it.
+ ASSERT_NO_THROW(user_file->open());
+ EXPECT_TRUE(user_file->isOpen());
+
+ // Verify that we cannot open an already open file.
+ ASSERT_THROW(user_file->open(), UserFileError);
+
+ // Verifyt we can close it.
+ ASSERT_NO_THROW(user_file->close());
+ EXPECT_FALSE(user_file->isOpen());
+
+ // Verify that we can reopen it.
+ ASSERT_NO_THROW(user_file->open());
+ EXPECT_TRUE(user_file->isOpen());
+}
+
+TEST(UserFile, readFile) {
+ UserFilePtr user_file;
+
+ // Construct an open a known file.
+ ASSERT_NO_THROW(user_file.reset(new
+ UserFile(testFilePath("test_users_1.txt"))));
+ ASSERT_NO_THROW(user_file->open());
+ EXPECT_TRUE(user_file->isOpen());
+
+ UserPtr user;
+ int i = 0;
+ do {
+ ASSERT_NO_THROW(user = user_file->readNextUser());
+ switch (i++) {
+ case 0:
+ EXPECT_EQ(UserId::HW_ADDRESS, user->getUserId().getType());
+ EXPECT_EQ("01ac00f03344", user->getUserId().toText());
+ EXPECT_EQ("true", user->getProperty("opt1"));
+ break;
+ case 1:
+ EXPECT_EQ(UserId::CLIENT_ID, user->getUserId().getType());
+ EXPECT_EQ("0899e0cc0707", user->getUserId().toText());
+ EXPECT_EQ("false", user->getProperty("opt1"));
+ break;
+ case 2:
+ EXPECT_EQ(UserId::DUID, user->getUserId().getType());
+ EXPECT_EQ("225060de0a0b", user->getUserId().toText());
+ EXPECT_EQ("true", user->getProperty("opt1"));
+ break;
+ default:
+ // this is an error, TBD
+ break;
+ }
+ } while (user);
+
+
+ ASSERT_NO_THROW(user_file->close());
+}
+
+
+
+} // end of anonymous namespace
diff --git a/src/hooks/dhcp/user_chk/tests/user_registry_unittests.cc b/src/hooks/dhcp/user_chk/tests/user_registry_unittests.cc
index d6d5114..5fee7c5 100644
--- a/src/hooks/dhcp/user_chk/tests/user_registry_unittests.cc
+++ b/src/hooks/dhcp/user_chk/tests/user_registry_unittests.cc
@@ -15,6 +15,8 @@
#include <dhcp/hwaddr.h>
#include <exceptions/exceptions.h>
#include <user_registry.h>
+#include <user_file.h>
+#include <test_data_files_config.h>
#include <boost/function.hpp>
#include <boost/bind.hpp>
@@ -25,6 +27,10 @@ using namespace std;
namespace {
+std::string testFilePath(const std::string& name) {
+ return (std::string(USER_CHK_TEST_DIR) + "/" + name);
+}
+
TEST(UserRegistry, constructor) {
UserRegistryPtr reg;
ASSERT_NO_THROW(reg.reset(new UserRegistry()));
@@ -41,7 +47,7 @@ TEST(UserRegistry, userBasics) {
UserPtr user, user2;
// Verify that a blank user cannot be added.
- ASSERT_THROW(reg->addUser(user), isc::BadValue);
+ ASSERT_THROW(reg->addUser(user), UserRegistryError);
// Make new users.
ASSERT_NO_THROW(user.reset(new User(*id)));
@@ -54,7 +60,7 @@ TEST(UserRegistry, userBasics) {
UserPtr found_user;
ASSERT_NO_THROW(found_user = reg->findUser(*id));
EXPECT_TRUE(found_user);
- EXPECT_EQ(*id, found_user->getUserId());
+ EXPECT_EQ(found_user->getUserId(), *id);
// Verify user not added cannot be found.
ASSERT_NO_THROW(found_user = reg->findUser(*id2));
@@ -78,14 +84,14 @@ TEST(UserRegistry, findByHWAddr) {
ASSERT_NO_THROW(reg->addUser(user));
// Make a HWAddr instance using the same id value.
- isc::dhcp::HWAddr hwaddr(user->getUserId().getId(),
+ isc::dhcp::HWAddr hwaddr(user->getUserId().getId(),
isc::dhcp::HTYPE_ETHER);
// Verify user can be found by HWAddr.
UserPtr found_user;
ASSERT_NO_THROW(found_user = reg->findUser(hwaddr));
EXPECT_TRUE(found_user);
- EXPECT_EQ(user->getUserId(), found_user->getUserId());
+ EXPECT_EQ(found_user->getUserId(), user->getUserId());
}
TEST(UserRegistry, findByDUID) {
@@ -106,7 +112,7 @@ TEST(UserRegistry, findByDUID) {
UserPtr found_user;
ASSERT_NO_THROW(found_user = reg->findUser(duid));
EXPECT_TRUE(found_user);
- EXPECT_EQ(user->getUserId(), found_user->getUserId());
+ EXPECT_EQ(found_user->getUserId(), user->getUserId());
}
TEST(UserRegistry, findByClientId) {
@@ -127,7 +133,62 @@ TEST(UserRegistry, findByClientId) {
UserPtr found_user;
ASSERT_NO_THROW(found_user = reg->findUser(client_id));
EXPECT_TRUE(found_user);
- EXPECT_EQ(user->getUserId(), found_user->getUserId());
+ EXPECT_EQ(found_user->getUserId(), user->getUserId());
+}
+
+TEST(UserRegistry, oneOfEach) {
+ UserRegistryPtr reg;
+ ASSERT_NO_THROW(reg.reset(new UserRegistry()));
+
+ // Make user ids.
+ UserIdPtr idh, idc, idd;
+ ASSERT_NO_THROW(idh.reset(new UserId(UserId::HW_ADDRESS, "01010101")));
+ ASSERT_NO_THROW(idc.reset(new UserId(UserId::CLIENT_ID, "02020202")));
+ ASSERT_NO_THROW(idd.reset(new UserId(UserId::DUID, "03030303")));
+
+ UserPtr user;
+ user.reset(new User(*idh));
+ ASSERT_NO_THROW(reg->addUser(user));
+
+ user.reset(new User(*idc));
+ ASSERT_NO_THROW(reg->addUser(user));
+ user.reset(new User(*idd));
+ ASSERT_NO_THROW(reg->addUser(user));
+
+ UserPtr found_user;
+ ASSERT_NO_THROW(found_user = reg->findUser(*idh));
+ ASSERT_NO_THROW(found_user = reg->findUser(*idc));
+ ASSERT_NO_THROW(found_user = reg->findUser(*idd));
+}
+
+TEST(UserRegistry, userFileTest) {
+ UserRegistryPtr reg;
+ ASSERT_NO_THROW(reg.reset(new UserRegistry()));
+
+ // Create the data source.
+ UserDataSourcePtr user_file;
+ ASSERT_NO_THROW(user_file.reset(new
+ UserFile(testFilePath("test_users_1.txt"))));
+
+ // Set the registry's data source and refresh the registry.
+ ASSERT_NO_THROW(reg->setSource(user_file));
+ //ASSERT_NO_THROW(reg->refresh());
+ (reg->refresh());
+
+ // Verify we can find all the expected users.
+ UserPtr found_user;
+ UserIdPtr id;
+ ASSERT_NO_THROW(id.reset(new UserId(UserId::HW_ADDRESS, "01ac00f03344")));
+ ASSERT_NO_THROW(found_user = reg->findUser(*id));
+ EXPECT_TRUE(found_user);
+
+ ASSERT_NO_THROW(id.reset(new UserId(UserId::CLIENT_ID, "0899e0cc0707")));
+ ASSERT_NO_THROW(found_user = reg->findUser(*id));
+ EXPECT_TRUE(found_user);
+
+ ASSERT_NO_THROW(id.reset(new UserId(UserId::DUID, "225060de0a0b")));
+ ASSERT_NO_THROW(found_user = reg->findUser(*id));
+ EXPECT_TRUE(found_user);
}
} // end of anonymous namespace
diff --git a/src/hooks/dhcp/user_chk/tests/user_unittests.cc b/src/hooks/dhcp/user_chk/tests/user_unittests.cc
index 03cc072..ca61e24 100644
--- a/src/hooks/dhcp/user_chk/tests/user_unittests.cc
+++ b/src/hooks/dhcp/user_chk/tests/user_unittests.cc
@@ -35,28 +35,28 @@ TEST(UserTest, construction) {
ASSERT_NO_THROW(user.reset(new User(*id)));
// Verify construction from a type and an address vector.
- ASSERT_NO_THROW(user.reset(new User(UserId::HW_ADDRESS, id->getId())));
- ASSERT_NO_THROW(user.reset(new User(UserId::DUID, id->getId())));
- ASSERT_NO_THROW(user.reset(new User(UserId::CLIENT_ID, id->getId())));
+ ASSERT_NO_THROW(user.reset(new User(UserId::HW_ADDRESS, id->getId())));
+ ASSERT_NO_THROW(user.reset(new User(UserId::DUID, id->getId())));
+ ASSERT_NO_THROW(user.reset(new User(UserId::CLIENT_ID, id->getId())));
// Verify construction from a type and an address string.
- ASSERT_NO_THROW(user.reset(new User(UserId::HW_ADDRESS, test_address)));
- ASSERT_NO_THROW(user.reset(new User(UserId::DUID, test_address)));
- ASSERT_NO_THROW(user.reset(new User(UserId::CLIENT_ID, test_address)));
+ ASSERT_NO_THROW(user.reset(new User(UserId::HW_ADDRESS, test_address)));
+ ASSERT_NO_THROW(user.reset(new User(UserId::DUID, test_address)));
+ ASSERT_NO_THROW(user.reset(new User(UserId::CLIENT_ID, test_address)));
}
TEST(UserTest, properties) {
UserPtr user;
- ASSERT_NO_THROW(user.reset(new User(UserId::DUID, "01020304050607")));
+ ASSERT_NO_THROW(user.reset(new User(UserId::DUID, "01020304050607")));
std::string value = "";
EXPECT_NO_THROW(user->setProperty("one","1"));
EXPECT_NO_THROW(value = user->getProperty("one"));
- EXPECT_EQ(value, "1");
+ EXPECT_EQ("1", value);
EXPECT_NO_THROW(user->setProperty("one","1.0"));
EXPECT_NO_THROW(value = user->getProperty("one"));
- EXPECT_EQ(value, "1.0");
+ EXPECT_EQ("1.0", value);
EXPECT_NO_THROW(user->delProperty("one"));
EXPECT_NO_THROW(value = user->getProperty("one"));
diff --git a/src/hooks/dhcp/user_chk/tests/userid_unittests.cc b/src/hooks/dhcp/user_chk/tests/userid_unittests.cc
index 43c7889..679fbd7 100644
--- a/src/hooks/dhcp/user_chk/tests/userid_unittests.cc
+++ b/src/hooks/dhcp/user_chk/tests/userid_unittests.cc
@@ -147,8 +147,9 @@ TEST(UserIdTest, client_id_type) {
EXPECT_FALSE(*id < *id2);
}
-TEST(UserIdTest, type_compare) {
+TEST(UserIdTest, mixed_type_compare) {
UserIdPtr hw, duid, client;
+ // Address are the same
ASSERT_NO_THROW(hw.reset(new UserId(UserId::HW_ADDRESS,
"01FF02AC030B0709")));
ASSERT_NO_THROW(duid.reset(new UserId(UserId::DUID,
@@ -157,9 +158,26 @@ TEST(UserIdTest, type_compare) {
"01FF02AC030B0709")));
// Verify that UserIdType influences logical comparators.
- EXPECT_NE(*hw, *duid);
- EXPECT_NE(*hw , *client);
- EXPECT_NE(*duid, *client);
+ EXPECT_TRUE(*hw < *duid);
+ EXPECT_TRUE(*duid < *client);
+
+
+ // Now use different addresses.
+ ASSERT_NO_THROW(hw.reset(new UserId(UserId::HW_ADDRESS,
+ "01010101")));
+ ASSERT_NO_THROW(duid.reset(new UserId(UserId::DUID,
+ "02020202")));
+ ASSERT_NO_THROW(client.reset(new UserId(UserId::CLIENT_ID,
+ "03030303")));
+
+ EXPECT_FALSE(*hw == *duid);
+ EXPECT_TRUE(*hw != *duid);
+ EXPECT_TRUE(*hw < *duid);
+
+ EXPECT_FALSE(*duid == *client);
+ EXPECT_TRUE(*duid != *client);
+ EXPECT_TRUE(*duid < *client);
}
+
} // end of anonymous namespace
diff --git a/src/hooks/dhcp/user_chk/user.cc b/src/hooks/dhcp/user_chk/user.cc
index 3955cf6..108e20f 100644
--- a/src/hooks/dhcp/user_chk/user.cc
+++ b/src/hooks/dhcp/user_chk/user.cc
@@ -112,7 +112,8 @@ UserId::operator !=(const UserId & other) const {
bool
UserId::operator <(const UserId & other) const {
- return ((this->id_type_ == other.id_type_) && (this->id_ < other.id_));
+ return ((this->id_type_ < other.id_type_) ||
+ ((this->id_type_ == other.id_type_) && (this->id_ < other.id_)));
}
void
@@ -160,11 +161,11 @@ UserId::lookupTypeStr(UserIdType type) {
UserId::UserIdType
UserId::lookupType(const std::string& type_str) {
- if (type_str == HW_ADDRESS_STR) {
+ if (type_str.compare(HW_ADDRESS_STR) == 0) {
return (HW_ADDRESS);
- } else if (type_str == DUID_STR) {
+ } else if (type_str.compare(DUID_STR) == 0) {
return (DUID);
- } else if (type_str == CLIENT_ID_STR) {
+ } else if (type_str.compare(CLIENT_ID_STR) == 0) {
return (CLIENT_ID);
}
@@ -187,13 +188,23 @@ User::User(UserId::UserIdType id_type, const std::vector<uint8_t>& id)
: user_id_(id_type, id) {
}
-User::User(UserId::UserIdType id_type, const std::string& id_str)
+User::User(UserId::UserIdType id_type, const std::string& id_str)
: user_id_(id_type, id_str) {
}
User::~User() {
}
+const PropertyMap&
+User::getProperties() const {
+ return (properties_);
+}
+
+void
+User::setProperties(const PropertyMap& properties) {
+ properties_ = properties;
+}
+
void User::setProperty(const std::string& name, const std::string& value) {
if (name.empty()) {
isc_throw (isc::BadValue, "User property name cannot be blank");
diff --git a/src/hooks/dhcp/user_chk/user.h b/src/hooks/dhcp/user_chk/user.h
index beada57..afc8962 100644
--- a/src/hooks/dhcp/user_chk/user.h
+++ b/src/hooks/dhcp/user_chk/user.h
@@ -22,15 +22,17 @@
class UserId {
public:
+ // Use explicit value to ensure consistent numeric ordering for key
+ // comparisions.
enum UserIdType {
- HW_ADDRESS,
- DUID,
- CLIENT_ID
+ HW_ADDRESS = 0,
+ DUID = 1,
+ CLIENT_ID = 2
};
static const char* HW_ADDRESS_STR;
static const char* DUID_STR;
- static const char* CLIENT_ID_STR;
+ static const char* CLIENT_ID_STR;
UserId(UserIdType id_type, const std::vector<uint8_t>& id);
@@ -41,7 +43,7 @@ public:
/// @brief Returns a const reference to the actual id value
const std::vector<uint8_t>& getId() const;
- /// @brief Returns the UserIdType
+ /// @brief Returns the UserIdType
UserIdType getType() const;
/// @brief Returns textual representation of a id (e.g. 00:01:02:03:ff)
@@ -63,10 +65,10 @@ public:
private:
void decodeHex(const std::string& input, std::vector<uint8_t>& bytes) const;
- /// @brief The type of id value
+ /// @brief The type of id value
UserIdType id_type_;
- /// @brief The id value
+ /// @brief The id value
std::vector<uint8_t> id_;
};
@@ -89,6 +91,10 @@ public:
~User();
+ const PropertyMap& getProperties() const;
+
+ void setProperties(const PropertyMap& properties);
+
void setProperty(const std::string& name, const std::string& value);
std::string getProperty(const std::string& name) const;
diff --git a/src/hooks/dhcp/user_chk/user_data_source.cc b/src/hooks/dhcp/user_chk/user_data_source.cc
index 9a80b2f..8827d3d 100644
--- a/src/hooks/dhcp/user_chk/user_data_source.cc
+++ b/src/hooks/dhcp/user_chk/user_data_source.cc
@@ -23,27 +23,27 @@ UserDataSource::~UserDataSource() {
}
}
-void
+void
UserDataSource::open() {
open_flag_ = false;
}
-UserPtr
+UserPtr
UserDataSource::readNextUser() {
return (UserPtr());
}
-void
+void
UserDataSource::close() {
open_flag_ = false;
}
-bool
+bool
UserDataSource::isOpen() const {
return open_flag_;
}
-void
+void
UserDataSource::setOpenFlag(bool value) {
open_flag_ = value;
}
diff --git a/src/hooks/dhcp/user_chk/user_data_source.h b/src/hooks/dhcp/user_chk/user_data_source.h
index 33a64ed..696e8e0 100644
--- a/src/hooks/dhcp/user_chk/user_data_source.h
+++ b/src/hooks/dhcp/user_chk/user_data_source.h
@@ -21,13 +21,13 @@ class UserDataSource {
public:
UserDataSource();
- ~UserDataSource();
+ virtual ~UserDataSource();
- void open();
+ virtual void open();
- UserPtr readNextUser();
+ virtual UserPtr readNextUser();
- void close();
+ virtual void close();
bool isOpen() const;
diff --git a/src/hooks/dhcp/user_chk/user_file.cc b/src/hooks/dhcp/user_chk/user_file.cc
new file mode 100644
index 0000000..24324c9
--- /dev/null
+++ b/src/hooks/dhcp/user_chk/user_file.cc
@@ -0,0 +1,136 @@
+// Copyright (C) 2013 Internet Systems Consortium, Inc. ("ISC")
+//
+// Permission to use, copy, modify, and/or distribute this software for any
+// purpose with or without fee is hereby granted, provided that the above
+// copyright notice and this permission notice appear in all copies.
+//
+// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+// AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+// PERFORMANCE OF THIS SOFTWARE.
+
+#include <cc/data.h>
+#include <user.h>
+#include <user_file.h>
+
+#include <boost/foreach.hpp>
+
+UserFile::UserFile(const std::string& fname) : fname_(fname) {
+ if (fname_.empty()) {
+ isc_throw(UserFileError, "file name cannot be blank");
+ }
+}
+
+UserFile::~UserFile(){
+};
+
+void
+UserFile::open() {
+ if (isOpen()) {
+ isc_throw (UserFileError, "file is already open");
+ }
+
+ ifs_.open(fname_.c_str(), std::ifstream::in);
+ if (!ifs_.is_open()) {
+ isc_throw(UserFileError, "cannot open file:" << fname_);
+ }
+
+ setOpenFlag(true);
+}
+
+UserPtr
+UserFile::readNextUser() {
+ if (!isOpen()) {
+ isc_throw (UserFileError, "cannot read, file is not open");
+ }
+
+ if (ifs_.good()) {
+ char buf[4096];
+
+ // get the next line
+ ifs_.getline(buf, sizeof(buf));
+
+ // we got something, try to make a user out of it.
+ if (ifs_.gcount() > 0) {
+ return(makeUser(buf));
+ }
+ }
+
+ // returns an empty user
+ return (UserDataSource::readNextUser());
+}
+
+UserPtr
+UserFile::makeUser(const std::string& user_string) {
+ // This method leverages the existing JSON parsing provided by isc::data
+ // library. Should this prove to be a performance issue, it may be that
+ // lighter weight solution would be appropriate.
+
+ // Turn the string of JSON text into an Element set.
+ isc::data::ElementPtr elements;
+ try {
+ elements = isc::data::Element::fromJSON(user_string);
+ } catch (isc::data::JSONError& ex) {
+ isc_throw(UserFileError,
+ "UserFile entry is malformed JSON: " << ex.what());
+ }
+
+ // Get a map of the Elements, keyed by element name.
+ isc::data::ConstElementPtr element;
+ PropertyMap properties;
+ std::string id_type_str;
+ std::string id_str;
+
+ std::pair<std::string, isc::data::ConstElementPtr> element_pair;
+ BOOST_FOREACH (element_pair, elements->mapValue()) {
+ std::string label = element_pair.first;
+ std::string value = "";
+ element_pair.second->getValue(value);
+
+ if (label == "type") {
+ id_type_str = value;
+ } else if (label == "id") {
+ id_str = value;
+ } else {
+ if (properties.find(label) != properties.end()) {
+ isc_throw (UserFileError,
+ "UserFile entry contains duplicate values: "
+ << user_string);
+ }
+ properties[label]=value;
+ }
+ }
+
+ UserId::UserIdType id_type;
+ try {
+ id_type = UserId::lookupType(id_type_str);
+ } catch (const std::exception& ex) {
+ isc_throw (UserFileError, "UserFile entry has invalid type: "
+ << user_string << " " << ex.what());
+ }
+
+ UserPtr user;
+ try {
+ user.reset(new User(id_type, id_str));
+ } catch (const std::exception& ex) {
+ isc_throw (UserFileError, "UserFile cannot create user form entry: "
+ << user_string << " " << ex.what());
+ }
+
+
+ user->setProperties(properties);
+ return (user);
+}
+
+void
+UserFile::close() {
+ if (ifs_.is_open()) {
+ ifs_.close();
+ }
+
+ setOpenFlag(false);
+}
+
diff --git a/src/hooks/dhcp/user_chk/user_file.h b/src/hooks/dhcp/user_chk/user_file.h
new file mode 100644
index 0000000..4b3020f
--- /dev/null
+++ b/src/hooks/dhcp/user_chk/user_file.h
@@ -0,0 +1,61 @@
+// Copyright (C) 2013 Internet Systems Consortium, Inc. ("ISC")
+//
+// Permission to use, copy, modify, and/or distribute this software for any
+// purpose with or without fee is hereby granted, provided that the above
+// copyright notice and this permission notice appear in all copies.
+//
+// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+// AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+// PERFORMANCE OF THIS SOFTWARE.
+
+#ifndef _USER_FILE_H
+#define _USER_FILE_H
+
+#include <exceptions/exceptions.h>
+
+#include <user_data_source.h>
+#include <user.h>
+
+#include <boost/shared_ptr.hpp>
+#include <fstream>
+#include <string>
+
+using namespace std;
+
+/// @brief Thrown UserFile encounters an error
+class UserFileError : public isc::Exception {
+public:
+ UserFileError(const char* file, size_t line,
+ const char* what) :
+ isc::Exception(file, line, what) { };
+};
+
+class UserFile : public UserDataSource {
+public:
+ UserFile(const std::string& fname);
+
+ virtual ~UserFile();
+
+ // must throw if open fails.
+ void open();
+
+ UserPtr readNextUser();
+
+ void close();
+
+ UserPtr makeUser(const std::string& user_string);
+
+private:
+ string fname_;
+
+ std::ifstream ifs_;
+
+};
+
+typedef boost::shared_ptr<UserFile> UserFilePtr;
+
+#endif
diff --git a/src/hooks/dhcp/user_chk/user_registry.cc b/src/hooks/dhcp/user_chk/user_registry.cc
index e816ddb..4df69ac 100644
--- a/src/hooks/dhcp/user_chk/user_registry.cc
+++ b/src/hooks/dhcp/user_chk/user_registry.cc
@@ -21,31 +21,34 @@ UserRegistry::UserRegistry() {
UserRegistry::~UserRegistry(){
}
-void
+void
UserRegistry::addUser(UserPtr& user) {
if (!user) {
- isc_throw (isc::BadValue, "UserRegistry cannot add blank user");
+ isc_throw (UserRegistryError, "UserRegistry cannot add blank user");
}
- if (findUser(user->getUserId())) {
- isc_throw (isc::BadValue, "Duplicate User!");
+ UserPtr found_user;
+ if ((found_user = findUser(user->getUserId()))) {
+ isc_throw (UserRegistryError, "UserRegistry duplicate user: "
+ << user->getUserId());
}
users_[user->getUserId()] = user;
}
-const UserPtr&
+const UserPtr&
UserRegistry::findUser(const UserId& id) const {
static UserPtr empty;
UserMap::const_iterator it = users_.find(id);
if (it != users_.end()) {
+ const UserPtr tmp = (*it).second;
return ((*it).second);
}
return empty;
}
-void
+void
UserRegistry::removeUser(const UserId& id) {
static UserPtr empty;
UserMap::iterator it = users_.find(id);
@@ -54,25 +57,47 @@ UserRegistry::removeUser(const UserId& id) {
}
}
-const UserPtr&
+const UserPtr&
UserRegistry::findUser(const isc::dhcp::HWAddr& hwaddr) const {
UserId id(UserId::HW_ADDRESS, hwaddr.hwaddr_);
return (findUser(id));
}
-const UserPtr&
+const UserPtr&
UserRegistry::findUser(const isc::dhcp::ClientId& client_id) const {
UserId id(UserId::CLIENT_ID, client_id.getClientId());
return (findUser(id));
}
-const UserPtr&
+const UserPtr&
UserRegistry::findUser(const isc::dhcp::DUID& duid) const {
UserId id(UserId::DUID, duid.getDuid());
return (findUser(id));
}
void UserRegistry::refresh() {
+ if (!source_) {
+ isc_throw(UserRegistryError,
+ "UserRegistry: cannot refresh, no data source");
+ }
+
+ if (!source_->isOpen()) {
+ source_->open();
+ }
+
+ clearall();
+ try {
+ UserPtr user;
+ while ((user = source_->readNextUser())) {
+ addUser(user);
+ }
+ } catch (const std::exception& ex) {
+ source_->close();
+ isc_throw (UserRegistryError, "UserRegistry: refresh failed during read"
+ << ex.what());
+ }
+
+ source_->close();
}
void UserRegistry::clearall() {
diff --git a/src/hooks/dhcp/user_chk/user_registry.h b/src/hooks/dhcp/user_chk/user_registry.h
index 1e089d0..d8db0c5 100644
--- a/src/hooks/dhcp/user_chk/user_registry.h
+++ b/src/hooks/dhcp/user_chk/user_registry.h
@@ -16,6 +16,7 @@
#include <dhcp/hwaddr.h>
#include <dhcp/duid.h>
+#include <exceptions/exceptions.h>
#include <user.h>
#include <user_data_source.h>
@@ -23,6 +24,14 @@
using namespace std;
+/// @brief Thrown UserRegistry encounters an error
+class UserRegistryError : public isc::Exception {
+public:
+ UserRegistryError(const char* file, size_t line,
+ const char* what) :
+ isc::Exception(file, line, what) { };
+};
+
typedef std::map<UserId,UserPtr> UserMap;
class UserRegistry {
More information about the bind10-changes
mailing list