Commit 862b0e38 authored by Xie Jiagui's avatar Xie Jiagui
Browse files

Merge branch 'master' into trac1308

parents 11885ff9 cf5e4481
337. [func] tomek
libdhcp++: Support for DHCPv4 option that can store a single
address or a list of IPv4 addresses added. Support for END option
added.
(Trac #1350, git cc20ff993da1ddb1c6e8a98370438b45a2be9e0a)
336. [func] jelte
libdns++ (and its python wrapper) now includes a class Serial, for
SOA SERIAL comparison and addition. Operations on instances of this
class follow the specification from RFC 1982.
Rdata::SOA::getSerial() now returns values of this type (and not
uint32_t).
(Trac #1278, git 2ae72d76c74f61a67590722c73ebbf631388acbd)
335. [bug]* jelte
The DataSourceClientContainer class that dynamically loads
datasource backend libraries no longer provides just a .so file name
to its call to dlopen(), but passes it an absolute path. This means
that it is no longer an system implementation detail that depends on
[DY]LD_LIBRARY_PATH which file is chosen, should there be multiple
options (for instance, when test-running a new build while a
different version is installed).
These loadable libraries are also no longer installed in the default
library path, but in a subdirectory of the libexec directory of the
target ($prefix/libexec/[version]/backends).
This also removes the need to handle b10-xfin and b10-xfrout as
'special' hardcoded components, and they are now started as regular
components as dictated by the configuration of the boss process.
(Trac #1292, git 83ce13c2d85068a1bec015361e4ef8c35590a5d0)
334. [bug] jinmei
b10-xfrout could potentially create an overflow response message
(exceeding the 64KB max) or could create unnecessarily small
messages. The former was actually unlikely to happen due to the
effect of name compression, and the latter was marginal and at least
shouldn't cause an interoperability problem, but these were still
potential problems and were fixed.
(Trac #1389, git 3fdce88046bdad392bd89ea656ec4ac3c858ca2f)
333. [bug] dvv
Solaris needs "-z now" to force non-lazy binding and prevent g++ static
initialization code from deadlocking.
(Trac #1439, git c789138250b33b6b08262425a08a2a0469d90433)
332. [bug] vorner
C++ exceptions in the isc.dns.Rdata wrapper are now converted
to python ones instead of just aborting the interpretter.
(Trac #1407, git 5b64e839be2906b8950f5b1e42a3fadd72fca033)
bind10-devel-20111128 released on November 28, 2011
331. [bug] shane
......
......@@ -96,6 +96,8 @@ case "$host" in
# Solaris requires special definitions to get some standard libraries
# (e.g. getopt(3)) available with common used header files.
CPPFLAGS="$CPPFLAGS -D_XPG4_2 -D__EXTENSIONS__"
# "now" binding is necessary to prevent deadlocks in C++ static initialization code
LDFLAGS="$LDFLAGS -z now"
;;
*-apple-darwin*)
# libtool doesn't work perfectly with Darwin: libtool embeds the
......@@ -990,6 +992,7 @@ AC_OUTPUT([doc/version.ent
src/lib/python/bind10_config.py
src/lib/cc/session_config.h.pre
src/lib/cc/tests/session_unittests_config.h
src/lib/datasrc/datasrc_config.h.pre
src/lib/log/tests/console_test.sh
src/lib/log/tests/destination_test.sh
src/lib/log/tests/init_logger_test.sh
......
......@@ -574,33 +574,6 @@ class BoB:
# ... and start
return self.start_process("b10-resolver", resargs, self.c_channel_env)
def __ld_path_hack(self):
# XXX: a quick-hack workaround. xfrin/out will implicitly use
# dynamically loadable data source modules, which will be installed in
# $(libdir).
# On some OSes (including MacOS X and *BSDs) the main process (python)
# cannot find the modules unless they are located in a common shared
# object path or a path in the (DY)LD_LIBRARY_PATH. We should seek
# a cleaner solution, but for a short term workaround we specify the
# path here, unconditionally, and without even bothering which
# environment variable should be used.
#
# We reuse the ADD_LIBEXEC_PATH variable to see whether we need to
# do this, as the conditions that make this workaround needed are
# the same as for the libexec path addition
# TODO: Once #1292 is finished, remove this method and the special
# component, use it as normal component.
env = dict(self.c_channel_env)
if ADD_LIBEXEC_PATH:
cur_path = os.getenv('DYLD_LIBRARY_PATH')
cur_path = '' if cur_path is None else ':' + cur_path
env['DYLD_LIBRARY_PATH'] = "@@LIBDIR@@" + cur_path
cur_path = os.getenv('LD_LIBRARY_PATH')
cur_path = '' if cur_path is None else ':' + cur_path
env['LD_LIBRARY_PATH'] = "@@LIBDIR@@" + cur_path
return env
def start_cmdctl(self):
"""
Starts the command control process
......@@ -613,22 +586,6 @@ class BoB:
return self.start_process("b10-cmdctl", args, self.c_channel_env,
self.cmdctl_port)
def start_xfrin(self):
# Set up the command arguments.
args = ['b10-xfrin']
if self.verbose:
args += ['-v']
return self.start_process("b10-xfrin", args, self.__ld_path_hack())
def start_xfrout(self):
# Set up the command arguments.
args = ['b10-xfrout']
if self.verbose:
args += ['-v']
return self.start_process("b10-xfrout", args, self.__ld_path_hack())
def start_all_components(self):
"""
Starts up all the components. Any exception generated during the
......
......@@ -14,8 +14,8 @@
"priority": 5,
"kind": "dispensable"
},
"b10-xfrin": { "special": "xfrin", "kind": "dispensable" },
"b10-xfrout": { "special": "xfrout", "kind": "dispensable" },
"b10-xfrin": { "address": "Xfrin", "kind": "dispensable" },
"b10-xfrout": { "address": "Xfrout", "kind": "dispensable" },
"b10-zonemgr": { "address": "Zonemgr", "kind": "dispensable" },
"b10-stats": { "address": "Stats", "kind": "dispensable" },
"b10-stats-httpd": {
......
......@@ -268,7 +268,9 @@ class MockBob(BoB):
'b10-stats-httpd': self.start_stats_httpd,
'b10-cmdctl': self.start_cmdctl,
'b10-dhcp6': self.start_dhcp6,
'b10-dhcp4': self.start_dhcp4 }
'b10-dhcp4': self.start_dhcp4,
'b10-xfrin': self.start_xfrin,
'b10-xfrout': self.start_xfrout }
return procmap[name]()
def start_xfrout(self):
......@@ -463,8 +465,9 @@ class TestStartStopProcessesBob(unittest.TestCase):
if start_auth:
config['b10-auth'] = { 'kind': 'needed', 'special': 'auth' }
config['b10-xfrout'] = { 'kind': 'dispensable',
'special': 'xfrout' }
config['b10-xfrin'] = { 'kind': 'dispensable', 'special': 'xfrin' }
'address': 'Xfrout' }
config['b10-xfrin'] = { 'kind': 'dispensable',
'address': 'Xfrin' }
config['b10-zonemgr'] = { 'kind': 'dispensable',
'address': 'Zonemgr' }
if start_resolver:
......
......@@ -27,5 +27,6 @@ endif
PYTHONPATH=$(abs_top_builddir)/src/lib/dns/python/.libs:$(abs_top_builddir)/src/bin/xfrin:$(COMMON_PYTHON_PATH) \
TESTDATASRCDIR=$(abs_top_srcdir)/src/bin/xfrin/tests/testdata/ \
TESTDATAOBJDIR=$(abs_top_builddir)/src/bin/xfrin/tests/testdata/ \
B10_FROM_BUILD=$(abs_top_builddir) \
$(PYCOVERAGE_RUN) $(abs_srcdir)/$$pytest || exit ; \
done
......@@ -17,7 +17,6 @@ import unittest
import re
import shutil
import socket
import sqlite3
import sys
import io
from isc.testutils.tsigctx_mock import MockTSIGContext
......@@ -25,6 +24,13 @@ from xfrin import *
import xfrin
from isc.xfrin.diff import Diff
import isc.log
# If we use any python library that is basically a wrapper for
# a library we use as well (like sqlite3 in our datasources),
# we must make sure we import ours first; If we have special
# rpath or libtool rules to pick the correct version, python might
# choose the wrong one first, if those rules aren't hit first.
# This would result in missing symbols later.
import sqlite3
#
# Commonly used (mostly constant) test parameters
......
......@@ -67,10 +67,12 @@ class MySocket():
self.sendqueue = self.sendqueue[size:]
return result
def read_msg(self, parse_options=Message.PARSE_DEFAULT):
def read_msg(self, parse_options=Message.PARSE_DEFAULT, need_len=False):
sent_data = self.readsent()
get_msg = Message(Message.PARSE)
get_msg.from_wire(bytes(sent_data[2:]), parse_options)
if need_len:
return (get_msg, len(sent_data) - 2)
return get_msg
def clear_send(self):
......@@ -863,7 +865,150 @@ class TestXfroutSession(TestXfroutSessionBase):
self.assertEqual(len(expected_records), len(actual_records))
for (expected_rr, actual_rr) in zip(expected_records, actual_records):
self.assertTrue(expected_rr, actual_rr)
self.assertTrue(rrsets_equal(expected_rr, actual_rr))
def test_reply_xfrout_query_axfr_maxlen(self):
# The test RR(set) has the length of 65535 - 12 (size of hdr) bytes:
# owner name = 1 (root), fixed fields (type,class,TTL,RDLEN) = 10
# RDATA = 65512 (= 65535 - 12 - 1 - 10)
self.xfrsess._soa = self.soa_rrset
test_rr = create_generic(Name('.'), 65512)
self.xfrsess._iterator = [self.soa_rrset, test_rr]
self.xfrsess._reply_xfrout_query(self.getmsg(), self.sock)
# The first message should contain the beginning SOA, and only that RR
r = self.sock.read_msg()
self.assertEqual(1, r.get_rr_count(Message.SECTION_ANSWER))
self.assertTrue(rrsets_equal(self.soa_rrset,
r.get_section(Message.SECTION_ANSWER)[0]))
# The second message should contain the beginning SOA, and only that RR
# The wire format data should have the possible maximum size.
r, rlen = self.sock.read_msg(need_len=True)
self.assertEqual(65535, rlen)
self.assertEqual(1, r.get_rr_count(Message.SECTION_ANSWER))
self.assertTrue(rrsets_equal(test_rr,
r.get_section(Message.SECTION_ANSWER)[0]))
# The third message should contain the ending SOA, and only that RR
r = self.sock.read_msg()
self.assertEqual(1, r.get_rr_count(Message.SECTION_ANSWER))
self.assertTrue(rrsets_equal(self.soa_rrset,
r.get_section(Message.SECTION_ANSWER)[0]))
# there should be no more message
self.assertEqual(0, len(self.sock.sendqueue))
def maxlen_test_common_setup(self, tsig=False):
'''Common initialization for some of the tests below
For those tests we use '.' for all owner names and names in RDATA
to avoid having unexpected results due to compression. It returns
the created SOA for convenience.
If tsig is True, also setup TSIG (mock) context. In our test cases
the size of the TSIG RR is 81 bytes (key name = example.com,
algorithm = hmac-md5)
'''
soa = RRset(Name('.'), RRClass.IN(), RRType.SOA(), RRTTL(3600))
soa.add_rdata(Rdata(RRType.SOA(), RRClass.IN(), '. . 0 0 0 0 0'))
self.mdata = self.create_request_data(zone_name=Name('.'))
self.xfrsess._soa = soa
if tsig:
self.xfrsess._tsig_ctx = \
self.create_mock_tsig_ctx(TSIGError.NOERROR)
self.xfrsess._tsig_len = 81
return soa
def maxlen_test_common_checks(self, soa_rr, test_rr, expected_n_rr):
'''A set of common assertion checks for some tests below.
In all cases two AXFR response messages should have been created.
expected_n_rr is a list of two elements, each specifies the expected
number of answer RRs for each message: expected_n_rr[0] is the expected
number of the first answer RRs; expected_n_rr[1] is the expected number
of the second answer RRs. The message that contains two RRs should
have the maximum possible wire length (65535 bytes). And, in all
cases, the resulting RRs should be in the order of SOA, another RR,
SOA.
'''
# Check the first message
r, rlen = self.sock.read_msg(need_len=True)
if expected_n_rr[0] == 2:
self.assertEqual(65535, rlen)
self.assertEqual(expected_n_rr[0],
r.get_rr_count(Message.SECTION_ANSWER))
actual_rrs = r.get_section(Message.SECTION_ANSWER)[:]
# Check the second message
r, rlen = self.sock.read_msg(need_len=True)
if expected_n_rr[1] == 2:
self.assertEqual(65535, rlen)
self.assertEqual(expected_n_rr[1],
r.get_rr_count(Message.SECTION_ANSWER))
actual_rrs.extend(r.get_section(Message.SECTION_ANSWER))
for (expected_rr, actual_rr) in zip([soa_rr, test_rr, soa_rr],
actual_rrs):
self.assertTrue(rrsets_equal(expected_rr, actual_rr))
# there should be no more message
self.assertEqual(0, len(self.sock.sendqueue))
def test_reply_xfrout_query_axfr_maxlen_with_soa(self):
# Similar to the 'maxlen' test, but the first message should be
# able to contain both SOA and the large RR.
soa = self.maxlen_test_common_setup()
# The first message will contain the question (5 bytes), so the
# test RDATA should allow a room for that.
test_rr = create_generic(Name('.'), 65512 - 5 - get_rrset_len(soa))
self.xfrsess._iterator = [soa, test_rr]
self.xfrsess._reply_xfrout_query(self.getmsg(), self.sock)
self.maxlen_test_common_checks(soa, test_rr, [2, 1])
def test_reply_xfrout_query_axfr_maxlen_with_soa_with_tsig(self):
# Similar to the previous case, but with TSIG (whose size is 81 bytes).
soa = self.maxlen_test_common_setup(True)
test_rr = create_generic(Name('.'), 65512 - 5 - 81 -
get_rrset_len(soa))
self.xfrsess._iterator = [soa, test_rr]
self.xfrsess._reply_xfrout_query(self.getmsg(), self.sock)
self.maxlen_test_common_checks(soa, test_rr, [2, 1])
def test_reply_xfrout_query_axfr_maxlen_with_endsoa(self):
# Similar to the max w/ soa test, but the first message cannot contain
# both SOA and the long RR due to the question section. The second
# message should be able to contain both.
soa = self.maxlen_test_common_setup()
test_rr = create_generic(Name('.'), 65512 - get_rrset_len(soa))
self.xfrsess._iterator = [soa, test_rr]
self.xfrsess._reply_xfrout_query(self.getmsg(), self.sock)
self.maxlen_test_common_checks(soa, test_rr, [1, 2])
def test_reply_xfrout_query_axfr_maxlen_with_endsoa_with_tsig(self):
# Similar to the previous case, but with TSIG.
soa = self.maxlen_test_common_setup(True)
test_rr = create_generic(Name('.'), 65512 - 81 - get_rrset_len(soa))
self.xfrsess._iterator = [soa, test_rr]
self.xfrsess._reply_xfrout_query(self.getmsg(), self.sock)
self.maxlen_test_common_checks(soa, test_rr, [1, 2])
def test_reply_xfrout_query_axfr_toobigdata(self):
# Similar to the 'maxlen' test, but the RR doesn't even fit in a
# single message.
self.xfrsess._soa = self.soa_rrset
test_rr = create_generic(Name('.'), 65513) # 1 byte larger than 'max'
self.xfrsess._iterator = [self.soa_rrset, test_rr]
# the reply method should fail with exception
self.assertRaises(XfroutSessionError, self.xfrsess._reply_xfrout_query,
self.getmsg(), self.sock)
# The first message should still have been sent and contain the
# beginning SOA, and only that RR
r = self.sock.read_msg()
self.assertEqual(1, r.get_rr_count(Message.SECTION_ANSWER))
self.assertTrue(rrsets_equal(self.soa_rrset,
r.get_section(Message.SECTION_ANSWER)[0]))
# And there should have been no other messages sent
self.assertEqual(0, len(self.sock.sendqueue))
def test_reply_xfrout_query_ixfr_soa_only(self):
# Creating an IXFR response that contains only one RR, which is the
......@@ -875,7 +1020,8 @@ class TestXfroutSession(TestXfroutSessionBase):
reply_msg = self.sock.read_msg(Message.PRESERVE_ORDER)
answer = reply_msg.get_section(Message.SECTION_ANSWER)
self.assertEqual(1, len(answer))
self.assertTrue(create_soa(SOA_CURRENT_VERSION), answer[0])
self.assertTrue(rrsets_equal(create_soa(SOA_CURRENT_VERSION),
answer[0]))
class TestXfroutSessionWithSQLite3(TestXfroutSessionBase):
'''Tests for XFR-out sessions using an SQLite3 DB.
......@@ -899,14 +1045,23 @@ class TestXfroutSessionWithSQLite3(TestXfroutSessionBase):
# This zone contains two A RRs for the same name with different TTLs.
# These TTLs should be preseved in the AXFR stream.
actual_records = response.get_section(Message.SECTION_ANSWER)
expected_records = [create_soa(2011112001),
create_ns(self.ns_name),
create_a(Name(self.ns_name), '192.0.2.1', 3600),
create_a(Name(self.ns_name), '192.0.2.2', 7200),
create_soa(2011112001)]
self.assertEqual(len(expected_records), len(actual_records))
for (expected_rr, actual_rr) in zip(expected_records, actual_records):
self.assertTrue(expected_rr, actual_rr)
self.assertEqual(5, len(actual_records))
# The first and last RR should be the expected SOA
expected_soa = create_soa(2011112001)
self.assertTrue(rrsets_equal(expected_soa, actual_records[0]))
self.assertTrue(rrsets_equal(expected_soa, actual_records[-1]))
# The ordering of the intermediate RRs can differ depending on the
# internal details of the SQLite3 library, so we sort them by a simple
# rule sufficient for the purpose here, and then compare them.
expected_others = [create_ns(self.ns_name),
create_a(Name(self.ns_name), '192.0.2.1', 3600),
create_a(Name(self.ns_name), '192.0.2.2', 7200)]
keyfn = lambda x: (x.get_type(), x.get_ttl())
for (expected_rr, actual_rr) in zip(sorted(expected_others, key=keyfn),
sorted(actual_records[1:4],
key=keyfn)):
self.assertTrue(rrsets_equal(expected_rr, actual_rr))
def test_axfr_normal_session(self):
XfroutSession._handle(self.xfrsess)
......@@ -945,7 +1100,7 @@ class TestXfroutSessionWithSQLite3(TestXfroutSessionBase):
create_soa(2011112001)]
self.assertEqual(len(expected_records), len(actual_records))
for (expected_rr, actual_rr) in zip(expected_records, actual_records):
self.assertTrue(expected_rr, actual_rr)
self.assertTrue(rrsets_equal(expected_rr, actual_rr))
def test_ixfr_soa_only(self):
# The requested SOA serial is the latest one. The response should
......@@ -956,7 +1111,8 @@ class TestXfroutSessionWithSQLite3(TestXfroutSessionBase):
response = self.sock.read_msg(Message.PRESERVE_ORDER);
answers = response.get_section(Message.SECTION_ANSWER)
self.assertEqual(1, len(answers))
self.assertTrue(create_soa(SOA_CURRENT_VERSION), answers[0])
self.assertTrue(rrsets_equal(create_soa(SOA_CURRENT_VERSION),
answers[0]))
class MyUnixSockServer(UnixSockServer):
def __init__(self):
......
......@@ -66,6 +66,11 @@ class XfroutConfigError(Exception):
"""
pass
class XfroutSessionError(Exception):
'''An exception raised for some unexpected events during an xfrout session.
'''
pass
def init_paths():
global SPECFILE_PATH
global AUTH_SPECFILE_PATH
......@@ -93,7 +98,8 @@ init_paths()
SPECFILE_LOCATION = SPECFILE_PATH + "/xfrout.spec"
AUTH_SPECFILE_LOCATION = AUTH_SPECFILE_PATH + os.sep + "auth.spec"
VERBOSE_MODE = False
XFROUT_MAX_MESSAGE_SIZE = 65535
XFROUT_DNS_HEADER_SIZE = 12 # protocol constant
XFROUT_MAX_MESSAGE_SIZE = 65535 # ditto
# borrowed from xfrin.py @ #1298. We should eventually unify it.
def format_zone_str(zone_name, zone_class):
......@@ -534,32 +540,44 @@ class XfroutSession():
def _send_message_with_last_soa(self, msg, sock_fd, rrset_soa,
message_upper_len):
'''Add the SOA record to the end of message. If it can't be
added, a new message should be created to send out the last soa .
'''Add the SOA record to the end of message.
If it would exceed the maximum allowable size of a message, a new
message will be created to send out the last SOA.
We assume a message with a single SOA can always fit the buffer
with or without TSIG. In theory this could be wrong if TSIG is
stupidly large, but in practice this assumption should be reasonable.
'''
if (message_upper_len + self._tsig_len + get_rrset_len(rrset_soa) >=
XFROUT_MAX_MESSAGE_SIZE):
if message_upper_len + get_rrset_len(rrset_soa) > \
XFROUT_MAX_MESSAGE_SIZE:
self._send_message(sock_fd, msg, self._tsig_ctx)
msg = self._clear_message(msg)
# If tsig context exist, sign the last packet
msg.add_rrset(Message.SECTION_ANSWER, rrset_soa)
self._send_message(sock_fd, msg, self._tsig_ctx)
def _reply_xfrout_query(self, msg, sock_fd):
#TODO, there should be a better way to insert rrset.
msg.make_response()
msg.set_header_flag(Message.HEADERFLAG_AA)
# Reserved space for the fixed header size, the size of the question
# section, and TSIG size (when included). The size of the question
# section is the sum of the qname length and the size of the
# fixed-length fields (type and class, 2 bytes each).
message_upper_len = XFROUT_DNS_HEADER_SIZE + \
msg.get_question()[0].get_name().get_length() + 4 + \
self._tsig_len
# If the iterator is None, we are responding to IXFR with a single
# SOA RR.
if self._iterator is None:
self._send_message_with_last_soa(msg, sock_fd, self._soa, 0)
self._send_message_with_last_soa(msg, sock_fd, self._soa,
message_upper_len)
return
# Add the beginning SOA
msg.add_rrset(Message.SECTION_ANSWER, self._soa)
message_upper_len = get_rrset_len(self._soa) + self._tsig_len
message_upper_len += get_rrset_len(self._soa)
# Add the rest of the zone/diff contets
for rrset in self._iterator:
......@@ -577,20 +595,33 @@ class XfroutSession():
# size without compression) and use that to see if we
# may have reached the limit
rrset_len = get_rrset_len(rrset)
if message_upper_len + rrset_len < XFROUT_MAX_MESSAGE_SIZE:
if message_upper_len + rrset_len <= XFROUT_MAX_MESSAGE_SIZE:
msg.add_rrset(Message.SECTION_ANSWER, rrset)
message_upper_len += rrset_len
continue
# RR would not fit. If there are other RRs in the buffer, send
# them now and leave this RR to the next message.
self._send_message(sock_fd, msg, self._tsig_ctx)
# Create a new message and reserve space for the carried-over
# RR (and TSIG space in case it's to be TSIG signed)
msg = self._clear_message(msg)
message_upper_len = XFROUT_DNS_HEADER_SIZE + rrset_len + \
self._tsig_len
# If this RR overflows the buffer all by itself, fail. In theory
# some RRs might fit in a TCP message when compressed even if they
# do not fit when uncompressed, but surely we don't want to send
# such monstrosities to an unsuspecting slave.
if message_upper_len > XFROUT_MAX_MESSAGE_SIZE:
raise XfroutSessionError('RR too large for zone transfer (' +
str(rrset_len) + ' bytes)')
# Add the RRset to the new message
msg.add_rrset(Message.SECTION_ANSWER, rrset)
# Reserve tsig space for signed packet
message_upper_len = rrset_len + self._tsig_len
# Add and send the trailing SOA
self._send_message_with_last_soa(msg, sock_fd, self._soa,
message_upper_len)
......@@ -782,7 +813,6 @@ class UnixSockServer(socketserver_mixin.NoPollMixIn,
os.unlink(self._sock_file)
except Exception as e:
logger.error(XFROUT_REMOVE_UNIX_SOCKET_FILE_ERROR, self._sock_file, str(e))
pass
def update_config_data(self, new_config):
'''Apply the new config setting of xfrout module.
......
......@@ -14,6 +14,9 @@ CLEANFILES = *.gcno *.gcda
# with -Werror (our default setting).
lib_LTLIBRARIES = libasiolink.la
libasiolink_la_LDFLAGS = -no-undefined -version-info 1:0:1
libasiolink_la_SOURCES = asiolink.h
libasiolink_la_SOURCES += dummy_io_cb.h
libasiolink_la_SOURCES += interval_timer.cc interval_timer.h
......
......@@ -7,9 +7,15 @@ AM_CPPFLAGS += $(SQLITE_CFLAGS)
AM_CXXFLAGS = $(B10_CXXFLAGS)
pkglibexecdir = $(libexecdir)/@PACKAGE@/backends
datasrc_config.h: datasrc_config.h.pre
$(SED) -e "s|@@PKGLIBEXECDIR@@|$(pkglibexecdir)|" datasrc_config.h.pre >$@
CLEANFILES = *.gcno *.gcda datasrc_messages.h datasrc_messages.cc
CLEANFILES += datasrc_config.h
lib_LTLIBRARIES = libdatasrc.la sqlite3_ds.la memory_ds.la
lib_LTLIBRARIES = libdatasrc.la
libdatasrc_la_SOURCES = data_source.h data_source.cc
libdatasrc_la_SOURCES += static_datasrc.h static_datasrc.cc
libdatasrc_la_SOURCES += sqlite3_datasrc.h sqlite3_datasrc.cc
......@@ -25,8 +31,11 @@ libdatasrc_la_SOURCES += database.h database.cc
libdatasrc_la_SOURCES += factory.h factory.cc
nodist_libdatasrc_la_SOURCES = datasrc_messages.h datasrc_messages.cc
pkglibexec_LTLIBRARIES = sqlite3_ds.la memory_ds.la
sqlite3_ds_la_SOURCES = sqlite3_accessor.h sqlite3_accessor.cc
sqlite3_ds_la_LDFLAGS = -module
sqlite3_ds_la_LDFLAGS += -no-undefined -version-info 1:0:0
sqlite3_ds_la_LIBADD = $(top_builddir)/src/lib/exceptions/libexceptions.la
sqlite3_ds_la_LIBADD += libdatasrc.la
sqlite3_ds_la_LIBADD += $(SQLITE_LIBS)
......@@ -42,7 +51,7 @@ libdatasrc_la_LIBADD += $(top_builddir)/src/lib/log/liblog.la
libdatasrc_la_LIBADD += $(top_builddir)/src/lib/cc/libcc.la
libdatasrc_la_LIBADD += $(SQLITE_LIBS)
BUILT_SOURCES = datasrc_messages.h datasrc_messages.cc
BUILT_SOURCES = datasrc_config.h datasrc_messages.h datasrc_messages.cc
datasrc_messages.h datasrc_messages.cc: Makefile datasrc_messages.mes
$(top_builddir)/src/lib/log/compiler/message $(top_srcdir)/src/lib/datasrc/datasrc_messages.mes
......
......@@ -843,7 +843,7 @@ public:
committed_(false), accessor_(accessor), zone_id_(zone_id),
db_name_(accessor->getDBName()), zone_name_(zone_name.toText()),
zone_class_(zone_class), journaling_(journaling),
diff_phase_(NOT_STARTED),
diff_phase_(NOT_STARTED), serial_(0),
finder_(new DatabaseClient::Finder(accessor_, zone_id_, zone_name))
{
logger.debug(DBG_TRACE_DATA, DATASRC_DATABASE_UPDATER_CREATED)
......@@ -896,7 +896,7 @@ private:
ADD
};
DiffPhase diff_phase_;
uint32_t serial_;
Serial serial_;
boost::scoped_ptr<DatabaseClient::Finder> finder_;
// This is a set of validation checks commonly used for addRRset() and
......@@ -985,8 +985,8 @@ DatabaseUpdater::addRRset(const RRset& rrset) {
columns[Accessor::ADD_RDATA] = it->getCurrent().toText();
if (journaling_) {
journal[Accessor::DIFF_RDATA] = columns[Accessor::ADD_RDATA];
accessor_->addRecordDiff(zone_id_, serial_, Accessor::DIFF_ADD,
journal);
accessor_->addRecordDiff(zone_id_, serial_.getValue(),
Accessor::DIFF_ADD, journal);
}
accessor_->addRecordToZone(columns);
}
......@@ -1023,8 +1023,8 @@ DatabaseUpdater::deleteRRset(const RRset& rrset) {
params[Accessor::DEL_RDATA] = it->getCurrent().toText();
if (journaling_) {
journal[Accessor::DIFF_RDATA] = params[Accessor::DEL_RDATA];
accessor_->addRecordDiff(zone_id_, serial_, Accessor::DIFF_DELETE,
journal);
accessor_->addRecordDiff(zone_id_, serial_.getValue(),
Accessor::DIFF_DELETE, journal);
}
accessor_->deleteRecordInZone(params);
}
......
// Copyright (C) 2011 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