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
Sebastian Schrader
Kea
Commits
40f6dd2b
Commit
40f6dd2b
authored
Nov 18, 2011
by
Michal 'vorner' Vaner
Browse files
Merge branch 'master' of
git+ssh://git.bind10.isc.org/var/bind10/git/bind10
parents
b54f1b46
84fa061a
Changes
19
Expand all
Hide whitespace changes
Inline
Side-by-side
ChangeLog
View file @
40f6dd2b
321. [func]* jinmei
b10-xfrin now installs IXFR differences into the underlying data
source (if it supports journaling) so that the stored differences
can be used for subsequent IXFR-out transactions.
Note: this is a backward incompatibility change for older sqlite3
database files. They need to be upgraded to have a "diffs" table.
(Trac #1376, git 1219d81b49e51adece77dc57b5902fa1c6be1407)
320. [func]* vorner
The --brittle switch was removed from the bind10 executable.
It didn't
work after
the #213 change and the same effect can be accomplished by
declaring all components as core.
The --brittle switch was removed from the bind10 executable.
It didn't
work after
change #316 (Trac #213) and the same
effect can be accomplished by
declaring all components as core.
(Trac #1340, git f9224368908dd7ba16875b0d36329cf1161193f0)
319. [func] naokikambe
...
...
@@ -15,12 +23,12 @@
only for the XML documents but also is for the XSD and XSL documents.
(Trac #917, git b34bf286c064d44746ec0b79e38a6177d01e6956)
318. [func]
stephen
318. [func]
stephen
Add C++ API for accessing zone difference information in database-based
data sources.
(Trac #1330, git 78770f52c7f1e7268d99e8bfa8c61e889813bb33)
317. [func]
vorner
317. [func]
vorner
datasrc: the getUpdater method of DataSourceClient supports an optional
'journaling' parameter to indicate the generated updater to store diffs.
The database based derived class implements this extension.
...
...
src/bin/xfrin/tests/testdata/example.com.sqlite3
View file @
40f6dd2b
No preview for this file type
src/bin/xfrin/tests/xfrin_test.py
View file @
40f6dd2b
...
...
@@ -14,8 +14,10 @@
# WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
import
unittest
import
re
import
shutil
import
socket
import
sqlite3
import
sys
import
io
from
isc.testutils.tsigctx_mock
import
MockTSIGContext
...
...
@@ -170,7 +172,8 @@ class MockDataSourceClient():
return
(
ZoneFinder
.
SUCCESS
,
dup_soa_rrset
)
raise
ValueError
(
'Unexpected input to mock finder: bug in test case?'
)
def
get_updater
(
self
,
zone_name
,
replace
):
def
get_updater
(
self
,
zone_name
,
replace
,
journaling
=
False
):
self
.
_journaling_enabled
=
journaling
return
self
def
add_rrset
(
self
,
rrset
):
...
...
@@ -1132,6 +1135,7 @@ class TestAXFR(TestXfrinConnection):
def
test_do_xfrin
(
self
):
self
.
conn
.
response_generator
=
self
.
_create_normal_response_data
self
.
assertEqual
(
self
.
conn
.
do_xfrin
(
False
),
XFRIN_OK
)
self
.
assertFalse
(
self
.
conn
.
_datasrc_client
.
_journaling_enabled
)
def
test_do_xfrin_with_tsig
(
self
):
# use TSIG with a mock context. we fake all verify results to
...
...
@@ -1283,6 +1287,7 @@ class TestIXFRResponse(TestXfrinConnection):
answers
=
[
soa_rrset
,
begin_soa_rrset
,
soa_rrset
,
soa_rrset
])
self
.
conn
.
_handle_xfrin_responses
()
self
.
assertEqual
(
type
(
XfrinIXFREnd
()),
type
(
self
.
conn
.
get_xfrstate
()))
self
.
assertTrue
(
self
.
conn
.
_datasrc_client
.
_journaling_enabled
)
self
.
assertEqual
([],
self
.
conn
.
_datasrc_client
.
diffs
)
check_diffs
(
self
.
assertEqual
,
[[(
'delete'
,
begin_soa_rrset
),
(
'add'
,
soa_rrset
)]],
...
...
@@ -1387,6 +1392,8 @@ class TestIXFRResponse(TestXfrinConnection):
answers
=
[
soa_rrset
,
ns_rr
,
a_rr
,
soa_rrset
])
self
.
conn
.
_handle_xfrin_responses
()
self
.
assertEqual
(
type
(
XfrinAXFREnd
()),
type
(
self
.
conn
.
get_xfrstate
()))
# In the case AXFR-style IXFR, journaling must have been disabled.
self
.
assertFalse
(
self
.
conn
.
_datasrc_client
.
_journaling_enabled
)
self
.
assertEqual
([],
self
.
conn
.
_datasrc_client
.
diffs
)
# The SOA should be added exactly once, and in our implementation
# it should be added at the end of the sequence.
...
...
@@ -1540,6 +1547,19 @@ class TestXFRSessionWithSQLite3(TestXfrinConnection):
self
.
assertEqual
(
XFRIN_OK
,
self
.
conn
.
do_xfrin
(
False
,
RRType
.
IXFR
()))
self
.
assertEqual
(
1234
,
self
.
get_zone_serial
())
# Also confirm the corresponding diffs are stored in the diffs table
conn
=
sqlite3
.
connect
(
self
.
sqlite3db_obj
)
cur
=
conn
.
cursor
()
cur
.
execute
(
'SELECT name, rrtype, ttl, rdata FROM diffs ORDER BY id'
)
soa_rdata_base
=
'master.example.com. admin.example.com. '
+
\
'SERIAL 3600 1800 2419200 7200'
self
.
assertEqual
(
cur
.
fetchall
(),
[(
TEST_ZONE_NAME_STR
,
'SOA'
,
3600
,
re
.
sub
(
'SERIAL'
,
str
(
1230
),
soa_rdata_base
)),
(
TEST_ZONE_NAME_STR
,
'SOA'
,
3600
,
re
.
sub
(
'SERIAL'
,
str
(
1234
),
soa_rdata_base
))])
conn
.
close
()
def
test_do_ixfrin_sqlite3_fail
(
self
):
'''Similar to the previous test, but xfrin fails due to error.
...
...
src/bin/xfrin/xfrin.py.in
View file @
40f6dd2b
...
...
@@ -367,7 +367,10 @@ class XfrinIXFRDeleteSOA(XfrinState):
' RR is given in IXFRDeleteSOA state')
# This is the beginning state of one difference sequence (changes
# for one SOA update). We need to create a new Diff object now.
conn._diff = Diff(conn._datasrc_client, conn._zone_name)
# Note also that we (unconditionally) enable journaling here. The
# Diff constructor may internally disable it, however, if the
# underlying data source doesn't support journaling.
conn._diff = Diff(conn._datasrc_client, conn._zone_name, False, True)
conn._diff.delete_data(rr)
self.set_xfrstate(conn, XfrinIXFRDelete())
return True
...
...
src/lib/datasrc/client.h
View file @
40f6dd2b
...
...
@@ -15,6 +15,8 @@
#ifndef __DATA_SOURCE_CLIENT_H
#define __DATA_SOURCE_CLIENT_H 1
#include
<utility>
#include
<boost/noncopyable.hpp>
#include
<boost/shared_ptr.hpp>
...
...
@@ -311,6 +313,55 @@ public:
virtual
ZoneUpdaterPtr
getUpdater
(
const
isc
::
dns
::
Name
&
name
,
bool
replace
,
bool
journaling
=
false
)
const
=
0
;
/// Return a journal reader to retrieve differences of a zone.
///
/// A derived version of this method creates a concrete
/// \c ZoneJournalReader object specific to the underlying data source
/// for the specified name of zone and differences between the versions
/// specified by the beginning and ending serials of the corresponding
/// SOA RRs.
/// The RR class of the zone is the one that the client is expected to
/// handle (see the detailed description of this class).
///
/// Note that the SOA serials are compared by the semantics of the serial
/// number arithmetic. So, for example, \c begin_serial can be larger than
/// \c end_serial as bare unsigned integers. The underlying data source
/// implementation is assumed to keep track of sufficient history to
/// identify (if exist) the corresponding difference between the specified
/// versions.
///
/// This method returns the result as a pair of a result code and
/// a pointer to a \c ZoneJournalReader object. On success, the result
/// code is \c SUCCESS and the pointer must be non NULL; otherwise
/// the result code is something other than \c SUCCESS and the pinter
/// must be NULL.
///
/// If the specified zone is not found in the data source, the result
/// code is \c NO_SUCH_ZONE.
/// Otherwise, if specified range of difference for the zone is not found
/// in the data source, the result code is \c NO_SUCH_VERSION.
///
/// Handling differences is an optional feature of data source.
/// If the underlying data source does not support difference handling,
/// this method for that type of data source can throw an exception of
/// class \c NotImplemented.
///
/// \exception NotImplemented The data source does not support differences.
/// \exception DataSourceError Other operational errors at the data source
/// level.
///
/// \param zone The name of the zone for which the difference should be
/// retrieved.
/// \param begin_serial The SOA serial of the beginning version of the
/// differences.
/// \param end_serial The SOA serial of the ending version of the
/// differences.
///
/// \return A pair of result code and a pointer to \c ZoneJournalReader.
virtual
std
::
pair
<
ZoneJournalReader
::
Result
,
ZoneJournalReaderPtr
>
getJournalReader
(
const
isc
::
dns
::
Name
&
zone
,
uint32_t
begin_serial
,
uint32_t
end_serial
)
const
=
0
;
};
}
}
...
...
src/lib/datasrc/database.cc
View file @
40f6dd2b
...
...
@@ -13,6 +13,7 @@
// PERFORMANCE OF THIS SOFTWARE.
#include
<string>
#include
<utility>
#include
<vector>
#include
<datasrc/database.h>
...
...
@@ -1069,5 +1070,105 @@ DatabaseClient::getUpdater(const isc::dns::Name& name, bool replace,
return
(
ZoneUpdaterPtr
(
new
DatabaseUpdater
(
update_accessor
,
zone
.
second
,
name
,
rrclass_
,
journaling
)));
}
//
// Zone journal reader using some database system as the underlying data
// source.
//
class
DatabaseJournalReader
:
public
ZoneJournalReader
{
private:
// A shortcut typedef to keep the code concise.
typedef
DatabaseAccessor
Accessor
;
public:
DatabaseJournalReader
(
shared_ptr
<
Accessor
>
accessor
,
const
Name
&
zone
,
int
zone_id
,
const
RRClass
&
rrclass
,
uint32_t
begin
,
uint32_t
end
)
:
accessor_
(
accessor
),
zone_
(
zone
),
rrclass_
(
rrclass
),
begin_
(
begin
),
end_
(
end
),
finished_
(
false
)
{
context_
=
accessor_
->
getDiffs
(
zone_id
,
begin
,
end
);
}
virtual
~
DatabaseJournalReader
()
{}
virtual
ConstRRsetPtr
getNextDiff
()
{
if
(
finished_
)
{
isc_throw
(
InvalidOperation
,
"Diff read attempt past the end of sequence on "
<<
accessor_
->
getDBName
());
}
string
data
[
Accessor
::
COLUMN_COUNT
];
if
(
!
context_
->
getNext
(
data
))
{
finished_
=
true
;
LOG_DEBUG
(
logger
,
DBG_TRACE_BASIC
,
DATASRC_DATABASE_JOURNALREADER_END
).
arg
(
zone_
).
arg
(
rrclass_
).
arg
(
accessor_
->
getDBName
()).
arg
(
begin_
).
arg
(
end_
);
return
(
ConstRRsetPtr
());
}
try
{
RRsetPtr
rrset
(
new
RRset
(
Name
(
data
[
Accessor
::
NAME_COLUMN
]),
rrclass_
,
RRType
(
data
[
Accessor
::
TYPE_COLUMN
]),
RRTTL
(
data
[
Accessor
::
TTL_COLUMN
])));
rrset
->
addRdata
(
rdata
::
createRdata
(
rrset
->
getType
(),
rrclass_
,
data
[
Accessor
::
RDATA_COLUMN
]));
LOG_DEBUG
(
logger
,
DBG_TRACE_DETAILED
,
DATASRC_DATABASE_JOURNALREADER_NEXT
).
arg
(
rrset
->
getName
()).
arg
(
rrset
->
getType
()).
arg
(
zone_
).
arg
(
rrclass_
).
arg
(
accessor_
->
getDBName
());
return
(
rrset
);
}
catch
(
const
Exception
&
ex
)
{
LOG_ERROR
(
logger
,
DATASRC_DATABASE_JOURNALREADR_BADDATA
).
arg
(
zone_
).
arg
(
rrclass_
).
arg
(
accessor_
->
getDBName
()).
arg
(
begin_
).
arg
(
end_
).
arg
(
ex
.
what
());
isc_throw
(
DataSourceError
,
"Failed to create RRset from diff on "
<<
accessor_
->
getDBName
());
}
}
private:
shared_ptr
<
Accessor
>
accessor_
;
const
Name
zone_
;
const
RRClass
rrclass_
;
Accessor
::
IteratorContextPtr
context_
;
const
uint32_t
begin_
;
const
uint32_t
end_
;
bool
finished_
;
};
// The JournalReader factory
pair
<
ZoneJournalReader
::
Result
,
ZoneJournalReaderPtr
>
DatabaseClient
::
getJournalReader
(
const
isc
::
dns
::
Name
&
zone
,
uint32_t
begin_serial
,
uint32_t
end_serial
)
const
{
shared_ptr
<
DatabaseAccessor
>
jnl_accessor
(
accessor_
->
clone
());
const
pair
<
bool
,
int
>
zoneinfo
(
jnl_accessor
->
getZone
(
zone
.
toText
()));
if
(
!
zoneinfo
.
first
)
{
return
(
pair
<
ZoneJournalReader
::
Result
,
ZoneJournalReaderPtr
>
(
ZoneJournalReader
::
NO_SUCH_ZONE
,
ZoneJournalReaderPtr
()));
}
try
{
const
pair
<
ZoneJournalReader
::
Result
,
ZoneJournalReaderPtr
>
ret
(
ZoneJournalReader
::
SUCCESS
,
ZoneJournalReaderPtr
(
new
DatabaseJournalReader
(
jnl_accessor
,
zone
,
zoneinfo
.
second
,
rrclass_
,
begin_serial
,
end_serial
)));
LOG_DEBUG
(
logger
,
DBG_TRACE_BASIC
,
DATASRC_DATABASE_JOURNALREADER_START
).
arg
(
zone
).
arg
(
rrclass_
).
arg
(
jnl_accessor
->
getDBName
()).
arg
(
begin_serial
).
arg
(
end_serial
);
return
(
ret
);
}
catch
(
const
NoSuchSerial
&
)
{
return
(
pair
<
ZoneJournalReader
::
Result
,
ZoneJournalReaderPtr
>
(
ZoneJournalReader
::
NO_SUCH_VERSION
,
ZoneJournalReaderPtr
()));
}
}
}
}
src/lib/datasrc/database.h
View file @
40f6dd2b
...
...
@@ -23,6 +23,8 @@
#include
<dns/rrclass.h>
#include
<dns/rrset.h>
#include
<datasrc/data_source.h>
#include
<datasrc/client.h>
#include
<datasrc/client.h>
#include
<dns/name.h>
...
...
@@ -544,12 +546,10 @@ public:
/// is not for the SOA RR; it passes TTL for a diff that deletes an RR
/// while in \c deleteRecordInZone() it's omitted. This is because
/// the stored diffs are expected to be retrieved in the form that
/// \c get
Record
Diffs() is expected to meet. This means if the caller
/// \c getDiffs() is expected to meet. This means if the caller
/// wants to use this method with other update operations, it must
/// ensure the additional information is ready when this method is called.
///
/// \note \c getRecordDiffs() is not yet implemented.
///
/// The caller of this method must ensure that the added diffs via
/// this method in a single transaction form an IXFR-style difference
/// sequences: Each difference sequence is a sequence of RRs:
...
...
@@ -562,7 +562,7 @@ public:
/// an SOA RR, \c serial must be identical to the serial of that SOA).
/// The underlying derived class implementation may or may not check
/// this condition, but if the caller doesn't meet the condition
/// a subsequent call to \c get
Record
Diffs() will not work as expected.
/// a subsequent call to \c getDiffs() will not work as expected.
///
/// Any call to this method must be in a transaction, and, for now,
/// it must be a transaction triggered by \c startUpdateZone() (that is,
...
...
@@ -932,6 +932,15 @@ public:
bool
replace
,
bool
journaling
=
false
)
const
;
/// This implementation internally clones the accessor from the one
/// used in the client for retrieving diffs and iterating over them.
/// The returned reader object will be able to work separately from
/// the original client.
virtual
std
::
pair
<
ZoneJournalReader
::
Result
,
ZoneJournalReaderPtr
>
getJournalReader
(
const
isc
::
dns
::
Name
&
zone
,
uint32_t
begin_serial
,
uint32_t
end_serial
)
const
;
private:
/// \brief The RR class that this client handles.
const
isc
::
dns
::
RRClass
rrclass_
;
...
...
src/lib/datasrc/datasrc_messages.mes
View file @
40f6dd2b
...
...
@@ -630,3 +630,31 @@ database module are shown in the log message.
Debug information. A set of updates to a zone has been successfully
committed to the corresponding database backend. The zone name,
its class and the database name are printed.
% DATASRC_DATABASE_JOURNALREADER_START %1/%2 on %3 from %4 to %5
This is a debug message indicating that the program starts reading
a zone's difference sequences from a database-based data source. The
zone's name and class, database name, and the start and end serials
are shown in the message.
% DATASRC_DATABASE_JOURNALREADER_NEXT %1/%2 in %3/%4 on %5
This is a debug message indicating that the program retrieves one
difference in difference sequences of a zone and successfully converts
it to an RRset. The zone's name and class, database name, and the
name and RR type of the retrieved diff are shown in the message.
% DATASRC_DATABASE_JOURNALREADER_END %1/%2 on %3 from %4 to %5
This is a debug message indicating that the program (successfully)
reaches the end of sequences of a zone's differences. The zone's name
and class, database name, and the start and end serials are shown in
the message.
% DATASRC_DATABASE_JOURNALREADR_BADDATA failed to convert a diff to RRset in %1/%2 on %3 between %4 and %5: %6
This is an error message indicating that a zone's diff is broken and
the data source library failed to convert it to a valid RRset. The
most likely cause of this is that someone has manually modified the
zone's diff in the database and inserted invalid data as a result.
The zone's name and class, database name, and the start and end
serials, and an additional detail of the error are shown in the
message. The administrator should examine the diff in the database
to find any invalid data and fix it.
src/lib/datasrc/memory_datasrc.cc
View file @
40f6dd2b
...
...
@@ -850,6 +850,13 @@ InMemoryClient::getUpdater(const isc::dns::Name&, bool, bool) const {
isc_throw
(
isc
::
NotImplemented
,
"Update attempt on in memory data source"
);
}
pair
<
ZoneJournalReader
::
Result
,
ZoneJournalReaderPtr
>
InMemoryClient
::
getJournalReader
(
const
isc
::
dns
::
Name
&
,
uint32_t
,
uint32_t
)
const
{
isc_throw
(
isc
::
NotImplemented
,
"Journaling isn't supported for "
"in memory data source"
);
}
namespace
{
// convencience function to add an error message to a list of those
...
...
src/lib/datasrc/memory_datasrc.h
View file @
40f6dd2b
...
...
@@ -287,6 +287,10 @@ public:
bool
replace
,
bool
journaling
=
false
)
const
;
virtual
std
::
pair
<
ZoneJournalReader
::
Result
,
ZoneJournalReaderPtr
>
getJournalReader
(
const
isc
::
dns
::
Name
&
zone
,
uint32_t
begin_serial
,
uint32_t
end_serial
)
const
;
private:
// TODO: Do we still need the PImpl if nobody should manipulate this class
// directly any more (it should be handled through DataSourceClient)?
...
...
src/lib/datasrc/sqlite3_accessor.h
View file @
40f6dd2b
...
...
@@ -71,7 +71,6 @@ public:
DataSourceError
(
file
,
line
,
what
)
{}
};
struct
SQLite3Parameters
;
/**
...
...
src/lib/datasrc/tests/client_unittest.cc
View file @
40f6dd2b
...
...
@@ -12,6 +12,8 @@
// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
// PERFORMANCE OF THIS SOFTWARE.
#include
<utility>
#include
<datasrc/client.h>
#include
<dns/name.h>
...
...
@@ -37,6 +39,11 @@ public:
{
return
(
ZoneUpdaterPtr
());
}
virtual
std
::
pair
<
ZoneJournalReader
::
Result
,
ZoneJournalReaderPtr
>
getJournalReader
(
const
isc
::
dns
::
Name
&
,
uint32_t
,
uint32_t
)
const
{
isc_throw
(
isc
::
NotImplemented
,
"Journaling isn't supported "
"in Nop data source"
);
}
};
class
ClientTest
:
public
::
testing
::
Test
{
...
...
src/lib/datasrc/tests/database_unittest.cc
View file @
40f6dd2b
This diff is collapsed.
Click to expand it.
src/lib/datasrc/tests/testdata/Makefile.am
View file @
40f6dd2b
CLEANFILES
=
*
.copied
BUILT_SOURCES
=
rwtest.sqlite3.copied
# We use install-sh with the -m option to make sure it's writable
rwtest.sqlite3.copied
:
$(srcdir)/rwtest.sqlite3
$(top_srcdir)
/install-sh
-m
644
$(srcdir)
/rwtest.sqlite3
$@
src/lib/datasrc/zone.h
View file @
40f6dd2b
...
...
@@ -560,6 +560,98 @@ public:
/// \brief A pointer-like type pointing to a \c ZoneUpdater object.
typedef
boost
::
shared_ptr
<
ZoneUpdater
>
ZoneUpdaterPtr
;
/// The base class for retrieving differences between two versions of a zone.
///
/// On construction, each derived class object will internally set up
/// retrieving sequences of differences between two specific version of
/// a specific zone managed in a particular data source. So the constructor
/// of a derived class would normally take parameters to identify the zone
/// and the two versions for which the differences should be retrieved.
/// See \c DataSourceClient::getJournalReader for more concrete details
/// used in this API.
///
/// Once constructed, an object of this class will act like an iterator
/// over the sequences. Every time the \c getNextDiff() method is called
/// it returns one element of the differences in the form of an \c RRset
/// until it reaches the end of the entire sequences.
class
ZoneJournalReader
{
public:
/// Result codes used by a factory method for \c ZoneJournalReader
enum
Result
{
SUCCESS
,
///< A \c ZoneJournalReader object successfully created
NO_SUCH_ZONE
,
///< Specified zone does not exist in the data source
NO_SUCH_VERSION
///< Specified versions do not exist in the diff storage
};
protected:
/// The default constructor.
///
/// This is intentionally defined as protected to ensure that this base
/// class is never instantiated directly.
ZoneJournalReader
()
{}
public:
/// The destructor
virtual
~
ZoneJournalReader
()
{}
/// Return the next difference RR of difference sequences.
///
/// In this API, the difference between two versions of a zone is
/// conceptually represented as IXFR-style difference sequences:
/// Each difference sequence is a sequence of RRs: an older version of
/// SOA (to be deleted), zero or more other deleted RRs, the
/// post-transaction SOA (to be added), and zero or more other
/// added RRs. (Note, however, that the underlying data source
/// implementation may or may not represent the difference in
/// straightforward realization of this concept. The mapping between
/// the conceptual difference and the actual implementation is hidden
/// in each derived class).
///
/// This method provides an application with a higher level interface
/// to retrieve the difference along with the conceptual model: the
/// \c ZoneJournalReader object iterates over the entire sequences
/// from the beginning SOA (which is to be deleted) to one of the
/// added RR of with the ending SOA, and each call to this method returns
/// one RR in the form of an \c RRset that contains exactly one RDATA
/// in the order of the sequences.
///
/// Note that the ordering of the sequences specifies the semantics of
/// each difference: add or delete. For example, the first RR is to
/// be deleted, and the last RR is to be added. So the return value
/// of this method does not explicitly indicate whether the RR is to be
/// added or deleted.
///
/// This method ensures the returned \c RRset represents an RR, that is,
/// it contains exactly one RDATA. However, it does not necessarily
/// ensure that the resulting sequences are in the form of IXFR-style.
/// For example, the first RR is supposed to be an SOA, and it should
/// normally be the case, but this interface does not necessarily require
/// the derived class implementation ensure this. Normally the
/// differences are expected to be stored using this API (via a
/// \c ZoneUpdater object), and as long as that is the case and the
/// underlying implementation follows the requirement of the API, the
/// result of this method should be a valid IXFR-style sequences.
/// So this API does not mandate the almost redundant check as part of
/// the interface. If the application needs to make it sure 100%, it
/// must check the resulting sequence itself.
///
/// Once the object reaches the end of the sequences, this method returns
/// \c Null. Any subsequent call will result in an exception of
/// class \c InvalidOperation.
///
/// \exception InvalidOperation The method is called beyond the end of
/// the difference sequences.
/// \exception DataSourceError Underlying data is broken and the RR
/// cannot be created or other low level data source error.
///
/// \return An \c RRset that contains one RDATA corresponding to the
/// next difference in the sequences.
virtual
isc
::
dns
::
ConstRRsetPtr
getNextDiff
()
=
0
;
};
/// \brief A pointer-like type pointing to a \c ZoneUpdater object.
typedef
boost
::
shared_ptr
<
ZoneJournalReader
>
ZoneJournalReaderPtr
;
}
// end of datasrc
}
// end of isc
...
...
src/lib/exceptions/exceptions.h
View file @
40f6dd2b
...
...
@@ -126,6 +126,17 @@ public:
isc
::
Exception
(
file
,
line
,
what
)
{}
};
/// \brief A generic exception that is thrown if a function is called
/// in a prohibited way.
///
/// For example, this can happen if a class method is called when the object's
/// state does not allow that particular method.
class
InvalidOperation
:
public
Exception
{
public:
InvalidOperation
(
const
char
*
file
,
size_t
line
,
const
char
*
what
)
:
isc
::
Exception
(
file
,
line
,
what
)
{}
};
///
/// \brief A generic exception that is thrown when an unexpected
/// error condition occurs.
...
...
src/lib/python/isc/xfrin/diff.py
View file @
40f6dd2b
...
...
@@ -59,7 +59,7 @@ class Diff:
the changes to underlying data source right away, but keeps them for
a while.
"""
def
__init__
(
self
,
ds_client
,
zone
,
replace
=
False
):
def
__init__
(
self
,
ds_client
,
zone
,
replace
=
False
,
journaling
=
False
):
"""
Initializes the diff to a ready state. It checks the zone exists
in the datasource and if not, NoSuchZone is raised. This also creates
...
...
@@ -67,13 +67,25 @@ class Diff:
The ds_client is the datasource client containing the zone. Zone is
isc.dns.Name object representing the name of the zone (its apex).
If replace is
t
rue, the content of the whole zone is wiped out before
If replace is
T
rue, the content of the whole zone is wiped out before
applying the diff.
If journaling is True, the history of subsequent updates will be
recorded as well as the updates themselves as long as the underlying
data source support the journaling. If the data source allows
incoming updates but does not support journaling, the Diff object
will still continue applying the diffs with disabling journaling.
You can also expect isc.datasrc.Error or isc.datasrc.NotImplemented
exceptions.
"""
self
.
__updater
=
ds_client
.
get_updater
(
zone
,
replace
)
try
:
self
.
__updater
=
ds_client
.
get_updater
(
zone
,
replace
,
journaling
)
except
isc
.
datasrc
.
NotImplemented
as
ex
:
if
not
journaling
:
raise
ex
self
.
__updater
=
ds_client
.
get_updater
(
zone
,
replace
,
False
)
logger
.
info
(
LIBXFRIN_NO_JOURNAL
,
zone
,
ds_client
)
if
self
.
__updater
is
None
:
# The no such zone case
raise
NoSuchZone
(
"Zone "
+
str
(
zone
)
+
...
...
src/lib/python/isc/xfrin/libxfrin_messages.mes
View file @
40f6dd2b
...
...
@@ -19,3 +19,13 @@
The xfrin module received an update containing multiple rdata changes for the
same RRset. But the TTLs of these don't match each other. As we combine them
together, the later one get's overwritten to the earlier one in the sequence.
% LIBXFRIN_NO_JOURNAL disabled journaling for updates to %1 on %2
An attempt was made to create a Diff object with journaling enabled, but
the underlying data source didn't support journaling (while still allowing
updates) and so the created object has it disabled. At a higher level this
means that the updates will be applied to the zone but subsequent IXFR requests
will result in a full zone transfer (i.e., an AXFR-style IXFR). Unless the
overhead of the full transfer is an issue this message can be ignored;
otherwise you may want to check why the journaling wasn't allowed on the
data source and either fix the issue or use a different type of data source.
src/lib/python/isc/xfrin/tests/diff_tests.py
View file @
40f6dd2b
...
...
@@ -15,6 +15,7 @@
import
isc.log
import
unittest
import
isc.datasrc
from
isc.dns
import
Name
,
RRset
,
RRClass
,
RRType
,
RRTTL
,
Rdata
from
isc.xfrin.diff
import
Diff
,
NoSuchZone
...
...