Skip to content
GitLab
Projects
Groups
Snippets
/
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Menu
Open sidebar
ISC Open Source Projects
Kea
Commits
c6de8f18
Commit
c6de8f18
authored
Jul 28, 2012
by
JINMEI Tatuya
Browse files
[master] Merge branch 'trac2091b'
parents
3e4bfd2a
01d1c2a8
Changes
12
Expand all
Hide whitespace changes
Inline
Side-by-side
src/lib/datasrc/memory/rdata_encoder.cc
View file @
c6de8f18
...
...
@@ -297,18 +297,10 @@ encodeRdata(const rdata::Rdata& rdata, RRClass rrclass, RRType rrtype,
{
const
Name
name
(
ibuffer
);
const
LabelSequence
labels
(
name
);
size_t
nlen
;
const
uint8_t
*
ndata
=
labels
.
getData
(
&
nlen
);
assert
(
nlen
<
256
);
// nlen should fit in 8 bits
size_t
olen
;
uint8_t
offset_holder
[
Name
::
MAX_LABELS
];
labels
.
getOffsetData
(
&
olen
,
offset_holder
);
assert
(
olen
<
256
);
// olen should fit in 8 bits
data_result
.
push_back
(
nlen
);
data_result
.
push_back
(
olen
);
data_result
.
insert
(
data_result
.
end
(),
ndata
,
ndata
+
nlen
);
data_result
.
insert
(
data_result
.
end
(),
offset_holder
,
offset_holder
+
olen
);
uint8_t
labels_holder
[
LabelSequence
::
MAX_SERIALIZED_LENGTH
];
labels
.
serialize
(
labels_holder
,
sizeof
(
labels_holder
));
data_result
.
insert
(
data_result
.
end
(),
labels_holder
,
labels_holder
+
labels
.
getSerializedLength
());
break
;
}
}
...
...
@@ -348,15 +340,11 @@ foreachRdataField(RRClass rrclass, RRType rrtype,
case
RdataFieldSpec
::
DOMAIN_NAME
:
{
++
name_count
;
const
uint8_t
nlen
=
encoded_data
.
at
(
off
);
const
uint8_t
olen
=
encoded_data
.
at
(
off
+
1
);
const
LabelSequence
labels
(
&
encoded_data
.
at
(
off
));
if
(
name_callback
)
{
const
uint8_t
*
ndata
=
&
encoded_data
.
at
(
off
+
2
);
const
uint8_t
*
odata
=
&
encoded_data
.
at
(
off
+
2
+
nlen
);
name_callback
(
LabelSequence
(
ndata
,
odata
,
olen
),
field_spec
.
name_attributes
);
name_callback
(
labels
,
field_spec
.
name_attributes
);
}
off
+=
(
2
+
nlen
+
olen
);
off
+=
labels
.
getSerializedLength
(
);
break
;
}
}
...
...
src/lib/datasrc/memory_datasrc.cc
View file @
c6de8f18
...
...
@@ -14,6 +14,8 @@
#include
<exceptions/exceptions.h>
#include
<util/memory_segment_local.h>
#include
<dns/name.h>
#include
<dns/nsec3hash.h>
#include
<dns/rdataclass.h>
...
...
@@ -120,19 +122,48 @@ typedef NSEC3Map::value_type NSEC3Pair;
// Actual zone data: Essentially a set of zone's RRs. This is defined as
// a separate structure so that it'll be replaceable on reload.
struct
ZoneData
{
// Note: this code is not entirely exception safe; domains_storage_ could
// leak if the constructor throws. But since it's an intermediate version
// toward a full revision and the actual risk of leak should be very small
// in practice, we leave it open for now.
ZoneData
(
const
Name
&
origin
)
:
domains_
(
true
),
domains_storage_
(
DomainTree
::
create
(
local_mem_sgmt_
,
true
)),
domains_
(
*
domains_storage_
),
aux_wild_domains_
(
NULL
),
origin_data_
(
NULL
),
nsec_signed_
(
false
)
{
// We create the node for origin (it needs to exist anyway in future)
domains_
.
insert
(
origin
,
&
origin_data_
);
domains_
.
insert
(
local_mem_sgmt_
,
origin
,
&
origin_data_
);
DomainPtr
origin_domain
(
new
Domain
);
origin_data_
->
setData
(
origin_domain
);
}
// The main data (name + RRsets)
DomainTree
domains_
;
~
ZoneData
()
{
DomainTree
::
destroy
(
local_mem_sgmt_
,
domains_storage_
);
if
(
aux_wild_domains_
!=
NULL
)
{
DomainTree
::
destroy
(
local_mem_sgmt_
,
aux_wild_domains_
);
}
// The assert may be too harsh, but we assume we'll discard (rewrite)
// this code soon enough. Until then this would be a good way to
// detect any memory leak. Also, at that point we shouldn't use
// a single separate memory segment for each zone tree; normally
// zone data for multiple zones will be managed in a single segment.
assert
(
local_mem_sgmt_
.
allMemoryDeallocated
());
}
// Memory segment to allocate/deallocate memory for the tree and the nodes.
// (This will eventually have to be abstract; for now we hardcode the
// specific derived segment class).
util
::
MemorySegmentLocal
local_mem_sgmt_
;
// The main data (name + RRsets). We use domains_ as a reference to
// domains_storage_ so we don't have to update the rest of the code;
// it will eventually have to be revised substantially, at which point
// we should clean this up, too.
DomainTree
*
domains_storage_
;
DomainTree
&
domains_
;
// An auxiliary tree for wildcard expanded data used in additional data
// processing. It contains names like "ns.wild.example" in the following
...
...
@@ -150,11 +181,11 @@ struct ZoneData {
// should be even empty, and even if it has content it should be very
// small.
private:
scoped_ptr
<
DomainTree
>
aux_wild_domains_
;
DomainTree
*
aux_wild_domains_
;
public:
DomainTree
&
getAuxWildDomains
()
{
if
(
!
aux_wild_domains_
)
{
aux_wild_domains_
.
reset
(
new
DomainTree
);
if
(
aux_wild_domains_
==
NULL
)
{
aux_wild_domains_
=
DomainTree
::
create
(
local_mem_sgmt_
);
}
return
(
*
aux_wild_domains_
);
}
...
...
@@ -448,15 +479,11 @@ ZoneData::findNode(const Name& name, RBTreeNodeChain<Domain>& node_path,
if
(
node
->
getFlag
(
domain_flag
::
WILD
)
&&
// maybe a wildcard, check only
(
options
&
ZoneFinder
::
NO_WILDCARD
)
==
0
)
{
// if not disabled.
if
(
node_path
.
getLastComparisonResult
().
getRelation
()
==
NameComparisonResult
::
COMMONANCESTOR
&&
node_path
.
getLastComparisonResult
().
getCommonLabels
()
>
1
)
{
// Wildcard canceled. Treat it as NXDOMAIN.
// Note: Because the way the tree stores relative names, we
// will have exactly one common label (the ".") in case we have
// nothing common under the node we got, and we will get
// more common labels otherwise (yes, this relies on the
// internal RBTree structure, which leaks out through this
// little bit).
NameComparisonResult
::
COMMONANCESTOR
)
{
// This means, e.g., we have *.wild.example and
// bar.foo.wild.example and are looking for
// baz.foo.wild.example. The common ancestor, foo.wild.example,
// should cancel wildcard. Treat it as NXDOMAIN.
LOG_DEBUG
(
logger
,
DBG_TRACE_DATA
,
DATASRC_MEM_WILDCARD_CANCEL
).
arg
(
name
);
return
(
ResultType
(
ZoneFinder
::
NXDOMAIN
,
NULL
,
...
...
@@ -857,7 +884,9 @@ struct InMemoryZoneFinder::InMemoryZoneFinderImpl {
//
// We also perform the same trick for empty wild card names possibly
// contained in 'name' (e.g., '*.foo.example' in 'bar.*.foo.example').
void
addWildcards
(
DomainTree
&
domains
,
const
Name
&
name
)
{
void
addWildcards
(
util
::
MemorySegment
&
mem_sgmt
,
DomainTree
&
domains
,
const
Name
&
name
)
{
Name
wname
(
name
);
const
unsigned
int
labels
(
wname
.
getLabelCount
());
const
unsigned
int
origin_labels
(
origin_
.
getLabelCount
());
...
...
@@ -870,7 +899,8 @@ struct InMemoryZoneFinder::InMemoryZoneFinderImpl {
// Ensure a separate level exists for the "wildcarding" name,
// and mark the node as "wild".
DomainNode
*
node
;
DomainTree
::
Result
result
(
domains
.
insert
(
wname
.
split
(
1
),
DomainTree
::
Result
result
(
domains
.
insert
(
mem_sgmt
,
wname
.
split
(
1
),
&
node
));
assert
(
result
==
DomainTree
::
SUCCESS
||
result
==
DomainTree
::
ALREADYEXISTS
);
...
...
@@ -880,7 +910,7 @@ struct InMemoryZoneFinder::InMemoryZoneFinderImpl {
// Note: for 'name' itself we do this later anyway, but the
// overhead should be marginal because wildcard names should
// be rare.
result
=
domains
.
insert
(
wname
,
&
node
);
result
=
domains
.
insert
(
mem_sgmt
,
wname
,
&
node
);
assert
(
result
==
DomainTree
::
SUCCESS
||
result
==
DomainTree
::
ALREADYEXISTS
);
}
...
...
@@ -1167,12 +1197,14 @@ struct InMemoryZoneFinder::InMemoryZoneFinderImpl {
// tree.
// Note: this can throw an exception, breaking strong exception
// guarantee. (see also the note for contextCheck() below).
addWildcards
(
zone_data
.
domains_
,
rrset
->
getName
());
addWildcards
(
zone_data
.
local_mem_sgmt_
,
zone_data
.
domains_
,
rrset
->
getName
());
// Get the node
DomainNode
*
node
;
DomainTree
::
Result
result
=
zone_data
.
domains_
.
insert
(
rrset
->
getName
(),
&
node
);
DomainTree
::
Result
result
=
zone_data
.
domains_
.
insert
(
zone_data
.
local_mem_sgmt_
,
rrset
->
getName
(),
&
node
);
// Just check it returns reasonable results
assert
((
result
==
DomainTree
::
SUCCESS
||
result
==
DomainTree
::
ALREADYEXISTS
)
&&
node
!=
NULL
);
...
...
@@ -1605,7 +1637,8 @@ addAdditional(RBNodeRRset* rrset, ZoneData* zone_data,
// Wildcard and glue shouldn't coexist. Make it sure here.
assert
(
!
node
->
getFlag
(
domain_flag
::
GLUE
));
if
(
zone_data
->
getAuxWildDomains
().
insert
(
name
,
&
wildnode
)
if
(
zone_data
->
getAuxWildDomains
().
insert
(
zone_data
->
local_mem_sgmt_
,
name
,
&
wildnode
)
==
DomainTree
::
SUCCESS
)
{
// If we first insert the node, copy the RRsets. If the
// original node was empty, we add empty data so
...
...
@@ -1782,9 +1815,22 @@ InMemoryZoneFinder::getFileName() const {
/// member variables later for new features.
class
InMemoryClient
::
InMemoryClientImpl
{
public:
InMemoryClientImpl
()
:
zone_count
(
0
)
{}
InMemoryClientImpl
()
:
zone_count
(
0
),
zone_table
(
ZoneTable
::
create
(
local_mem_sgmt
))
{}
~
InMemoryClientImpl
()
{
ZoneTable
::
destroy
(
local_mem_sgmt
,
zone_table
);
// see above for the assert().
assert
(
local_mem_sgmt
.
allMemoryDeallocated
());
}
// Memory segment to allocate/deallocate memory for the zone table.
// (This will eventually have to be abstract; for now we hardcode the
// specific derived segment class).
util
::
MemorySegmentLocal
local_mem_sgmt
;
unsigned
int
zone_count
;
ZoneTable
zone_table
;
ZoneTable
*
zone_table
;
};
InMemoryClient
::
InMemoryClient
()
:
impl_
(
new
InMemoryClientImpl
)
...
...
@@ -1809,7 +1855,8 @@ InMemoryClient::addZone(ZoneFinderPtr zone_finder) {
LOG_DEBUG
(
logger
,
DBG_TRACE_BASIC
,
DATASRC_MEM_ADD_ZONE
).
arg
(
zone_finder
->
getOrigin
()).
arg
(
zone_finder
->
getClass
().
toText
());
const
result
::
Result
result
=
impl_
->
zone_table
.
addZone
(
zone_finder
);
const
result
::
Result
result
=
impl_
->
zone_table
->
addZone
(
impl_
->
local_mem_sgmt
,
zone_finder
);
if
(
result
==
result
::
SUCCESS
)
{
++
impl_
->
zone_count
;
}
...
...
@@ -1819,7 +1866,7 @@ InMemoryClient::addZone(ZoneFinderPtr zone_finder) {
InMemoryClient
::
FindResult
InMemoryClient
::
findZone
(
const
isc
::
dns
::
Name
&
name
)
const
{
LOG_DEBUG
(
logger
,
DBG_TRACE_DATA
,
DATASRC_MEM_FIND_ZONE
).
arg
(
name
);
ZoneTable
::
FindResult
result
(
impl_
->
zone_table
.
findZone
(
name
));
ZoneTable
::
FindResult
result
(
impl_
->
zone_table
->
findZone
(
name
));
return
(
FindResult
(
result
.
code
,
result
.
zone
));
}
...
...
@@ -1925,7 +1972,7 @@ public:
ZoneIteratorPtr
InMemoryClient
::
getIterator
(
const
Name
&
name
,
bool
separate_rrs
)
const
{
ZoneTable
::
FindResult
result
(
impl_
->
zone_table
.
findZone
(
name
));
ZoneTable
::
FindResult
result
(
impl_
->
zone_table
->
findZone
(
name
));
if
(
result
.
code
!=
result
::
SUCCESS
)
{
isc_throw
(
DataSourceError
,
"No such zone: "
+
name
.
toText
());
}
...
...
src/lib/datasrc/rbtree.h
View file @
c6de8f18
This diff is collapsed.
Click to expand it.
src/lib/datasrc/tests/Makefile.am
View file @
c6de8f18
...
...
@@ -60,6 +60,7 @@ run_unittests_SOURCES += sqlite3_unittest.cc
run_unittests_SOURCES
+=
sqlite3_accessor_unittest.cc
run_unittests_SOURCES
+=
memory_datasrc_unittest.cc
run_unittests_SOURCES
+=
rbnode_rrset_unittest.cc
run_unittests_SOURCES
+=
zonetable_unittest.cc
run_unittests_SOURCES
+=
zone_finder_context_unittest.cc
run_unittests_SOURCES
+=
faked_nsec3.h faked_nsec3.cc
run_unittests_SOURCES
+=
client_list_unittest.cc
...
...
src/lib/datasrc/tests/rbtree_unittest.cc
View file @
c6de8f18
This diff is collapsed.
Click to expand it.
src/lib/datasrc/tests/zonetable_unittest.cc
View file @
c6de8f18
...
...
@@ -14,6 +14,8 @@
#include
<exceptions/exceptions.h>
#include
<util/memory_segment_local.h>
#include
<dns/name.h>
#include
<dns/rrclass.h>
...
...
@@ -40,7 +42,7 @@ TEST(ZoneTest, init) {
TEST
(
ZoneTest
,
find
)
{
InMemoryZoneFinder
zone
(
RRClass
::
IN
(),
Name
(
"example.com"
));
EXPECT_EQ
(
ZoneFinder
::
NXDOMAIN
,
zone
.
find
(
Name
(
"www.example.com"
),
RRType
::
A
())
.
code
);
zone
.
find
(
Name
(
"www.example.com"
),
RRType
::
A
())
->
code
);
}
class
ZoneTableTest
:
public
::
testing
::
Test
{
...
...
@@ -50,68 +52,77 @@ protected:
zone2
(
new
InMemoryZoneFinder
(
RRClass
::
IN
(),
Name
(
"example.net"
))),
zone3
(
new
InMemoryZoneFinder
(
RRClass
::
IN
(),
Name
(
"example"
)))
Name
(
"example"
))),
zone_table
(
ZoneTable
::
create
(
mem_sgmt_
))
{}
ZoneTable
zone_table
;
~
ZoneTableTest
()
{
ZoneTable
::
destroy
(
mem_sgmt_
,
zone_table
);
}
ZoneFinderPtr
zone1
,
zone2
,
zone3
;
isc
::
util
::
MemorySegmentLocal
mem_sgmt_
;
ZoneTable
*
zone_table
;
};
TEST_F
(
ZoneTableTest
,
addZone
)
{
EXPECT_EQ
(
result
::
SUCCESS
,
zone_table
.
addZone
(
zone1
));
EXPECT_EQ
(
result
::
EXIST
,
zone_table
.
addZone
(
zone1
));
EXPECT_EQ
(
result
::
SUCCESS
,
zone_table
->
addZone
(
mem_sgmt_
,
zone1
));
EXPECT_EQ
(
result
::
EXIST
,
zone_table
->
addZone
(
mem_sgmt_
,
zone1
));
// names are compared in a case insensitive manner.
EXPECT_EQ
(
result
::
EXIST
,
zone_table
.
addZone
(
EXPECT_EQ
(
result
::
EXIST
,
zone_table
->
addZone
(
mem_sgmt_
,
ZoneFinderPtr
(
new
InMemoryZoneFinder
(
RRClass
::
IN
(),
Name
(
"EXAMPLE.COM"
)))));
EXPECT_EQ
(
result
::
SUCCESS
,
zone_table
.
addZone
(
zone2
));
EXPECT_EQ
(
result
::
SUCCESS
,
zone_table
.
addZone
(
zone3
));
EXPECT_EQ
(
result
::
SUCCESS
,
zone_table
->
addZone
(
mem_sgmt_
,
zone2
));
EXPECT_EQ
(
result
::
SUCCESS
,
zone_table
->
addZone
(
mem_sgmt_
,
zone3
));
// Zone table is indexed only by name. Duplicate origin name with
// different zone class isn't allowed.
EXPECT_EQ
(
result
::
EXIST
,
zone_table
.
addZone
(
EXPECT_EQ
(
result
::
EXIST
,
zone_table
->
addZone
(
mem_sgmt_
,
ZoneFinderPtr
(
new
InMemoryZoneFinder
(
RRClass
::
CH
(),
Name
(
"example.com"
)))));
/// Bogus zone (NULL)
EXPECT_THROW
(
zone_table
.
addZone
(
ZoneFinderPtr
()),
isc
::
InvalidParameter
);
EXPECT_THROW
(
zone_table
->
addZone
(
mem_sgmt_
,
ZoneFinderPtr
()),
isc
::
InvalidParameter
);
}
TEST_F
(
ZoneTableTest
,
DISABLED_removeZone
)
{
EXPECT_EQ
(
result
::
SUCCESS
,
zone_table
.
addZone
(
zone1
));
EXPECT_EQ
(
result
::
SUCCESS
,
zone_table
.
addZone
(
zone2
));
EXPECT_EQ
(
result
::
SUCCESS
,
zone_table
.
addZone
(
zone3
));
EXPECT_EQ
(
result
::
SUCCESS
,
zone_table
->
addZone
(
mem_sgmt_
,
zone1
));
EXPECT_EQ
(
result
::
SUCCESS
,
zone_table
->
addZone
(
mem_sgmt_
,
zone2
));
EXPECT_EQ
(
result
::
SUCCESS
,
zone_table
->
addZone
(
mem_sgmt_
,
zone3
));
EXPECT_EQ
(
result
::
SUCCESS
,
zone_table
.
removeZone
(
Name
(
"example.net"
)));
EXPECT_EQ
(
result
::
NOTFOUND
,
zone_table
.
removeZone
(
Name
(
"example.net"
)));
EXPECT_EQ
(
result
::
SUCCESS
,
zone_table
->
removeZone
(
Name
(
"example.net"
)));
EXPECT_EQ
(
result
::
NOTFOUND
,
zone_table
->
removeZone
(
Name
(
"example.net"
)));
}
TEST_F
(
ZoneTableTest
,
findZone
)
{
EXPECT_EQ
(
result
::
SUCCESS
,
zone_table
.
addZone
(
zone1
));
EXPECT_EQ
(
result
::
SUCCESS
,
zone_table
.
addZone
(
zone2
));
EXPECT_EQ
(
result
::
SUCCESS
,
zone_table
.
addZone
(
zone3
));
EXPECT_EQ
(
result
::
SUCCESS
,
zone_table
->
addZone
(
mem_sgmt_
,
zone1
));
EXPECT_EQ
(
result
::
SUCCESS
,
zone_table
->
addZone
(
mem_sgmt_
,
zone2
));
EXPECT_EQ
(
result
::
SUCCESS
,
zone_table
->
addZone
(
mem_sgmt_
,
zone3
));
EXPECT_EQ
(
result
::
SUCCESS
,
zone_table
.
findZone
(
Name
(
"example.com"
)).
code
);
EXPECT_EQ
(
result
::
SUCCESS
,
zone_table
->
findZone
(
Name
(
"example.com"
)).
code
);
EXPECT_EQ
(
Name
(
"example.com"
),
zone_table
.
findZone
(
Name
(
"example.com"
)).
zone
->
getOrigin
());
zone_table
->
findZone
(
Name
(
"example.com"
)).
zone
->
getOrigin
());
EXPECT_EQ
(
result
::
NOTFOUND
,
zone_table
.
findZone
(
Name
(
"example.org"
)).
code
);
zone_table
->
findZone
(
Name
(
"example.org"
)).
code
);
EXPECT_EQ
(
ConstZoneFinderPtr
(),
zone_table
.
findZone
(
Name
(
"example.org"
)).
zone
);
zone_table
->
findZone
(
Name
(
"example.org"
)).
zone
);
// there's no exact match. the result should be the longest match,
// and the code should be PARTIALMATCH.
EXPECT_EQ
(
result
::
PARTIALMATCH
,
zone_table
.
findZone
(
Name
(
"www.example.com"
)).
code
);
zone_table
->
findZone
(
Name
(
"www.example.com"
)).
code
);
EXPECT_EQ
(
Name
(
"example.com"
),
zone_table
.
findZone
(
Name
(
"www.example.com"
)).
zone
->
getOrigin
());
zone_table
->
findZone
(
Name
(
"www.example.com"
)).
zone
->
getOrigin
());
// make sure the partial match is indeed the longest match by adding
// a zone with a shorter origin and query again.
ZoneFinderPtr
zone_com
(
new
InMemoryZoneFinder
(
RRClass
::
IN
(),
Name
(
"com"
)));
EXPECT_EQ
(
result
::
SUCCESS
,
zone_table
.
addZone
(
zone_com
));
EXPECT_EQ
(
result
::
SUCCESS
,
zone_table
->
addZone
(
mem_sgmt_
,
zone_com
));
EXPECT_EQ
(
Name
(
"example.com"
),
zone_table
.
findZone
(
Name
(
"www.example.com"
)).
zone
->
getOrigin
());
zone_table
->
findZone
(
Name
(
"www.example.com"
)).
zone
->
getOrigin
());
}
}
src/lib/datasrc/zonetable.cc
View file @
c6de8f18
...
...
@@ -12,13 +12,15 @@
// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
// PERFORMANCE OF THIS SOFTWARE.
#include
<
cassert
>
#include
<
util/memory_segment.h
>
#include
<dns/name.h>
#include
<datasrc/zonetable.h>
#include
<datasrc/rbtree.h>
#include
<cassert>
using
namespace
std
;
using
namespace
isc
::
dns
;
...
...
@@ -30,8 +32,14 @@ struct ZoneTable::ZoneTableImpl {
// Type aliases to make it shorter
typedef
RBTree
<
ZoneFinder
>
ZoneTree
;
typedef
RBNode
<
ZoneFinder
>
ZoneNode
;
// The actual storage
ZoneTree
zones_
;
ZoneTree
*
zones_
;
// Constructor
ZoneTableImpl
(
util
::
MemorySegment
&
mem_sgmt
)
:
zones_
(
ZoneTree
::
create
(
mem_sgmt
))
{}
/*
* The implementation methods are here and just wrap-called in the
...
...
@@ -40,7 +48,7 @@ struct ZoneTable::ZoneTableImpl {
*/
// Implementation of ZoneTable::addZone
result
::
Result
addZone
(
ZoneFinderPtr
zone
)
{
result
::
Result
addZone
(
util
::
MemorySegment
&
mem_sgmt
,
ZoneFinderPtr
zone
)
{
// Sanity check
if
(
!
zone
)
{
isc_throw
(
InvalidParameter
,
...
...
@@ -49,7 +57,7 @@ struct ZoneTable::ZoneTableImpl {
// Get the node where we put the zone
ZoneNode
*
node
(
NULL
);
switch
(
zones_
.
insert
(
zone
->
getOrigin
(),
&
node
))
{
switch
(
zones_
->
insert
(
mem_sgmt
,
zone
->
getOrigin
(),
&
node
))
{
// This is OK
case
ZoneTree
::
SUCCESS
:
case
ZoneTree
::
ALREADYEXISTS
:
...
...
@@ -76,7 +84,7 @@ struct ZoneTable::ZoneTableImpl {
result
::
Result
my_result
;
// Translate the return codes
switch
(
zones_
.
find
(
name
,
&
node
))
{
switch
(
zones_
->
find
(
name
,
&
node
))
{
case
ZoneTree
::
EXACTMATCH
:
my_result
=
result
::
SUCCESS
;
break
;
...
...
@@ -100,16 +108,39 @@ struct ZoneTable::ZoneTableImpl {
}
};
ZoneTable
::
ZoneTable
()
:
impl_
(
new
ZoneTableImpl
)
ZoneTable
::
ZoneTable
(
util
::
MemorySegment
&
mem_sgmt
)
:
impl_
(
new
ZoneTableImpl
(
mem_sgmt
))
{}
ZoneTable
::~
ZoneTable
()
{
delete
impl_
;
}
ZoneTable
*
ZoneTable
::
create
(
util
::
MemorySegment
&
mem_sgmt
)
{
// The ZoneTable constructor can throw, so we need to prevent memory leak.
// This is ugly, but for now this seems to be the only place we need
// this, and since we'll substantially revise this code soon, so we don't
// work around it by this hack at the moment.
void
*
p
=
mem_sgmt
.
allocate
(
sizeof
(
ZoneTable
));
try
{
return
(
new
(
p
)
ZoneTable
(
mem_sgmt
));
}
catch
(...)
{
mem_sgmt
.
deallocate
(
p
,
sizeof
(
ZoneTable
));
throw
;
}
}
void
ZoneTable
::
destroy
(
util
::
MemorySegment
&
mem_sgmt
,
ZoneTable
*
ztable
)
{
ZoneTableImpl
::
ZoneTree
::
destroy
(
mem_sgmt
,
ztable
->
impl_
->
zones_
);
ztable
->~
ZoneTable
();
mem_sgmt
.
deallocate
(
ztable
,
sizeof
(
ZoneTable
));
}
result
::
Result
ZoneTable
::
addZone
(
ZoneFinderPtr
zone
)
{
return
(
impl_
->
addZone
(
zone
));
ZoneTable
::
addZone
(
util
::
MemorySegment
&
mem_sgmt
,
ZoneFinderPtr
zone
)
{
return
(
impl_
->
addZone
(
mem_sgmt
,
zone
));
}
result
::
Result
...
...
src/lib/datasrc/zonetable.h
View file @
c6de8f18
...
...
@@ -15,12 +15,14 @@
#ifndef __ZONETABLE_H
#define __ZONETABLE_H 1
#include
<
boost/shared_ptr.hpp
>
#include
<
util/memory_segment.h
>
#include
<dns/rrset.h>
#include
<datasrc/zone.h>
#include
<boost/shared_ptr.hpp>
namespace
isc
{
namespace
dns
{
class
Name
;
...
...
@@ -58,18 +60,47 @@ private:
ZoneTable
(
const
ZoneTable
&
source
);
ZoneTable
&
operator
=
(
const
ZoneTable
&
source
);
public:
/// Default constructor.
/// Constructor.
///
/// An object of this class is always expected to be created by the
/// allocator (\c create()), so the constructor is hidden as private.
///
/// This constructor internally involves resource allocation, and if
/// it fails, a corresponding standard exception will be thrown.
/// It never throws an exception otherwise.
ZoneTable
();
ZoneTable
(
util
::
MemorySegment
&
mem_sgmt
);
/// The destructor.
///
/// An object of this class is always expected to be destroyed explicitly
/// by \c destroy(), so the constructor is hidden as private.
~
ZoneTable
();
//@}
public:
/// \brief Allocate and construct \c ZoneTable
///
/// This static method allocates memory for a new \c ZoneTable object
/// from the given memory segment, constructs the object, and returns
/// a pointer to it.
///
/// \throw std::bad_alloc Memory allocation fails.
///
/// \param mem_sgmt A \c MemorySegment from which memory for the new
/// \c ZoneTable is allocated.
static
ZoneTable
*
create
(
util
::
MemorySegment
&
mem_sgmt
);
/// \brief Destruct and deallocate \c ZoneTable
///
/// \throw none
///
/// \param mem_sgmt The \c MemorySegment that allocated memory for
/// \c ztable.
/// \param ztable A non NULL pointer to a valid \c ZoneTable object
/// that was originally created by the \c create() method (the behavior
/// is undefined if this condition isn't met).
static
void
destroy
(
util
::
MemorySegment
&
mem_sgmt
,
ZoneTable
*
ztable
);
/// Add a \c Zone to the \c ZoneTable.
///
/// \c Zone must not be associated with a NULL pointer; otherwise
...
...
@@ -83,7 +114,7 @@ public:
/// added to the zone table.
/// \return \c result::EXIST The zone table already contains
/// zone of the same origin.
result
::
Result
addZone
(
ZoneFinderPtr
zone
);
result
::
Result
addZone
(
util
::
MemorySegment
&
mem_sgmt
,
ZoneFinderPtr
zone
);
/// Remove a \c Zone of the given origin name from the \c ZoneTable.
///
...
...
src/lib/dns/labelsequence.cc
View file @
c6de8f18
...
...
@@ -23,62 +23,75 @@
namespace
isc
{
namespace
dns
{
LabelSequence
::
LabelSequence
(
const
uint8_t
*
data
,
const
uint8_t
*
offsets
,
size_t
offsets_size
)
:
data_
(
data
),
offsets_
(
offsets
),
offsets_size_
(
offsets_size
),
first_label_
(
0
),
last_label_
(
offsets_size_
)
{
if
(
data
==
NULL
||
offsets
==
NULL
)
{
isc_throw
(
BadValue
,
"Null pointer passed to LabelSequence constructor"
);
}
if
(
offsets_size
==
0
)
{
isc_throw
(
BadValue
,
"Zero offsets to LabelSequence constructor"
);
LabelSequence
::
LabelSequence
(
const
void
*
buf
)
{
if
(
buf
==
NULL
)
{
isc_throw
(
BadValue
,
"Null pointer passed to LabelSequence constructor"
);
}
if
(
offsets_size
>
Name
::
MAX_LABELS
)
{
isc_throw
(
BadValue
,
"MAX_LABELS exceeded"
);
const
uint8_t
*
bp
=
reinterpret_cast
<
const
uint8_t
*>
(
buf
);
first_label_
=
0
;
const
uint8_t
offsets_len
=
*
bp
++
;
if
(
offsets_len
==
0
||
offsets_len
>
Name
::
MAX_LABELS
)
{
isc_throw
(
BadValue
,
"Bad offsets len in serialized LabelSequence data: "
<<
static_cast
<
unsigned
int
>
(
offsets_len
));
}
for
(
size_t
cur_offset
=
0
;
cur_offset
<
offsets_size
;
++
cur_offset
)
{
if
(
offsets
[
cur_offset
]
>
Name
::
MAX_LABELLEN
)
{
isc_throw
(
BadValue
,
"MAX_LABEL_LEN exceeded"
);
}
if
(
cur_offset
>
0
&&
offsets
[
cur_offset
]
<=
offsets
[
cur_offset
-
1
])
{
isc_throw
(
BadValue
,
"Offset smaller than previous offset"
);
last_label_
=
offsets_len
-
1
;
offsets_
=
bp
;
data_
=
bp
+
offsets_len
;
// Check the integrity on the offsets and the name data
const
uint8_t
*
dp
=
data_
;
for
(
size_t
cur_offset
=
0
;
cur_offset
<
offsets_len
;
++
cur_offset
)
{
if
(
offsets_
[
cur_offset
]
>
Name
::
MAX_LABELLEN
||