[svn] commit: r3184 - in /branches/trac232/src: bin/xfrin/ lib/datasrc/ lib/datasrc/python/ lib/datasrc/python/tests/ lib/datasrc/tests/
BIND 10 source code commits
bind10-changes at lists.isc.org
Tue Oct 12 09:42:13 UTC 2010
Author: jelte
Date: Tue Oct 12 09:42:13 2010
New Revision: 3184
Log:
added a replaceZone() where you pass a function that provides the data to replace it with.
In the python library, this function should return an iterator
modified xfrin to use that
Modified:
branches/trac232/src/bin/xfrin/xfrin.py.in
branches/trac232/src/lib/datasrc/data_source.cc
branches/trac232/src/lib/datasrc/data_source.h
branches/trac232/src/lib/datasrc/python/libdata_source_python.cc
branches/trac232/src/lib/datasrc/python/tests/data_source_python_test.py
branches/trac232/src/lib/datasrc/sqlite3_datasrc.cc
branches/trac232/src/lib/datasrc/sqlite3_datasrc.h
branches/trac232/src/lib/datasrc/tests/sqlite3_unittest.cc
Modified: branches/trac232/src/bin/xfrin/xfrin.py.in
==============================================================================
--- branches/trac232/src/bin/xfrin/xfrin.py.in (original)
+++ branches/trac232/src/bin/xfrin/xfrin.py.in Tue Oct 12 09:42:13 2010
@@ -200,8 +200,22 @@
self._send_query(RRType(252))
#isc.datasrc.sqlite3_ds.load(self._db_file, self._zone_name,
# self._handle_xfrin_response)
- self._handle_xfrin_response_new()
+
+ #self._handle_xfrin_response_new()
+ ds = libdata_source_python.DataSrc()
+ ds.init("{ \"database_file\": \"" + self._db_file +"\" }")
+ transaction = libdata_source_python.DataSrcTransaction(ds, Name(self._zone_name), RRClass.IN())
+ result = ds.start_transaction(transaction, True)
+
+ #result = ds.replace_zone(transaction, XfrinConnection._handle_xfrin_response, self)
+ print("[XX] Replacing zone")
+ result = ds.replace_zone(transaction, self._handle_xfrin_response)
+ print("[XX] done replacing zone")
+ #result = ds.replace_zone(transaction, test_xx_removeme)
+
+ result = ds.commit_transaction(transaction)
+ ds.close()
self.log_msg(logstr + 'succeeded')
@@ -214,6 +228,10 @@
self.log_msg(logstr + 'failed')
ret = XFRIN_FAIL
#TODO, recover data source.
+ except libdata_source_python.DataSrcError as dse:
+ self.log_msg(dse)
+ self.log_msg(logstr + 'failed')
+ ret = XFRIN_FAIL
except isc.datasrc.sqlite3_ds.Sqlite3DSError as e:
self.log_msg(e)
self.log_msg(logstr + 'failed')
@@ -292,7 +310,11 @@
def _handle_xfrin_response(self):
'''Return a generator for the response to a zone transfer. '''
- while True:
+ done = False
+ print("[XX] HANDLE generator called")
+ sys.stdout.flush()
+ soa_seen = False
+ while not done:
data_len = self._get_request_response(2)
msg_len = socket.htons(struct.unpack('H', data_len)[0])
recvdata = self._get_request_response(msg_len)
@@ -301,8 +323,39 @@
self._check_response_status(msg)
answer_section = msg.get_section(Section.ANSWER())
- for rr in self._handle_answer_section(answer_section):
- yield rr
+ print("[XX] LIST:")
+ for a in answer_section:
+ print(a)
+ for rrset in answer_section:
+ print("[XX] Type: " + rrset.get_type().to_text() + " soa seen: " + str(soa_seen))
+ sys.stdout.flush()
+ if rrset.get_type() == RRType.SOA():
+ print("[XX] SOA!")
+ sys.stdout.flush()
+ if soa_seen:
+ # second one, we're done.
+ print("[XX] Second SOA, done!")
+ done = True
+ break
+ elif rrset.get_rdata_count() == 2:
+ # workaround for current problem where second
+ # soa rr gets added by the parse to the first
+ done = True
+ new_soa = RRset(rrset.get_name(), rrset.get_class(),
+ rrset.get_type(), rrset.get_ttl())
+ new_soa.add_rdata(rrset.get_rdata()[0])
+ print("[XX] YIELDING: ")
+ print(new_soa)
+ sys.stdout.flush()
+ yield new_soa
+ else:
+ print("[XX] first soa")
+ sys.stdout.flush()
+ soa_seen = True
+ print("[XX] YIELDING: ")
+ print(rrset)
+ sys.stdout.flush()
+ yield rrset
if self._soa_rr_count == 2:
break
@@ -320,12 +373,22 @@
self._check_response_status(msg)
answer_section = msg.get_section(Section.ANSWER())
+
+ # tmp workaround until we can do this right (both soa rrs
+ # are put as one rrset in the beginning of the message)
+ soa_rrset = answer_section[0]
+ new_soa = RRset(soa_rrset.get_name(), soa_rrset.get_class(),
+ soa_rrset.get_type(), soa_rrset.get_ttl())
+ new_soa.add_rdata(soa_rrset.get_rdata()[0])
+ answer_section[0] = new_soa
+
ds = libdata_source_python.DataSrc()
ds.init("{ \"database_file\": \"" + self._db_file +"\" }")
transaction = libdata_source_python.DataSrcTransaction(ds, Name(self._zone_name), RRClass.IN())
- result = ds.start_transaction(transaction)
- result = ds.do_ixfr(transaction, answer_section)
-
+ result = ds.start_transaction(transaction, True)
+
+ result = ds.replace_zone(transaction, answer_section)
+
result = ds.commit_transaction(transaction)
ds.close()
Modified: branches/trac232/src/lib/datasrc/data_source.cc
==============================================================================
--- branches/trac232/src/lib/datasrc/data_source.cc (original)
+++ branches/trac232/src/lib/datasrc/data_source.cc Tue Oct 12 09:42:13 2010
@@ -1303,6 +1303,14 @@
return (W_NOT_IMPLEMENTED);
}
+DataSrc::WriteResult
+DataSrc::replaceZone(DataSrcTransaction& transaction UNUSED_PARAM,
+ isc::dns::RRsetPtr nextRRset(void*, void*) UNUSED_PARAM,
+ void* arg1 UNUSED_PARAM, void* arg2 UNUSED_PARAM)
+{
+ return (W_NOT_IMPLEMENTED);
+}
+
static bool
equalRRsets(ConstRRsetPtr a, ConstRRsetPtr b) {
if (a->getName() != b->getName() ||
@@ -1476,8 +1484,14 @@
}
RRsetIterator rrsets = start;
+ if (rrsets == end) {
+ return (DataSrc::ERROR);
+ }
RRsetPtr final_soa = *rrsets;
rrsets++;
+ if (rrsets == end) {
+ return (DataSrc::ERROR);
+ }
RRsetPtr first_soa = *rrsets;
rrsets++;
if (first_soa->getType() == RRType::SOA()) {
@@ -1701,5 +1715,13 @@
return (W_NOT_IMPLEMENTED);
}
-}
-}
+DataSrc::WriteResult
+MetaDataSrc::replaceZone(DataSrcTransaction& transaction UNUSED_PARAM,
+ isc::dns::RRsetPtr nextRRset(void*, void*) UNUSED_PARAM,
+ void* arg1 UNUSED_PARAM, void* arg2 UNUSED_PARAM)
+{
+ return (W_NOT_IMPLEMENTED);
+}
+
+}
+}
Modified: branches/trac232/src/lib/datasrc/data_source.h
==============================================================================
--- branches/trac232/src/lib/datasrc/data_source.h (original)
+++ branches/trac232/src/lib/datasrc/data_source.h Tue Oct 12 09:42:13 2010
@@ -420,9 +420,27 @@
/// rrsets.
/// This deletes *all* current RRsets in the zone.
/// \param transaction The transaction to perform the operations on
+ /// \param rrsets The full set of rrsets to replace the zone with
/// \return W_SUCCESS on success
virtual WriteResult replaceZone(DataSrcTransaction& transaction,
const isc::dns::RRsetContainer& rrsets);
+
+ /// \brief Replace the contents of the zone by the rrsets returned
+ /// by the given function callback.
+ /// The provided function should return exactly one RRsetPtr on
+ /// each call. It
+ /// This deletes *all* current RRsets in the zone.
+ /// \param transaction The transaction to perform the operations on
+ /// \param nextRRset Function that returns the next RRsetPtr on
+ /// each call to it
+ /// \param arg1 This will be passed as the first argument to the
+ /// nextRRset function (defaults to NULL)
+ /// \param arg2 This will be passed as the second argument to the
+ /// nextRRset function (defaults to NULL)
+ /// \return W_SUCCESS on success
+ virtual WriteResult replaceZone(DataSrcTransaction& transaction,
+ isc::dns::RRsetPtr nextRRset(void*, void*),
+ void* arg1 = NULL, void* arg2 = NULL);
//@}
/// \name High-level functions for writable data sources
@@ -465,14 +483,15 @@
virtual isc::dns::Rcode updateProcessUpdate(DataSrcTransaction& transaction,
isc::dns::RRsetPtr update);
- /// \brief Perform an IXFR operation
+ /// \brief Perform an IXFR operation directly from a dns message
+ /// section iterator
/// The given RRset iterator should point to the section of the
/// IXFR answer, and is processed as described in RFC1995
/// \param transaction the transaction to perform the operation in
/// \param start The start of the rrset iterator to handle
/// \param end the end of the rrset iterator to handle
/// \return SUCCESS on success, ERROR on failure.
- virtual Result doIXFR(DataSrcTransaction& transaction,
+ virtual Result doIXFR(DataSrcTransaction& transaction,
const isc::dns::RRsetIterator start,
const isc::dns::RRsetIterator end);
@@ -568,6 +587,9 @@
virtual WriteResult delZone(DataSrcTransaction& transaction);
virtual WriteResult replaceZone(DataSrcTransaction& transaction,
const isc::dns::RRsetContainer& rrsets);
+ virtual WriteResult replaceZone(DataSrcTransaction& transaction,
+ isc::dns::RRsetPtr nextRRset(void*, void*),
+ void* arg1 = NULL, void* arg2 = NULL);
// end of writable data sources part
private:
std::vector<ConstDataSrcPtr> data_sources;
Modified: branches/trac232/src/lib/datasrc/python/libdata_source_python.cc
==============================================================================
--- branches/trac232/src/lib/datasrc/python/libdata_source_python.cc (original)
+++ branches/trac232/src/lib/datasrc/python/libdata_source_python.cc Tue Oct 12 09:42:13 2010
@@ -819,10 +819,16 @@
static PyObject*
DataSrc_startTransaction(s_DataSrc* self, PyObject* args) {
s_DataSrcTransaction *transaction;
- if (PyArg_ParseTuple(args, "O!",
- &datasrc_transaction_type, &transaction)) {
+ PyObject* py_create_zone = NULL;
+ if (PyArg_ParseTuple(args, "O!|O",
+ &datasrc_transaction_type, &transaction,
+ &py_create_zone)) {
+ bool create_zone = false;
+ if (py_create_zone && PyObject_IsTrue(py_create_zone)) {
+ create_zone = true;
+ }
PyObject* result = Py_BuildValue("I", self->datasrc->startTransaction(
- *(transaction->datasrc_transaction)));
+ *(transaction->datasrc_transaction), create_zone));
// We increase the reference count, since the transaction
// object contains a reference to the data source
// The corresponding DECREF is in commit/rollback
@@ -916,34 +922,100 @@
}
+/// only used in the callback iterator to signal to the wrapping
+/// function that an object is not an RRset
+class NotRRsetException : public std::exception {};
+
+isc::dns::RRsetPtr
+callback_iterator(void* arg1, void* arg2)
+{
+ PyObject* iterator = reinterpret_cast<PyObject*>(arg1);
+ std::cout << "[XX] Getting next value from iterator" << std::endl;
+ PyObject* rrset_obj = PyIter_Next(iterator);
+ std::cout << "[XX] got next value from iterator" << std::endl;
+ if (rrset_obj) {
+ if (PyRRset_Check(rrset_obj)) {
+ return PyRRset_AsRRsetPtr(rrset_obj);
+ } else {
+ throw NotRRsetException();
+ }
+ } else {
+ return isc::dns::RRsetPtr();
+ }
+}
+
static PyObject*
DataSrc_replaceZone(s_DataSrc* self, PyObject* args) {
s_DataSrcTransaction *transaction;
- PyObject *rrset_list_obj;
-
- if (PyArg_ParseTuple(args, "O!O",
+ PyObject* rrset_list_or_function_obj;
+ PyObject* arg1 = NULL;
+ PyObject* arg2 = NULL;
+
+ if (PyArg_ParseTuple(args, "O!O|OO",
&datasrc_transaction_type, &transaction,
- &rrset_list_obj)) {
- if (!PyList_Check(rrset_list_obj)) {
- PyErr_SetString(PyExc_TypeError,
- "argument 2 of replace_zone() is not a List");
- return (NULL);
- }
- isc::dns::RRsetContainer rrset_list;
- for (int i = 0; i < PyList_Size(rrset_list_obj); ++i) {
- PyObject* rrset_obj = PyList_GET_ITEM(rrset_list_obj, i);
- if (!PyRRset_Check(rrset_obj)) {
- PyErr_SetString(PyExc_TypeError,
- "non-RRset object in argument 2 of replace_zone()");
+ &rrset_list_or_function_obj,
+ &arg1, &arg2)) {
+ if (PyList_Check(rrset_list_or_function_obj)) {
+ std::cout << "[XX] list argument" << std::endl;
+ isc::dns::RRsetContainer rrset_list;
+ for (int i = 0; i < PyList_Size(rrset_list_or_function_obj); ++i) {
+ PyObject* rrset_obj = PyList_GET_ITEM(rrset_list_or_function_obj, i);
+ if (!PyRRset_Check(rrset_obj)) {
+ PyErr_SetString(PyExc_TypeError,
+ "non-RRset object in argument 2 of replace_zone()");
+ return (NULL);
+ }
+ rrset_list.addRRset(PyRRset_AsRRsetPtr(rrset_obj));
+ }
+ PyObject* result = Py_BuildValue("I",
+ self->datasrc->replaceZone(
+ *(transaction->datasrc_transaction),
+ rrset_list));
+ return (result);
+ } else if (PyCallable_Check(rrset_list_or_function_obj)) {
+ std::cout << "[XX] callable argument" << std::endl;
+ PyObject* iterator = PyObject_CallFunctionObjArgs(rrset_list_or_function_obj, arg1, arg2, NULL);
+ if (!iterator) {
return (NULL);
}
- rrset_list.addRRset(PyRRset_AsRRsetPtr(rrset_obj));
- }
- PyObject* result = Py_BuildValue("I",
- self->datasrc->replaceZone(
- *(transaction->datasrc_transaction),
- rrset_list));
- return (result);
+ if (!PyIter_Check(iterator)) {
+ PyErr_SetString(PyExc_TypeError,
+ "Callback in replace_zone() is not an iterator");
+ return (NULL);
+ }
+ try {
+ PyObject* result = Py_BuildValue("I",
+ self->datasrc->replaceZone(
+ *(transaction->datasrc_transaction),
+ callback_iterator,
+ iterator, NULL
+ ));
+ return (result);
+ } catch (NotRRsetException) {
+ PyErr_SetString(PyExc_TypeError,
+ "non-RRset object returned by iterator in replace_zone()");
+ return (NULL);
+ }
+ /*
+ PyObject* rrset_obj;
+ while (rrset_obj = PyIter_Next(iterator)) {
+ std::cout << "[XX] GOT OBJ!" << std::endl;
+ //std::cout << PyObject_Dir(rrset_obj) << std::endl;
+ if (!PyRRset_Check(rrset_obj)) {
+ PyErr_SetString(PyExc_TypeError,
+ "non-RRset object returned by iterator in replace_zone()");
+ return (NULL);
+ }
+ }
+ PyErr_SetString(PyExc_TypeError,
+ "Callable!!!");
+ return (NULL);
+ */
+ } else {
+ PyErr_SetString(PyExc_TypeError,
+ "argument 2 of replace_zone() is not a List or a function");
+ return (NULL);
+ }
}
return (NULL);
}
Modified: branches/trac232/src/lib/datasrc/python/tests/data_source_python_test.py
==============================================================================
--- branches/trac232/src/lib/datasrc/python/tests/data_source_python_test.py (original)
+++ branches/trac232/src/lib/datasrc/python/tests/data_source_python_test.py Tue Oct 12 09:42:13 2010
@@ -23,6 +23,14 @@
from libdata_source_python import *
from pydnspp import *
+def get_new_rrs(list):
+ print("[XX] GET_NEW_RRS CALLED")
+ for l in list:
+ print("[XX] get_new_rrs list item: ")
+ print(l)
+ yield l
+
+
class DataSourceTest(unittest.TestCase):
def setUp(self):
self.ds = DataSrc()
@@ -338,7 +346,7 @@
result = self.ds.start_transaction(transaction)
self.assertEqual(DataSrc.W_NO_SUCH_ZONE, result)
- def test_replace_zone(self):
+ def test_replace_zone_list(self):
transaction = DataSrcTransaction(self.ds, Name("example.com"), RRClass.IN())
result = self.ds.start_transaction(transaction)
self.assertEqual(DataSrc.W_SUCCESS, result)
@@ -363,6 +371,45 @@
n = self.ds.find_rrset(Name("www.example.com"), RRClass.IN(), RRType.A(), result, 0, Name("example.com"))
self.assertEqual(DataSrc.SUCCESS, n);
self.assertEqual(0, len(result))
+
+ def test_replace_zone_function(self):
+ transaction = DataSrcTransaction(self.ds, Name("example.com"), RRClass.IN())
+ result = self.ds.start_transaction(transaction)
+ self.assertEqual(DataSrc.W_SUCCESS, result)
+
+ result = []
+ n = self.ds.find_rrset(Name("www.example.com"), RRClass.IN(), RRType.A(), result, 0, Name("example.com"))
+ self.assertEqual(DataSrc.SUCCESS, n);
+ self.assertEqual(1, len(result))
+
+ result = []
+ n = self.ds.find_rrset(Name("example.com"), RRClass.IN(), RRType.SOA(), result, 0, Name("example.com"))
+ self.assertEqual(DataSrc.SUCCESS, n);
+ self.assertEqual(1, len(result))
+
+ rrset1 = result[0]
+ rrset2 = RRset(Name("added.example.com"), RRClass.IN(), RRType.A(), RRTTL(3600))
+ rrset2.add_rdata(Rdata(rrset2.get_type(), rrset2.get_class(), "192.0.2.1"))
+ rrset3 = RRset(Name("added2.example.com"), RRClass.IN(), RRType.A(), RRTTL(3600))
+ rrset3.add_rdata(Rdata(rrset3.get_type(), rrset3.get_class(), "192.0.2.2"))
+
+ new_rrs = [ rrset1, rrset2, rrset3 ]
+
+ print("[XX] About to call replace_zone with function")
+ result = self.ds.replace_zone(transaction, get_new_rrs, new_rrs)
+ self.assertEqual(DataSrc.W_SUCCESS, result)
+
+ result = self.ds.commit_transaction(transaction)
+ self.assertEqual(DataSrc.W_SUCCESS, result)
+
+ result = []
+ n = self.ds.find_rrset(Name("www.example.com"), RRClass.IN(), RRType.A(), result, 0, Name("example.com"))
+ self.assertEqual(DataSrc.SUCCESS, n);
+ self.assertEqual(0, len(result))
+
+ n = self.ds.find_rrset(Name("added.example.com"), RRClass.IN(), RRType.A(), result, 0, Name("example.com"))
+ self.assertEqual(DataSrc.SUCCESS, n);
+ self.assertEqual(1, len(result))
def test_have_rrset(self):
transaction = DataSrcTransaction(self.ds, Name("example.com"), RRClass.IN())
Modified: branches/trac232/src/lib/datasrc/sqlite3_datasrc.cc
==============================================================================
--- branches/trac232/src/lib/datasrc/sqlite3_datasrc.cc (original)
+++ branches/trac232/src/lib/datasrc/sqlite3_datasrc.cc Tue Oct 12 09:42:13 2010
@@ -979,6 +979,7 @@
rdp->next();
}
} while (!rdp->isLast());
+ std::cout << "[XX] added rrset to zone " << zone_id << ": " << rrset->toText() << std::endl;
return result;
}
@@ -1139,6 +1140,37 @@
while (it != rrsets.end()) {
result = addRRset(transaction, *it);
if (result != DataSrc::W_SUCCESS) {
+ return result;
+ }
+ it++;
+ }
+ return DataSrc::W_SUCCESS;
+}
+
+DataSrc::WriteResult
+Sqlite3DataSrc::replaceZone(DataSrcTransaction& transaction,
+ isc::dns::RRsetPtr nextRRset(void*, void*),
+ void* arg1, void* arg2)
+{
+ if (transaction.getState() != DataSrcTransaction::RUNNING) {
+ std::cout << "[XX] Transaction not running" << std::endl;
+ return DataSrc::W_ERROR;
+ }
+
+ int zone_id = transaction.getData()->get("zone_id")->intValue();
+
+ DataSrc::WriteResult result = delAll(zone_id);
+ if (result != DataSrc::W_SUCCESS) {
+ std::cout << "[XX] delAll failed" << std::endl;
+ return result;
+ }
+
+ RRsetPtr next_rrset;
+ while (next_rrset = nextRRset(arg1, arg2)) {
+ std::cout << "[XX] adding rrset: " << next_rrset->toText() << std::endl;
+ result = addRRset(transaction, next_rrset);
+ if (result != DataSrc::W_SUCCESS) {
+ std::cout << "[XX] addrrset failed" << std::endl;
return result;
}
}
Modified: branches/trac232/src/lib/datasrc/sqlite3_datasrc.h
==============================================================================
--- branches/trac232/src/lib/datasrc/sqlite3_datasrc.h (original)
+++ branches/trac232/src/lib/datasrc/sqlite3_datasrc.h Tue Oct 12 09:42:13 2010
@@ -118,6 +118,9 @@
isc::dns::ConstRRsetPtr rrset);
WriteResult replaceZone(DataSrcTransaction& transaction,
const isc::dns::RRsetContainer& rrsets);
+ WriteResult replaceZone(DataSrcTransaction& transaction,
+ isc::dns::RRsetPtr nextRRset(void*, void*),
+ void* arg1 = NULL, void* arg2 = NULL);
WriteResult delZone(DataSrcTransaction& transaction);
private:
Modified: branches/trac232/src/lib/datasrc/tests/sqlite3_unittest.cc
==============================================================================
--- branches/trac232/src/lib/datasrc/tests/sqlite3_unittest.cc (original)
+++ branches/trac232/src/lib/datasrc/tests/sqlite3_unittest.cc Tue Oct 12 09:42:13 2010
@@ -13,6 +13,8 @@
// PERFORMANCE OF THIS SOFTWARE.
// $Id$
+
+#include <config.h>
#include <stdint.h>
@@ -1106,7 +1108,7 @@
EXPECT_EQ(DataSrc::NAME_NOT_FOUND, find_flags);
}
-TEST_F(Sqlite3DataSourceTest, replaceZone) {
+TEST_F(Sqlite3DataSourceTest, replaceZone_container) {
// reset database
ASSERT_EQ(0, install_writable_database());
@@ -1149,6 +1151,133 @@
EXPECT_EQ(DataSrc::NAME_NOT_FOUND, find_flags);
EXPECT_EQ(1, result_sets.size());
+}
+
+RRsetPtr
+getRRsetCallback_empty(void *arg1 UNUSED_PARAM,
+ void* arg2 UNUSED_PARAM) {
+ return RRsetPtr();
+}
+
+TEST_F(Sqlite3DataSourceTest, replaceZone_callback_empty) {
+ // reset database
+ ASSERT_EQ(0, install_writable_database());
+
+ // use our copied writable datasource db
+ ASSERT_EQ(DataSrc::SUCCESS, data_source.close());
+ ASSERT_EQ(DataSrc::SUCCESS, data_source.init(SQLITE_DBFILE_WRITE));
+
+ // check whether an A exists
+ EXPECT_EQ(DataSrc::SUCCESS,
+ data_source.findRRset(www_name, RRClass::IN(), RRType::A(),
+ result_sets, find_flags, &zone_name));
+ EXPECT_EQ(DataSrc::SUCCESS, find_flags);
+ EXPECT_EQ(1, result_sets.size());
+
+ // Replace them, roll back
+ DataSrcTransaction transaction1(&data_source, zone_name, RRClass::IN());
+ ASSERT_EQ(DataSrc::W_SUCCESS, data_source.startTransaction(transaction1));
+ ASSERT_EQ(DataSrc::W_SUCCESS, data_source.replaceZone(transaction1, getRRsetCallback_empty));
+ ASSERT_EQ(DataSrc::W_SUCCESS, data_source.rollbackTransaction(transaction1));
+
+ // check whether it still exists
+ EXPECT_EQ(DataSrc::SUCCESS,
+ data_source.findRRset(www_name, RRClass::IN(), RRType::A(),
+ result_sets, find_flags, &zone_name));
+ EXPECT_EQ(DataSrc::SUCCESS, find_flags);
+ EXPECT_EQ(1, result_sets.size());
+
+ // Replace them, commit
+ DataSrcTransaction transaction2(&data_source, zone_name, RRClass::IN());
+ ASSERT_EQ(DataSrc::W_SUCCESS, data_source.startTransaction(transaction2));
+ ASSERT_EQ(DataSrc::W_SUCCESS, data_source.replaceZone(transaction2, getRRsetCallback_empty));
+ ASSERT_EQ(DataSrc::W_SUCCESS, data_source.commitTransaction(transaction2));
+
+ // check whether it's gone now
+ EXPECT_EQ(DataSrc::SUCCESS,
+ data_source.findRRset(www_name, RRClass::IN(), RRType::A(),
+ result_sets, find_flags, &zone_name));
+ EXPECT_EQ(DataSrc::NAME_NOT_FOUND, find_flags);
+ EXPECT_EQ(1, result_sets.size());
+
+}
+
+RRsetPtr
+getRRsetCallback_vector(void *arg1,
+ void *arg2)
+{
+ //std::vector<RRsetPtr> v = static_cast<std::vector<RRsetPtr> >(arg1);
+ std::vector<RRsetPtr>* v = reinterpret_cast<std::vector<RRsetPtr>* >(arg1);
+ size_t* i = reinterpret_cast<size_t*>(arg2);
+ std::cout << "[XX] getRRsetCallback_vector() called" << std::endl;
+ std::cout << "[XX] i: " << *i << std::endl;
+
+ if (*i < v->size()) {
+ return ((*v)[(*i)++]);
+ } else {
+ return (RRsetPtr());
+ }
+}
+
+TEST_F(Sqlite3DataSourceTest, replaceZone_callback_vector) {
+ std::vector<RRsetPtr> rrsets;
+
+ size_t i = 0;
+
+ // reset database
+ ASSERT_EQ(0, install_writable_database());
+
+ // use our copied writable datasource db
+ ASSERT_EQ(DataSrc::SUCCESS, data_source.close());
+ ASSERT_EQ(DataSrc::SUCCESS, data_source.init(SQLITE_DBFILE_WRITE));
+
+ // Let's take the existing SOA for now
+ RRsetList soa_rrset;
+ EXPECT_EQ(DataSrc::SUCCESS,
+ data_source.findExactRRset(zone_name, RRClass::IN(), RRType::SOA(),
+ soa_rrset, find_flags, &zone_name));
+ ASSERT_EQ(DataSrc::SUCCESS, find_flags);
+ ASSERT_EQ(1, soa_rrset.size());
+
+ rrsets.push_back(soa_rrset.findRRset(RRType::SOA(), RRClass::IN()));
+ rrsets.push_back(new_rrset);
+
+ // Replace them, roll back
+ DataSrcTransaction transaction1(&data_source, zone_name, RRClass::IN());
+ ASSERT_EQ(DataSrc::W_SUCCESS, data_source.startTransaction(transaction1));
+ ASSERT_EQ(DataSrc::W_SUCCESS, data_source.replaceZone(transaction1, getRRsetCallback_vector, &rrsets, &i));
+ ASSERT_EQ(DataSrc::W_SUCCESS, data_source.rollbackTransaction(transaction1));
+
+ // check whether it still exists
+ EXPECT_EQ(DataSrc::SUCCESS,
+ data_source.findRRset(www_name, RRClass::IN(), RRType::A(),
+ result_sets, find_flags, &zone_name));
+ EXPECT_EQ(DataSrc::SUCCESS, find_flags);
+ EXPECT_EQ(1, result_sets.size());
+
+ // Replace them, commit
+ i = 0;
+ DataSrcTransaction transaction2(&data_source, zone_name, RRClass::IN());
+ ASSERT_EQ(DataSrc::W_SUCCESS, data_source.startTransaction(transaction2));
+ ASSERT_EQ(DataSrc::W_SUCCESS, data_source.replaceZone(transaction2, getRRsetCallback_vector, &rrsets, &i));
+ ASSERT_EQ(DataSrc::W_SUCCESS, data_source.commitTransaction(transaction2));
+
+ // check whether the original rrs are gone now
+ EXPECT_EQ(DataSrc::SUCCESS,
+ data_source.findRRset(www_name, RRClass::IN(), RRType::A(),
+ result_sets, find_flags, &zone_name));
+ EXPECT_EQ(DataSrc::NAME_NOT_FOUND, find_flags);
+ EXPECT_EQ(1, result_sets.size());
+
+ // and check if the new record exists
+ EXPECT_EQ(DataSrc::SUCCESS,
+ data_source.findExactRRset(new_rrset->getName(), new_rrset->getClass(), new_rrset->getType(),
+ result_sets, find_flags, &zone_name));
+ //std::cout << "[XX] done, exit" << std::endl;
+ //data_source.close();
+ //exit(0);
+ ASSERT_EQ(DataSrc::SUCCESS, find_flags);
+ ASSERT_EQ(1, result_sets.size());
}
TEST_F(Sqlite3DataSourceTest, delZone) {
More information about the bind10-changes
mailing list