Browse Source

[2573] added python wrapper for ZoneLoader extension

JINMEI Tatuya 12 years ago
parent
commit
ae4b62b7f8

+ 29 - 2
src/lib/python/isc/datasrc/tests/zone_loader_test.py

@@ -111,22 +111,49 @@ class ZoneLoaderTests(unittest.TestCase):
     def test_load_from_file(self):
     def test_load_from_file(self):
         self.loader = isc.datasrc.ZoneLoader(self.client, self.test_name,
         self.loader = isc.datasrc.ZoneLoader(self.client, self.test_name,
                                              self.test_file)
                                              self.test_file)
+        self.assertEqual(0, self.loader.get_rr_count())
+        self.assertEqual(0, self.loader.get_size())
+        self.assertEqual(0, self.loader.get_position())
+
         self.check_load()
         self.check_load()
 
 
+        # Expected values are hardcoded, taken from the test zone file,
+        # assuming it won't change too often.
+        self.assertEqual(8, self.loader.get_rr_count())
+        self.assertEqual(422, self.loader.get_size())
+        self.assertEqual(422, self.loader.get_position())
+
     def test_load_from_client(self):
     def test_load_from_client(self):
         self.source_client = isc.datasrc.DataSourceClient('sqlite3',
         self.source_client = isc.datasrc.DataSourceClient('sqlite3',
                                     DB_SOURCE_CLIENT_CONFIG)
                                     DB_SOURCE_CLIENT_CONFIG)
         self.loader = isc.datasrc.ZoneLoader(self.client, self.test_name,
         self.loader = isc.datasrc.ZoneLoader(self.client, self.test_name,
                                              self.source_client)
                                              self.source_client)
+
+        self.assertEqual(0, self.loader.get_rr_count())
+        self.assertEqual(0, self.loader.get_size())
+        self.assertEqual(0, self.loader.get_position())
+
         self.check_load()
         self.check_load()
 
 
-    def check_load_incremental(self):
+        # In case of loading from another data source, size and position are
+        # always 0.
+        self.assertEqual(8, self.loader.get_rr_count())
+        self.assertEqual(0, self.loader.get_size())
+        self.assertEqual(0, self.loader.get_position())
+
+    def check_load_incremental(self, from_file=True):
         # New zone has 8 RRs
         # New zone has 8 RRs
         # After 5, it should return False
         # After 5, it should return False
         self.assertFalse(self.loader.load_incremental(5))
         self.assertFalse(self.loader.load_incremental(5))
         # New zone should not have been loaded yet
         # New zone should not have been loaded yet
         self.check_zone_soa(ORIG_SOA_TXT)
         self.check_zone_soa(ORIG_SOA_TXT)
 
 
+        # In case it's from a zone file, check get_size() and get_position()
+        # are different.  expected values are taken from the test zone file.
+        if from_file:
+            self.assertEqual(422, self.loader.get_size())
+            self.assertEqual(288, self.loader.get_position())
+
         # After 5 more, it should return True (only having read 3)
         # After 5 more, it should return True (only having read 3)
         self.assertTrue(self.loader.load_incremental(5))
         self.assertTrue(self.loader.load_incremental(5))
         # New zone should now be loaded
         # New zone should now be loaded
@@ -147,7 +174,7 @@ class ZoneLoaderTests(unittest.TestCase):
                                             DB_SOURCE_CLIENT_CONFIG)
                                             DB_SOURCE_CLIENT_CONFIG)
         self.loader = isc.datasrc.ZoneLoader(self.client, self.test_name,
         self.loader = isc.datasrc.ZoneLoader(self.client, self.test_name,
                                              self.source_client)
                                              self.source_client)
-        self.check_load_incremental()
+        self.check_load_incremental(False)
 
 
     def test_bad_file(self):
     def test_bad_file(self):
         self.check_zone_soa(ORIG_SOA_TXT)
         self.check_zone_soa(ORIG_SOA_TXT)

+ 78 - 0
src/lib/python/isc/datasrc/zone_loader_inc.cc

@@ -113,4 +113,82 @@ on the next call (which will load 0 RRs). This is because the end of\n\
 iterator or master file is detected when reading past the end, not\n\
 iterator or master file is detected when reading past the end, not\n\
 when the last one is read.\n\
 when the last one is read.\n\
 ";
 ";
+
+const char* const ZoneLoader_getRRCount_doc = "\
+get_rr_count() -> integer\n\
+\n\
+Return the number of RRs loaded.\n\
+\n\
+This method returns the number of RRs loaded via this loader by the\n\
+time of the call. Before starting the load it will return 0. It will\n\
+return the total number of RRs of the zone on and after completing the\n\
+load.\n\
+\n\
+Exceptions:\n\
+  None\n\
+\n\
+";
+
+const char* const ZoneLoader_getSize_doc = "\
+get_size() -> integer\n\
+\n\
+Return the (estimated) total size of the entire zone.\n\
+\n\
+This method returns some hint on how large the zone will be when\n\
+completing the load. The returned size is a conceptual value that can\n\
+internally mean anything. The intended usage of the value is to\n\
+compare it to the return value of get_position() to estimate the\n\
+progress of the load at the time of the call.\n\
+\n\
+In this implementation, if the loader is constructed with a file name,\n\
+the returned size is the size of the zone file. If it includes other\n\
+files via the $INCLUDE directive, it will be the sum of the file sizes\n\
+of all such files that the loader has handled. Note that it may be\n\
+smaller than the final size if there are more files to be included\n\
+which the loader has not seen by the time of the call.\n\
+\n\
+Currently, if the loader is constructed with another data source\n\
+client, this method always returns 0. In future, it may be possible to\n\
+return something more effective, e.g, the total number of RRs if the\n\
+underlying data source can provide that information efficiently.\n\
+\n\
+In any case, the caller shouldn't assume anything specific about the\n\
+meaning of the value other than for comparing it to the result of\n\
+get_position().\n\
+\n\
+Exceptions:\n\
+  None\n\
+\n\
+";
+
+const char* const ZoneLoader_getPosition_doc = "\
+get_position() -> integer\n\
+\n\
+Return the current position of the loader in the zone being loaded.\n\
+\n\
+This method returns a conceptual \"position\" of this loader in the\n\
+loader relative to the return value of get_size(). Before starting the\n\
+load the position is set to 0; on successful completion, it will be\n\
+equal to the get_size() value; in the middle of the load, it's\n\
+expected to be between these values, which would give some hint about\n\
+the progress of the loader.\n\
+\n\
+In the current implementation, if the loader is constructed with a\n\
+file name, the returned value is the number of characters from the\n\
+zone file (and any included files) recognized by the underlying zone\n\
+file parser.\n\
+\n\
+If it's constructed with another data source client, it's always 0 for\n\
+now; however, if get_position() is extended in this case as documented\n\
+(see the method description), the result of get_rr_count() could be\n\
+used for the current position.\n\
+\n\
+Like get_size(), the value is conceptual and the caller shouldn't\n\
+assume any specific meaning of the value except for comparing it to\n\
+get_size() results.\n\
+\n\
+Exceptions:\n\
+  None\n\
+\n\
+";
 } // unnamed namespace
 } // unnamed namespace

+ 23 - 0
src/lib/python/isc/datasrc/zone_loader_python.cc

@@ -187,6 +187,24 @@ ZoneLoader_loadIncremental(PyObject* po_self, PyObject* args) {
     }
     }
 }
 }
 
 
+PyObject*
+ZoneLoader_getRRCount(PyObject* po_self, PyObject*) {
+    s_ZoneLoader* self = static_cast<s_ZoneLoader*>(po_self);
+    return (Py_BuildValue("I", self->cppobj->getRRCount()));
+}
+
+PyObject*
+ZoneLoader_getSize(PyObject* po_self, PyObject*) {
+    s_ZoneLoader* self = static_cast<s_ZoneLoader*>(po_self);
+    return (Py_BuildValue("I", self->cppobj->getSize()));
+}
+
+PyObject*
+ZoneLoader_getPosition(PyObject* po_self, PyObject*) {
+    s_ZoneLoader* self = static_cast<s_ZoneLoader*>(po_self);
+    return (Py_BuildValue("I", self->cppobj->getPosition()));
+}
+
 // This list contains the actual set of functions we have in
 // This list contains the actual set of functions we have in
 // python. Each entry has
 // python. Each entry has
 // 1. Python method name
 // 1. Python method name
@@ -197,6 +215,11 @@ PyMethodDef ZoneLoader_methods[] = {
     { "load", ZoneLoader_load, METH_NOARGS, ZoneLoader_load_doc },
     { "load", ZoneLoader_load, METH_NOARGS, ZoneLoader_load_doc },
     { "load_incremental", ZoneLoader_loadIncremental, METH_VARARGS,
     { "load_incremental", ZoneLoader_loadIncremental, METH_VARARGS,
       ZoneLoader_loadIncremental_doc },
       ZoneLoader_loadIncremental_doc },
+    { "get_rr_count", ZoneLoader_getRRCount, METH_NOARGS,
+      ZoneLoader_getRRCount_doc },
+    { "get_size", ZoneLoader_getSize, METH_NOARGS, ZoneLoader_getSize_doc },
+    { "get_position", ZoneLoader_getPosition, METH_NOARGS,
+      ZoneLoader_getPosition_doc },
     { NULL, NULL, 0, NULL }
     { NULL, NULL, 0, NULL }
 };
 };