Browse Source

[2094] overall documentation update

JINMEI Tatuya 12 years ago
parent
commit
fc772a408b

+ 1 - 1
src/lib/datasrc/Makefile.am

@@ -64,7 +64,7 @@ libdatasrc_la_LIBADD = $(top_builddir)/src/lib/exceptions/libexceptions.la
 libdatasrc_la_LIBADD += $(top_builddir)/src/lib/dns/libdns++.la
 libdatasrc_la_LIBADD += $(top_builddir)/src/lib/log/liblog.la
 libdatasrc_la_LIBADD += $(top_builddir)/src/lib/cc/libcc.la
-libdatasrc_la_LIBADD += memory/libdatasrc_memory.la
+libdatasrc_la_LIBADD += memory/libdatasrc_memory.la # convenience library
 libdatasrc_la_LIBADD += $(SQLITE_LIBS)
 
 BUILT_SOURCES = datasrc_config.h datasrc_messages.h datasrc_messages.cc

+ 42 - 19
src/lib/datasrc/memory/rdata_encoder.cc

@@ -38,27 +38,41 @@ namespace datasrc {
 namespace memory {
 
 namespace {
+/// Specification of a single RDATA field in terms of internal encoding.
 struct RdataFieldSpec {
     enum FieldType {
-        FIXEDLEN_DATA = 0,
-        VARLEN_DATA,
-        DOMAIN_NAME
+        FIXEDLEN_DATA = 0,      // fixed-length data field
+        VARLEN_DATA,            // variable-length data field
+        DOMAIN_NAME             // domain name
     };
         
-    FieldType type;
+    const FieldType type;       // field type
+
+    // type specific data.  We use a union so it'll be clear only one of them
+    // (determined by the type) is valid.  Since we want to make it as
+    // lightweight as possible, we use a relatively lower-level primitives
+    // here.
     union {
-        uint16_t fixeddata_len;
-        RdataNameAttributes name_attributes;
+        // The length of fixed-length data field.  Only valid for FIXEDLEN_DATA
+        const uint16_t fixeddata_len;
+
+        // Attributes of the name.  Only valid for DOMAIN_NAME.
+        const RdataNameAttributes name_attributes;
     };
 };
 
+/// Specification of RDATA in terms of internal encoding.
 struct RdataEncodeSpec {
-    uint16_t field_count;
-    uint16_t name_count;
-    uint16_t varlen_count;
-    const RdataFieldSpec* fields;
+    const uint16_t field_count; // total number of fields (# of fields member)
+    const uint16_t name_count;  // number of domain name fields
+    const uint16_t varlen_count; // number of variable-length data fields
+    const RdataFieldSpec* const fields; // list of field specs
 };
 
+// These constants are convenient shortcut to initialize the name_attributes
+// member of RdataFieldSpec (since it's a union, we can only directly
+// initialize fixeddata_len member, so we need to convert it to its type).
+// These are essentially small integers, so the cast should be safe.
 const uint16_t NAMEATTR_NOATTRIBUTE_INITIALIZER = static_cast<uint16_t>(0);
 const uint16_t NAMEATTR_COMPRESSIBLE_INITIALIZER =
     static_cast<uint16_t>(NAMEATTR_COMPRESSIBLE);
@@ -67,33 +81,33 @@ const uint16_t NAMEATTR_ADDITIONAL_INITIALIZER =
 const uint16_t NAMEATTR_COMPADDITIONAL_INITIALIZER =
     static_cast<uint16_t>(NAMEATTR_COMPRESSIBLE | NAMEATTR_ADDITIONAL);
 
-// TBD
+// Many types of RDATA can be treated as a single-field, variable length
+// field (in terms of our encoding).  The following define such most general
+// form of field spec.
 const RdataFieldSpec generic_data_fields[] = {
     {RdataFieldSpec::VARLEN_DATA, {0}}
 };
 const uint16_t n_generic_data_fields =
     sizeof(generic_data_fields) / sizeof(RdataFieldSpec);
-
-// Most general form of field spec: that consisting of single variable-len
-// data field.
 const RdataEncodeSpec generic_data_spec = {
     n_generic_data_fields, 0, 1, generic_data_fields
 };
 
-// TBD
+// RDATA consist of a single IPv4 address field.
 const RdataFieldSpec single_ipv4_fields[] = {
     {RdataFieldSpec::FIXEDLEN_DATA, {sizeof(uint32_t)}}
 };
 const uint16_t n_ipv4_fields =
     sizeof(single_ipv4_fields) / sizeof(RdataFieldSpec);
 
+// RDATA consist of a single IPv6 address field.
 const RdataFieldSpec single_ipv6_fields[] = {
     {RdataFieldSpec::FIXEDLEN_DATA, {16}} // 128bits = 16 bytes
 };
 const uint16_t n_ipv6_fields =
     sizeof(single_ipv6_fields) / sizeof(RdataFieldSpec);
 
-// TBD
+// There are several RR types that consist of a single domain name.
 const RdataFieldSpec single_noattr_name_fields[] = {
     {RdataFieldSpec::DOMAIN_NAME, {NAMEATTR_NOATTRIBUTE_INITIALIZER}}
 };
@@ -119,8 +133,7 @@ const RdataFieldSpec double_noattr_name_fields[] = {
 const uint16_t n_double_name_fields =
     sizeof(double_compressible_name_fields) / sizeof(RdataFieldSpec);
 
-
-// SOA specific: two compressible names + 20-byte data
+// SOA specific: two compressible names + 5*32-bit data
 const RdataFieldSpec soa_fields[] = {
     {RdataFieldSpec::DOMAIN_NAME, {NAMEATTR_COMPRESSIBLE_INITIALIZER}},
     {RdataFieldSpec::DOMAIN_NAME, {NAMEATTR_COMPRESSIBLE_INITIALIZER}},
@@ -165,7 +178,10 @@ const RdataFieldSpec nsec_fields[] = {
 };
 const uint16_t n_nsec_fields = sizeof(nsec_fields) / sizeof(RdataFieldSpec);
 
-// Class IN encode specs
+// Class IN encode specs.  This gives a shortcut to the encode spec for
+// some well-known types of RDATA specific to class IN (most of which are
+// generic and can be used for other classes).  The array index is the
+// RR type code.
 const RdataEncodeSpec encode_spec_list_in[] = {
     generic_data_spec,                         // #0: (NONE)
     {n_ipv4_fields, 0, 0, single_ipv4_fields},   // #1: A
@@ -213,6 +229,7 @@ const RdataEncodeSpec encode_spec_list_in[] = {
     // least for currently supported RR types.
 };
 
+// # of entries in encode_spec_list_in
 const size_t encode_spec_list_in_size =
     sizeof(encode_spec_list_in) / sizeof(encode_spec_list_in[0]);
 BOOST_STATIC_ASSERT(encode_spec_list_in_size == 48);
@@ -220,12 +237,16 @@ BOOST_STATIC_ASSERT(encode_spec_list_in_size == 48);
 inline
 const RdataEncodeSpec&
 getRdataEncodeSpec(RRClass rrclass, RRType rrtype) {
+    // Special case: for classes other than IN, we treat RDATA of RR types
+    // that are class-IN specific as generic opaque data.
     if (rrclass != RRClass::IN() &&
         (rrtype == RRType::A() || rrtype == RRType::AAAA() ||
          rrtype == RRType::SRV())) {
         return (generic_data_spec);
     }
 
+    // Otherwise, if the type is in the pre-defined range, we use the defined
+    // spec; otherwise we treat it as opaque data.
     const uint16_t typecode = rrtype.getCode();
     if (typecode < encode_spec_list_in_size) {
         return (encode_spec_list_in[rrtype.getCode()]);
@@ -247,6 +268,7 @@ getNAPTRDataLen(const rdata::Rdata& rdata) {
 }
 } // end of unnamed namespace
 
+namespace testing {
 void
 encodeRdata(const rdata::Rdata& rdata, RRClass rrclass, RRType rrtype,
             vector<uint8_t>& data_result, vector<uint16_t>& len_result)
@@ -352,6 +374,7 @@ foreachRdataField(RRClass rrclass, RRType rrtype,
     assert(name_count == encode_spec.name_count);
     assert(varlen_count == encode_spec.varlen_count);
 }
+} // namespace testing
 
 } // namespace memory
 } // namespace datasrc

+ 33 - 2
src/lib/datasrc/memory/rdata_encoder.h

@@ -28,23 +28,54 @@ namespace isc {
 namespace datasrc {
 namespace memory {
 
+/// \brief Attributes of domain name fields of encoded RDATA.
+///
+/// The enum values define special traits of the name that can affect how
+/// it should be handled in rendering or query processing.
 enum RdataNameAttributes {
-    NAMEATTR_COMPRESSIBLE = 1,
-    NAMEATTR_ADDITIONAL = (NAMEATTR_COMPRESSIBLE << 1)
+    NAMEATTR_COMPRESSIBLE = 1,  ///< Name should be compressed when rendered
+    NAMEATTR_ADDITIONAL = (NAMEATTR_COMPRESSIBLE << 1) ///< Name requires
+                                                      ///< Additional section
+                                                      ///< handling
 };
 
+// We use the following quick-hack version of encoder and "foreach"
+// operator until we implement the complete versions.  The plan is to
+// update the test cases that use these functions with the complete
+// functions/classes, and then remove the entire namespace.
+namespace testing {
+// "Encode" given RDATA of given RR class and type.
+//
+// Fixed/variable-length data fields are encoded in their wire-format;
+// domain names are encoded in the form of:
+//  - nlen: name data length (1 byte)
+//  - olen: offset data length (1 byte)
+//  - name data (nlen bytes)
+//  - offset data (olen bytes)
+//
+// The encoded results are appended to data_result.
+// If the RDATA contain variable-length data fields, the lengths of the
+// these fields will be appended in len_result, in the order of appearance.
 void encodeRdata(const dns::rdata::Rdata& rdata, dns::RRClass rrclass,
                  dns::RRType rrtype, std::vector<uint8_t>& data_result,
                  std::vector<uint16_t>& len_result);
 
+// Callbacks used in foreachRdataField.
 typedef boost::function<void(const dns::LabelSequence&,
                              RdataNameAttributes)> NameCallback;
 typedef boost::function<void(const uint8_t*, size_t)> DataCallback;
 
+// Iterate over each RDATA field (in terms of the internal encoding) stored
+// in encoded_data, and call the given callback for each data (for
+// domain name fields, name_callback will be called; for normal data fields
+// data_callback will be called).  If the encoded data contain variable-length
+// data fields, varlen_list should store a sequence of their lengths, in the
+// of the appearance.
 void foreachRdataField(dns::RRClass rrclass, dns::RRType rrtype,
                        const std::vector<uint8_t>& encoded_data,
                        const std::vector<uint16_t>& varlen_list,
                        NameCallback name_callback, DataCallback data_callback);
+}
 
 } // namespace memory
 } // namespace datasrc

+ 22 - 3
src/lib/datasrc/memory/tests/rdata_encoder_unittest.cc

@@ -34,18 +34,25 @@
 using namespace isc::dns;
 using namespace isc::dns::rdata;
 using namespace isc::datasrc::memory;
+using namespace isc::datasrc::memory::testing;
 
 using isc::util::unittests::matchWireData;
 using std::string;
 using std::vector;
 
 namespace {
+// This defines a tuple of test data used in test_rdata_list below.
 struct TestRdata {
-    const char* const rrclass;
-    const char* const rrtype;
-    const char* const rdata;
+    const char* const rrclass;  // RR class, textual form
+    const char* const rrtype;   // RR type, textual form
+    const char* const rdata;    // textual RDATA
     const size_t n_varlen_fields; // expected # of variable-len fields
 };
+
+// This test data consist of all supported types of RDATA (+ some
+// unusual and corner cases).  We'll construct corresponding Rdata
+// object from this, and compare its wire format data both generated
+// by normal libdns++ interface and via encoding conversion.
 const TestRdata test_rdata_list[] = {
     {"IN", "A", "192.0.2.1", 0},
     {"IN", "NS", "ns.example.com", 0},
@@ -85,6 +92,8 @@ const TestRdata test_rdata_list[] = {
     {NULL, NULL, NULL, 0}
 };
 
+// The following two functions will be used to generate wire format data
+// from encoded representation of each RDATA.
 void
 renderNameField(MessageRenderer* renderer, bool additional_required,
                 const LabelSequence& labels, RdataNameAttributes attributes)
@@ -102,12 +111,22 @@ renderDataField(MessageRenderer* renderer, const uint8_t* data,
 }
 
 TEST(RdataFieldSpec, checkData) {
+    // These two names will be rendered before and after the test RDATA,
+    // to check in case the RDATA contain a domain name whether it's
+    // compressed or not correctly.  The names in the RDATA should basically
+    // a subdomain of example.com, so it can be compressed due to dummy_name.
+    // Likewise, dummy_name2 should be able to be fully compressed due to
+    // the name in the RDATA.
     const Name dummy_name("com");
     const Name dummy_name2("example.com");
+
     MessageRenderer expected_renderer, actual_renderer;
     vector<uint8_t> encoded_data;
     vector<uint16_t> varlen_list;
 
+    // The set of RR types that require additional section processing.
+    // We'll pass it to renderNameField to check the stored attribute matches
+    // our expectation.
     std::set<RRType> need_additionals;
     need_additionals.insert(RRType::NS());
     need_additionals.insert(RRType::MX());