Skip to content
GitLab
Menu
Projects
Groups
Snippets
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Menu
Open sidebar
Adam Osuchowski
Kea
Commits
a3d4fe8a
Commit
a3d4fe8a
authored
May 14, 2013
by
JINMEI Tatuya
Browse files
[master] Merge branch 'trac2851'
parents
650c6ce2
0ef74c36
Changes
17
Hide whitespace changes
Inline
Side-by-side
src/bin/auth/datasrc_clients_mgr.h
View file @
a3d4fe8a
...
...
@@ -639,12 +639,21 @@ DataSrcClientsBuilderBase<MutexType, CondVarType>::getZoneWriter(
AUTH_DATASRC_CLIENTS_BUILDER_LOAD_ZONE_NOCACHE
)
.
arg
(
origin
).
arg
(
rrclass
);
break
;
// return NULL below
case
datasrc
::
ConfigurableClientList
::
CACHE_NOT_WRITABLE
:
// This is an internal error. Auth server should skip reloading zones
// on non writable caches.
isc_throw
(
InternalCommandError
,
"failed to load zone "
<<
origin
<<
"/"
<<
rrclass
<<
": internal failure, in-memory cache "
"is not writable"
);
case
datasrc
::
ConfigurableClientList
::
CACHE_DISABLED
:
// This is an internal error. Auth server must have the cache
// enabled.
isc_throw
(
InternalCommandError
,
"failed to load zone "
<<
origin
<<
"/"
<<
rrclass
<<
": internal failure, in-memory cache "
"is somehow disabled"
);
default:
// other cases can really never happen
isc_throw
(
Unexpected
,
"Impossible result in getting data source "
"ZoneWriter: "
<<
writerpair
.
first
);
}
return
(
boost
::
shared_ptr
<
datasrc
::
memory
::
ZoneWriter
>
());
...
...
src/bin/auth/tests/datasrc_clients_builder_unittest.cc
View file @
a3d4fe8a
...
...
@@ -406,6 +406,22 @@ TEST_F(DataSrcClientsBuilderTest,
EXPECT_EQ
(
orig_lock_count
+
1
,
map_mutex
.
lock_count
);
EXPECT_EQ
(
orig_unlock_count
+
1
,
map_mutex
.
unlock_count
);
// zone doesn't exist in the data source
const
ConstElementPtr
config_nozone
(
Element
::
fromJSON
(
"{"
"
\"
IN
\"
: [{"
"
\"
type
\"
:
\"
sqlite3
\"
,"
"
\"
params
\"
: {
\"
database_file
\"
:
\"
"
+
test_db
+
"
\"
},"
"
\"
cache-enable
\"
: true,"
"
\"
cache-zones
\"
: [
\"
nosuchzone.example
\"
]"
"}]}"
));
clients_map
=
configureDataSource
(
config_nozone
);
EXPECT_THROW
(
builder
.
handleCommand
(
Command
(
LOADZONE
,
Element
::
fromJSON
(
"{
\"
class
\"
:
\"
IN
\"
,"
"
\"
origin
\"
:
\"
nosuchzone.example
\"
}"
))),
TestDataSrcClientsBuilder
::
InternalCommandError
);
// basically impossible case: in-memory cache is completely disabled.
// In this implementation of manager-builder, this should never happen,
// but it catches it like other configuration error and keeps going.
...
...
@@ -503,14 +519,6 @@ TEST_F(DataSrcClientsBuilderTest, loadZoneInvalidParams) {
},
""
);
}
// zone doesn't exist in the data source
EXPECT_THROW
(
builder
.
handleCommand
(
Command
(
LOADZONE
,
Element
::
fromJSON
(
"{
\"
class
\"
:
\"
IN
\"
,
\"
origin
\"
:
\"
xx
\"
}"
))),
TestDataSrcClientsBuilder
::
InternalCommandError
);
// origin is bogus
EXPECT_THROW
(
builder
.
handleCommand
(
Command
(
LOADZONE
,
...
...
@@ -524,4 +532,35 @@ TEST_F(DataSrcClientsBuilderTest, loadZoneInvalidParams) {
isc
::
data
::
TypeError
);
}
// This works only if mapped memory segment is compiled.
// Note also that this test case may fail as we make b10-auth more aware
// of shared-memory cache.
TEST_F
(
DataSrcClientsBuilderTest
,
#ifdef USE_SHARED_MEMORY
loadInNonWritableCache
#else
DISABLED_loadInNonWritableCache
#endif
)
{
const
ConstElementPtr
config
=
Element
::
fromJSON
(
"{"
"
\"
IN
\"
: [{"
"
\"
type
\"
:
\"
MasterFiles
\"
,"
"
\"
params
\"
: {"
"
\"
test1.example
\"
:
\"
"
+
std
::
string
(
TEST_DATA_BUILDDIR
"/test1.zone.copied"
)
+
"
\"
},"
"
\"
cache-enable
\"
: true,"
"
\"
cache-type
\"
:
\"
mapped
\"
"
"}]}"
);
clients_map
=
configureDataSource
(
config
);
EXPECT_THROW
(
builder
.
handleCommand
(
Command
(
LOADZONE
,
Element
::
fromJSON
(
"{
\"
origin
\"
:
\"
test1.example
\"
,"
"
\"
class
\"
:
\"
IN
\"
}"
))),
TestDataSrcClientsBuilder
::
InternalCommandError
);
}
}
// unnamed namespace
src/lib/datasrc/cache_config.cc
View file @
a3d4fe8a
...
...
@@ -177,7 +177,7 @@ CacheConfig::getLoadAction(const dns::RRClass& rrclass,
assert
(
datasrc_client_
);
// If the specified zone name does not exist in our client of the source,
//
DataSourceError
is thrown, which is exactly the result what we
//
NoSuchZone
is thrown, which is exactly the result what we
// want, so no need to handle it.
ZoneIteratorPtr
iterator
(
datasrc_client_
->
getIterator
(
zone_name
));
if
(
!
iterator
)
{
...
...
src/lib/datasrc/cache_config.h
View file @
a3d4fe8a
...
...
@@ -157,12 +157,13 @@ public:
/// It doesn't throw an exception in this case because the expected caller
/// of this method would handle such a case internally.
///
/// \throw DataSourceError error happens in the underlying data source
/// storing the cache data. Most commonly it's because the specified zone
/// doesn't exist there.
/// \throw NoSuchZone The specified zone doesn't exist in the
/// underlying data source storing the original data to be cached.
/// \throw DataSourceError Other, unexpected but possible error happens
/// in the underlying data source.
/// \throw Unexpected Unexpected error happens in the underlying data
/// source
storing the cache data
. This shouldn't happen as long as the
///
data source
implementation meets the public API requirement.
/// source. This shouldn't happen as long as the
data source
/// implementation meets the public API requirement.
///
/// \param rrclass The RR class of the zone
/// \param zone_name The origin name of the zone
...
...
src/lib/datasrc/client.h
View file @
a3d4fe8a
...
...
@@ -201,9 +201,6 @@ public:
/// This allows for traversing the whole zone. The returned object can
/// provide the RRsets one by one.
///
/// This throws DataSourceError when the zone does not exist in the
/// datasource.
///
/// The default implementation throws isc::NotImplemented. This allows
/// for easy and fast deployment of minimal custom data sources, where
/// the user/implementer doesn't have to care about anything else but
...
...
@@ -214,6 +211,11 @@ public:
/// It is not fixed if a concrete implementation of this method can throw
/// anything else.
///
/// \throw NoSuchZone the zone does not exist in the datasource.
/// \throw Others Possibly implementation specific exceptions (it is
/// not fixed if a concrete implementation of this method can throw
/// anything else.)
///
/// \param name The name of zone apex to be traversed. It doesn't do
/// nearest match as findZone.
/// \param separate_rrs If true, the iterator will return each RR as a
...
...
src/lib/datasrc/client_list.cc
View file @
a3d4fe8a
...
...
@@ -102,10 +102,11 @@ ConfigurableClientList::configure(const ConstElementPtr& config,
}
// Get the name (either explicit, or guess)
const
ConstElementPtr
name_elem
(
dconf
->
get
(
"name"
));
const
string
name
(
name_elem
?
name_elem
->
stringValue
()
:
type
);
if
(
!
used_names
.
insert
(
name
).
second
)
{
const
string
datasrc_name
=
name_elem
?
name_elem
->
stringValue
()
:
type
;
if
(
!
used_names
.
insert
(
datasrc_name
).
second
)
{
isc_throw
(
ConfigurationError
,
"Duplicate name in client list: "
<<
name
);
<<
datasrc_
name
);
}
// Create a client for the underling data source via factory.
...
...
@@ -116,7 +117,7 @@ ConfigurableClientList::configure(const ConstElementPtr& config,
paramConf
);
if
(
!
allow_cache
&&
!
dsrc_pair
.
first
)
{
LOG_WARN
(
logger
,
DATASRC_LIST_NOT_CACHED
).
arg
(
name
).
arg
(
rrclass_
);
arg
(
datasrc_
name
).
arg
(
rrclass_
);
continue
;
}
...
...
@@ -129,13 +130,22 @@ ConfigurableClientList::configure(const ConstElementPtr& config,
new_data_sources
.
push_back
(
DataSourceInfo
(
dsrc_pair
.
first
,
dsrc_pair
.
second
,
cache_conf
,
rrclass_
,
name
));
datasrc_
name
));
// If cache is disabled we are done for this data source.
// If cache is disabled, or the zone table segment is not (yet)
// writable, we are done for this data source.
// Otherwise load zones into the in-memory cache.
if
(
!
cache_conf
->
isEnabled
())
{
continue
;
}
memory
::
ZoneTableSegment
&
zt_segment
=
*
new_data_sources
.
back
().
ztable_segment_
;
if
(
!
zt_segment
.
isWritable
())
{
LOG_DEBUG
(
logger
,
DBGLVL_TRACE_BASIC
,
DATASRC_LIST_CACHE_PENDING
).
arg
(
datasrc_name
);
continue
;
}
internal
::
CacheConfig
::
ConstZoneIterator
end_of_zones
=
cache_conf
->
end
();
for
(
internal
::
CacheConfig
::
ConstZoneIterator
zone_it
=
...
...
@@ -144,25 +154,23 @@ ConfigurableClientList::configure(const ConstElementPtr& config,
++
zone_it
)
{
const
Name
&
zname
=
zone_it
->
first
;
memory
::
LoadAction
load_action
;
try
{
load_action
=
cache_conf
->
getLoadAction
(
rrclass_
,
zname
);
}
catch
(
const
DataSourceError
&
)
{
isc_throw
(
ConfigurationError
,
"Data source error for "
"loading a zone (possibly non-existent) "
<<
zname
<<
"/"
<<
rrclass_
);
}
assert
(
load_action
);
// in this loop this should be always true
try
{
memory
::
ZoneWriter
writer
(
*
new_data_sources
.
back
().
ztable_segment_
,
const
memory
::
LoadAction
load_action
=
cache_conf
->
getLoadAction
(
rrclass_
,
zname
);
// in this loop this should be always true
assert
(
load_action
);
memory
::
ZoneWriter
writer
(
zt_segment
,
load_action
,
zname
,
rrclass_
);
writer
.
load
();
writer
.
install
();
writer
.
cleanup
();
}
catch
(
const
NoSuchZone
&
)
{
LOG_ERROR
(
logger
,
DATASRC_CACHE_ZONE_NOTFOUND
).
arg
(
zname
).
arg
(
rrclass_
).
arg
(
datasrc_name
);
}
catch
(
const
ZoneLoaderException
&
e
)
{
LOG_ERROR
(
logger
,
DATASRC_LOAD_ZONE_ERROR
)
.
arg
(
zname
).
arg
(
rrclass_
).
arg
(
name
).
arg
(
e
.
what
());
LOG_ERROR
(
logger
,
DATASRC_LOAD_ZONE_ERROR
).
arg
(
zname
).
arg
(
rrclass_
).
arg
(
datasrc_name
).
arg
(
e
.
what
());
}
}
}
...
...
@@ -309,48 +317,56 @@ ConfigurableClientList::findInternal(MutableResult& candidate,
// and the need_updater parameter is true, get the zone there.
}
// We still provide this method for backward compatibility. But to not have
// duplicate code, it is a thin wrapper around getCachedZoneWriter only.
ConfigurableClientList
::
ReloadResult
ConfigurableClientList
::
reload
(
const
Name
&
name
)
{
const
ZoneWriterPair
result
(
getCachedZoneWriter
(
name
));
if
(
result
.
first
!=
ZONE_SUCCESS
)
{
return
(
result
.
first
);
}
assert
(
result
.
second
);
result
.
second
->
load
();
result
.
second
->
install
();
result
.
second
->
cleanup
();
return
(
ZONE_SUCCESS
);
}
ConfigurableClientList
::
ZoneWriterPair
ConfigurableClientList
::
getCachedZoneWriter
(
const
Name
&
name
)
{
ConfigurableClientList
::
getCachedZoneWriter
(
const
Name
&
name
,
const
std
::
string
&
datasrc_name
)
{
if
(
!
allow_cache_
)
{
return
(
ZoneWriterPair
(
CACHE_DISABLED
,
ZoneWriterPtr
()));
}
// Try to find the correct zone.
MutableResult
result
;
findInternal
(
result
,
name
,
true
,
true
);
if
(
!
result
.
finder
)
{
return
(
ZoneWriterPair
(
ZONE_NOT_FOUND
,
ZoneWriterPtr
()));
}
// Find the data source from which the zone to be loaded into memory.
// Then get the appropriate load action and create a zone writer.
// Note that getCacheConfig() must return non NULL in this module (only
// tests could set it to a bogus value).
const
memory
::
LoadAction
load_action
=
result
.
info
->
getCacheConfig
()
->
getLoadAction
(
rrclass_
,
name
);
if
(
!
load_action
)
{
return
(
ZoneWriterPair
(
ZONE_NOT_CACHED
,
ZoneWriterPtr
()));
BOOST_FOREACH
(
const
DataSourceInfo
&
info
,
data_sources_
)
{
if
(
!
datasrc_name
.
empty
()
&&
datasrc_name
!=
info
.
name_
)
{
continue
;
}
// If there's an underlying "real" data source and it doesn't contain
// the given name, obviously we cannot load it. If a specific data
// source is given by the name, search should stop here.
if
(
info
.
data_src_client_
&&
info
.
data_src_client_
->
findZone
(
name
).
code
!=
result
::
SUCCESS
)
{
if
(
!
datasrc_name
.
empty
())
{
return
(
ZoneWriterPair
(
ZONE_NOT_FOUND
,
ZoneWriterPtr
()));
}
continue
;
}
// If the corresponding zone table segment is not (yet) writable,
// we cannot load at this time.
if
(
info
.
ztable_segment_
&&
!
info
.
ztable_segment_
->
isWritable
())
{
return
(
ZoneWriterPair
(
CACHE_NOT_WRITABLE
,
ZoneWriterPtr
()));
}
// Note that getCacheConfig() must return non NULL in this module
// (only tests could set it to a bogus value).
const
memory
::
LoadAction
load_action
=
info
.
getCacheConfig
()
->
getLoadAction
(
rrclass_
,
name
);
if
(
!
load_action
)
{
return
(
ZoneWriterPair
(
ZONE_NOT_CACHED
,
ZoneWriterPtr
()));
}
return
(
ZoneWriterPair
(
ZONE_SUCCESS
,
ZoneWriterPtr
(
new
memory
::
ZoneWriter
(
*
info
.
ztable_segment_
,
load_action
,
name
,
rrclass_
))));
}
// We can't find the specified zone. If a specific data source was
// given, this means the given name of data source doesn't exist, so
// we report it so.
if
(
!
datasrc_name
.
empty
())
{
return
(
ZoneWriterPair
(
DATASRC_NOT_FOUND
,
ZoneWriterPtr
()));
}
return
(
ZoneWriterPair
(
ZONE_SUCCESS
,
ZoneWriterPtr
(
new
memory
::
ZoneWriter
(
*
result
.
info
->
ztable_segment_
,
load_action
,
name
,
rrclass_
))));
return
(
ZoneWriterPair
(
ZONE_NOT_FOUND
,
ZoneWriterPtr
()));
}
// NOTE: This function is not tested, it would be complicated. However, the
...
...
src/lib/datasrc/client_list.h
View file @
a3d4fe8a
...
...
@@ -339,50 +339,51 @@ public:
return
(
configuration_
);
}
/// \brief Result of the reload() method.
enum
ReloadResult
{
CACHE_DISABLED
,
///< The cache is not enabled in this list.
ZONE_NOT_CACHED
,
///< Zone is served directly, not from cache
/// (including the case cache is disabled for
/// the specific data source).
ZONE_NOT_FOUND
,
///< Zone does not exist in this list.
ZONE_SUCCESS
///< The zone was successfully reloaded or
/// the writer provided.
};
/// \brief Reloads a cached zone.
///
/// This method finds a zone which is loaded into a cache and reloads it.
/// This may be used to renew the cache when the underlying data source
/// changes.
///
/// \param zone The origin of the zone to reload.
/// \return A status if the command worked.
/// \throw DataSourceError or anything else that the data source
/// containing the zone might throw is propagated.
/// \throw DataSourceError if something unexpected happens, like when
/// the original data source no longer contains the cached zone.
ReloadResult
reload
(
const
dns
::
Name
&
zone
);
private:
/// \brief Convenience type shortcut
typedef
boost
::
shared_ptr
<
memory
::
ZoneWriter
>
ZoneWriterPtr
;
public:
/// \brief Codes indicating in-memory cache status for a given zone name.
///
/// This is used as a result of the getCachedZoneWriter() method.
enum
CacheStatus
{
CACHE_DISABLED
,
///< The cache is not enabled in this list.
ZONE_NOT_CACHED
,
///< Zone is not to be cached (including the case
/// where caching is disabled for the specific
/// data source).
ZONE_NOT_FOUND
,
///< Zone does not exist in this list.
CACHE_NOT_WRITABLE
,
///< The cache is not writable (and zones can't
/// be loaded)
DATASRC_NOT_FOUND
,
///< Specific data source for load is specified
/// but it's not in the list
ZONE_SUCCESS
///< Zone to be cached is successfully found and
/// is ready to be loaded
};
/// \brief Return value of getCachedZoneWriter()
///
/// A pair containing status and the zone writer, for the
/// getCachedZoneWriter() method.
typedef
std
::
pair
<
ReloadResult
,
ZoneWriterPtr
>
ZoneWriterPair
;
/// \brief Return a zone writer that can be used to reload a zone.
///
/// This looks up a cached copy of zone and returns the ZoneWriter
/// that can be used to reload the content of the zone. This can
/// be used instead of reload() -- reload() works synchronously, which
/// is not what is needed every time.
///
/// \param zone The origin of the zone to reload.
typedef
std
::
pair
<
CacheStatus
,
ZoneWriterPtr
>
ZoneWriterPair
;
/// \brief Return a zone writer that can be used to (re)load a zone.
///
/// By default this method identifies the first data source in the list
/// that should serve the zone of the given name, and returns a ZoneWriter
/// object that can be used to load the content of the zone, in a specific
/// way for that data source.
///
/// If the optional \c datasrc_name parameter is provided with a non empty
/// string, this method only tries to load the specified zone into or with
/// the data source which has the given name, regardless where in the list
/// that data source is placed. Even if the given name of zone doesn't
/// exist in the data source, other data sources are not searched and
/// this method simply returns ZONE_NOT_FOUND in the first element
/// of the pair.
///
/// \param zone The origin of the zone to load.
/// \param datasrc_name If not empty, the name of the data source
/// to be used for loading the zone (see above).
/// \return The result has two parts. The first one is a status describing
/// if it worked or not (and in case it didn't, also why). If the
/// status is ZONE_SUCCESS, the second part contains a shared pointer
...
...
@@ -390,9 +391,8 @@ public:
/// NULL.
/// \throw DataSourceError or anything else that the data source
/// containing the zone might throw is propagated.
/// \throw DataSourceError if something unexpected happens, like when
/// the original data source no longer contains the cached zone.
ZoneWriterPair
getCachedZoneWriter
(
const
dns
::
Name
&
zone
);
ZoneWriterPair
getCachedZoneWriter
(
const
dns
::
Name
&
zone
,
const
std
::
string
&
datasrc_name
=
""
);
/// \brief Implementation of the ClientList::find.
virtual
FindResult
find
(
const
dns
::
Name
&
zone
,
...
...
@@ -421,12 +421,12 @@ public:
boost
::
shared_ptr
<
memory
::
ZoneTableSegment
>
ztable_segment_
;
std
::
string
name_
;
// cache_conf_ can be accessed only from this read-only getter,
// to protect its integrity as much as possible.
const
internal
::
CacheConfig
*
getCacheConfig
()
const
{
return
(
cache_conf_
.
get
());
}
private:
// this is kept private for now. When it needs to be accessed,
// we'll add a read-only getter method.
boost
::
shared_ptr
<
internal
::
CacheConfig
>
cache_conf_
;
};
...
...
src/lib/datasrc/database.cc
View file @
a3d4fe8a
...
...
@@ -1233,7 +1233,7 @@ public:
const
pair
<
bool
,
int
>
zone
(
accessor_
->
getZone
(
zone_name
.
toText
()));
if
(
!
zone
.
first
)
{
// No such zone, can't continue
isc_throw
(
DataSourceError
,
"Zone "
+
zone_name
.
toText
()
+
isc_throw
(
NoSuchZone
,
"Zone "
+
zone_name
.
toText
()
+
" can not be iterated, because it doesn't exist "
"in this data source"
);
}
...
...
src/lib/datasrc/datasrc_messages.mes
View file @
a3d4fe8a
...
...
@@ -70,6 +70,15 @@ The maximum allowed number of items of the hotspot cache is set to the given
number. If there are too many, some of them will be dropped. The size of 0
means no limit.
% DATASRC_CACHE_ZONE_NOTFOUND Zone %1/%2 not found on data source '%3' to cache
During data source configuration, a zone is to be loaded (cached) in
to memory from the underlying data source, but the zone is not found
in the data source. This particular zone was not loaded, but data
source configuration continues, possibly loading other zones into
memory. This is basically some kind of configuration or operation
error: either the name is incorrect in the configuration, or the zone
has been removed from the data source without updating the configuration.
% DATASRC_CHECK_ERROR post-load check of zone %1/%2 failed: %3
The zone was loaded into the data source successfully, but the content fails
basic sanity checks. See the message if you want to know what exactly is wrong
...
...
@@ -347,6 +356,13 @@ not contain RRs the requested type. AN NXRRSET indication is returned.
A debug message indicating that a query for the given name and RR type is being
processed.
% DATASRC_LIST_CACHE_PENDING in-memory cache for data source '%1' is not yet writable, pending load
While (re)configuring data source clients, zone data of the shown data
source cannot be loaded to in-memory cache at that point because the
cache is not yet ready for writing. This can happen for shared-memory
type of cache, in which case the cache will be reset later, either
by a higher level application or by a command from other module.
% DATASRC_LIST_NOT_CACHED zones in data source %1 for class %2 not cached, cache disabled globally. Will not be available.
The process disabled caching of RR data completely. However, this data source
is provided from a master file and it can be served from memory cache only.
...
...
@@ -354,7 +370,7 @@ Therefore, the entire data source will not be available for this process. If
this is a problem, you should configure the zones of that data source to some
database backend (sqlite3, for example) and use it from there.
% DATASRC_LOAD_ZONE_ERROR Error loading zone %1/%2 on data source %3: %4
% DATASRC_LOAD_ZONE_ERROR Error loading zone %1/%2 on data source
'
%3
'
: %4
During data source configuration, an error was found in the zone data
when it was being loaded in to memory on the shown data source. This
particular zone was not loaded, but data source configuration
...
...
src/lib/datasrc/exceptions.h
View file @
a3d4fe8a
...
...
@@ -20,8 +20,14 @@
namespace
isc
{
namespace
datasrc
{
/// This exception represents Backend-independent errors relating to
/// data source operations.
/// \brief Top level exception related to data source.
///
/// This exception is the most generic form of exception for errors or
/// unexpected events that can happen in the data source module. In general,
/// if an application needs to catch these conditions explicitly, it should
/// catch more specific exceptions derived from this class; the severity
/// of the conditions will vary very much, and such an application would
/// normally like to behave differently depending on the severity.
class
DataSourceError
:
public
Exception
{
public:
DataSourceError
(
const
char
*
file
,
size_t
line
,
const
char
*
what
)
:
...
...
@@ -40,6 +46,16 @@ public:
DataSourceError
(
file
,
line
,
what
)
{}
};
/// \brief A specified zone does not exist in the specified data source.
///
/// This exception is thrown from methods that take a zone name and perform
/// some action regarding that zone on the corresponding data source.
class
NoSuchZone
:
public
DataSourceError
{
public:
NoSuchZone
(
const
char
*
file
,
size_t
line
,
const
char
*
what
)
:
DataSourceError
(
file
,
line
,
what
)
{}
};
/// Base class for a number of exceptions that are thrown while working
/// with zones.
struct
ZoneException
:
public
Exception
{
...
...
src/lib/datasrc/memory/memory_client.cc
View file @
a3d4fe8a
...
...
@@ -242,7 +242,7 @@ InMemoryClient::getIterator(const Name& name, bool separate_rrs) const {
const
ZoneTable
*
zone_table
=
ztable_segment_
->
getHeader
().
getTable
();
const
ZoneTable
::
FindResult
result
(
zone_table
->
findZone
(
name
));
if
(
result
.
code
!=
result
::
SUCCESS
)
{
isc_throw
(
DataSourceError
,
"No such zone: "
+
name
.
toText
());
isc_throw
(
NoSuchZone
,
"No such zone: "
+
name
.
toText
());
}
return
(
ZoneIteratorPtr
(
new
MemoryIterator
(
...
...
src/lib/datasrc/tests/cache_config_unittest.cc
View file @
a3d4fe8a
...
...
@@ -281,7 +281,7 @@ TEST_F(CacheConfigTest, getLoadActionWithMock) {
// Zone configured for the cache but doesn't exist in the underling data
// source.
EXPECT_THROW
(
cache_conf
.
getLoadAction
(
RRClass
::
IN
(),
Name
(
"example.net"
)),
DataSourceError
);
NoSuchZone
);
// buggy data source client: it returns a null pointer from getIterator.
EXPECT_THROW
(
cache_conf
.
getLoadAction
(
RRClass
::
IN
(),
Name
(
"null.org"
)),
...
...
src/lib/datasrc/tests/client_list_unittest.cc
View file @
a3d4fe8a
...
...
@@ -250,6 +250,9 @@ public:
EXPECT_EQ
(
cache
,
list_
->
getDataSources
()[
index
].
cache_
!=
shared_ptr
<
InMemoryClient
>
());
}
ConfigurableClientList
::
CacheStatus
doReload
(
const
Name
&
origin
,
const
string
&
datasrc_name
=
""
);
const
RRClass
rrclass_
;
shared_ptr
<
TestedList
>
list_
;
const
ClientList
::
FindResult
negative_result_
;
...
...
@@ -668,17 +671,20 @@ TEST_F(ListTest, cacheZones) {
TEST_F
(
ListTest
,
badCache
)
{
list_
->
configure
(
config_elem_
,
true
);
checkDS
(
0
,
"test_type"
,
"{}"
,
false
);
// First, the zone is not in the data source
// First, the zone is not in the data source. configure() should still
// succeed, and the existence zone should be cached.
const
ConstElementPtr
elem1
(
Element
::
fromJSON
(
"["
"{"
"
\"
type
\"
:
\"
type
1
\"
,"
"
\"
type
\"
:
\"
test_
type
\"
,"
"
\"
cache-enable
\"
: true,"
"
\"
cache-zones
\"
: [
\"
example.org
\"
],"
"
\"
params
\"
: []"
"
\"
cache-zones
\"
: [
\"
example.org
\"
,
\"
example.com
\"
],"
"
\"
params
\"
: [
\"
example.org
\"
]"
"}]"
));
EXPECT_THROW
(
list_
->
configure
(
elem1
,
true
),
ConfigurableClientList
::
ConfigurationError
);
checkDS
(
0
,
"test_type"
,
"{}"
,
false
);
list_
->
configure
(
elem1
,
true
);
// shouldn't cause disruption
checkDS
(
0
,
"test_type"
,
"[
\"
example.org
\"
]"
,
true
);
const
shared_ptr
<
InMemoryClient
>
cache
(
list_
->
getDataSources
()[
0
].
cache_
);
EXPECT_EQ
(
1
,
cache
->
getZoneCount
());
EXPECT_EQ
(
result
::
SUCCESS
,
cache
->
findZone
(
Name
(
"example.org"
)).
code
);
// Now, the zone doesn't give an iterator
const
ConstElementPtr
elem2
(
Element
::
fromJSON
(
"["
"{"
...
...
@@ -688,7 +694,7 @@ TEST_F(ListTest, badCache) {
"
\"
params
\"
: [
\"
noiter.org
\"
]"
"}]"
));
EXPECT_THROW
(
list_
->
configure
(
elem2
,
true
),
isc
::
NotImplemented
);
checkDS
(
0
,
"test_type"
,
"
{}"
,
fals
e
);
checkDS
(
0
,
"test_type"
,
"
[
\"
example.org
\"
]"
,
tru
e
);
// Now, the zone returns NULL iterator
const
ConstElementPtr
elem3
(
Element
::
fromJSON
(
"["
"{"
...
...
@@ -698,7 +704,7 @@ TEST_F(ListTest, badCache) {
"
\"
params
\"
: [
\"
null.org
\"
]"
"}]"
));
EXPECT_THROW
(
list_
->
configure
(
elem3
,
true
),
isc
::
Unexpected
);
checkDS
(
0
,
"test_type"
,
"
{}"
,
fals
e
);
checkDS
(
0
,
"test_type"
,
"
[
\"
example.org
\"
]"
,
tru
e
);
// The autodetection of zones is not enabled
const
ConstElementPtr
elem4
(
Element
::
fromJSON
(
"["
"{"
...
...
@@ -707,7 +713,35 @@ TEST_F(ListTest, badCache) {
"
\"
params
\"
: [
\"
example.org
\"
]"
"}]"
));
EXPECT_THROW
(
list_
->
configure
(
elem4
,
true
),
isc
::
NotImplemented
);
checkDS
(
0
,
"test_type"
,
"{}"
,
false
);
checkDS
(
0
,
"test_type"
,
"[
\"
example.org
\"
]"
,
true
);
}
// This test relies on the property of mapped type of cache.
TEST_F
(
ListTest
,
#ifdef USE_SHARED_MEMORY
cacheInNonWritableSegment