BIND 10 #3007: Develop NameChangeRequest class
BIND 10 Development
do-not-reply at isc.org
Mon Jul 1 19:28:52 UTC 2013
#3007: Develop NameChangeRequest class
-------------------------------------+-------------------------------------
Reporter: tmark | Owner:
Type: enhancement | marcin
Priority: medium | Status:
Component: dhcp-ddns | reviewing
Keywords: | Milestone:
Sensitive: 0 | Sprint-DHCP-20130703
Sub-Project: DHCP | Resolution:
Estimated Difficulty: 0 | CVSS Scoring:
Total Hours: 0 | Defect Severity: N/A
| Feature Depending on Ticket:
| Add Hours to Ticket: 0
| Internal?: 0
-------------------------------------+-------------------------------------
Changes (by tmark):
* owner: tmark => marcin
Comment:
Replying to [comment:8 marcin]:
> Replying to [comment:7 tmark]:
> > Replying to [comment:6 marcin]:
> > > Reviewed commit b4b1eca7131cedca72a8973718881c1f18d2010f
> > >
> > > '''General'''
> > > The naming if the class and files is not consistent with naming of
other files, which are prefixed with !''d2_!'' or !''d_!''. Can you please
clarify once again what the selected naming convention for the files in d2
is?
> >
> > The "d_" are base classes independent of DHCP-DDNS, that actually form
the basis for a BIND10 module framework if you will.
> >
> > The "d2_" are larger grained classes specific to DHCP-DDNS, that are
typically derived from the "d_" framework.
> >
> > NameChangeRequest as a class name originates in the D2 design. I
wanted the file names to reflect the class. And while this message is
specific to DHCP-DDNS, its more along the lines of a "package" or library
used by D2. Besides if all of the source files started with "d2_"
> > then what would be the point?
>
> There is no point now. In the light of what you said here, it seems I
could have called d2_update_message class UpdateMessage or DNSUpdate. I
think understood wrong the naming conventions from our discussions on
jabber.
>
> >
> > Your d2_update_message.* could easily have been called dns_update.*,
as they really are not specific to DHPC-DDNS.
>
> Agree.
>
> >
> >
> >
> > > !NameChangeType, !NameChangeStatus, !NameChangeFormat: enumerator
type values should be in upper case.
> > >
> > > Also, why do you initialize the first enum value to 1 explicitly?
There is usually no need to explicitly initialize enumerators unless you
want to iterate on them like on regular integers. On the other hand, even
if this is the case, this may be unsafe, because compilers would not
guarantee that the other enumerator values will be assigned: 2, 3, 4, etc.
> > >
> >
> > Ok, I looked it up in the coding guidelines, we are both right and
both wrong.
> > Apparently they are suppose to be like this:
> >
> > enum EnumName {
> > FOO,
> > BAR
> > } enum_instance;
> >
> > and without specific values unless necessary. One of the reasons I
like
> > non-zero values, is that the values look more intentional at run time.
Is it 0 or uninitialized? No matter, I'll adhere to the guideline.
>
> IMO, the point of enums is to have named (instead of raw ints) values.
If you need an additional state meaining !''uninitialized!'' you can
always introduce the relevant value, say UNINITIALIZED.
>
> <snip>
>
> > >
> > > a private member: !''brief!'' tag should start with lower case
letter
> >
> > Oops again.
> >
>
> It is still there - see line 104.
This time I REALLY got it.
>
>
> <snip>
>
> > > NameChangeRequest constructor: Theoretically, all constructor
arguments could be declared const because constructor does not modify them
(it probably shouldn't).
> >
> > There is no point in declaring a primitive const.
> >
>
> There is. If you don't intend to get arguments modified by your
function, declaring them const guarantees that it is caught in the
compilation time if you do. I agree it is not as big important as in case
of references but... what is the point in not declaring them const if they
are not modified?
>
> Also, conding guidelines mandate it:
http://bind10.isc.org/wiki/CodingGuidelines#Consts
So they do. Fixed all over.
>
> <snip>
>
> > > NameChangeRequest::fromFormat: please consider providing default
value for the !''format!'' argument because it sounds that we will be
using JSON it most of the time. Also !''format!'' could be declared const.
> > >
> >
> > I would prefer not to supply a default. Reading through code and
seeing this "fromFormat(FMT_JSON, some_buffer)" leaves no room to wonder
about the intent, compared to "fromFormat(ome_buffer)". It is better for
the interface to insist on clear intent from the developer.
>
> Fair enough.
>
> >
> > Again, why const a primitive?
>
> See above.
Fixed.
>
> <snip>
>
> > >
> > > For both functions above: in the doxygen comments there is no need
to say:
> > > {{{
> > > @return returns a ...
> > > }}}
> > > I could be:
> > > {{{
> > > @return a
> > > }}}
> > > because the tag itself says that the comment is about returning a
value.
> >
> > Ok, but if I don't include them, Stephen will tell me they are
missing.
> >
> Hm.... that's fair enough, but I don't recall such a comment from
Stephen with regards to any other code. But, this is a minor issue, so I
leave it up to you.
>
> <snip>
>
> > > private member fqdn_ and ip_address_: I am wondering if more
specialized type could be selected for these members. For example, for the
fqdn_ it could be !''isc::dns::Name!'', for the other one it could be
!''isc::asiolink::ip_address!''. They have the functionality to validate
whether the given value is a valid name or IP address.
> > >
> >
> > Addressed below.
> >
>
> <snip>
>
> > > '''ncr_msg.cc'''
> > > D2Dhcid::fromStr: this implementation is overly complicated. Similar
problem is addressed in src/lib/dhcp/option_data_types.cc, function
writeBinary.
> > >
> > > D2Dhcid::toStr: In !''util::encode!'', there are suitable functions
to implement this easier.
> > >
> >
> > Changed to use util::encode. (While the impl I had might have seemed
overly complicated it is extremely fast. I will bet you money that the
util::encode is much, much slower.)
>
> Perhaps it is slower, but when programming in C++ there is always a
tradeoff between complexity and performance. Utilities are implemented and
we use them in various places of the code to make code simpler. If they
are slow, we could modify them rather than duplicate functionality.
>
> <snip>
>
> > >
> > > NameChangeRequest::toFormat: There should be no new line between
!''switch (format)!'' and !''{!''
>
> This was not addressed.
Sorry, I did one, and then got distracted.
>
> > >
> > > NameChangeRequest::toJSON: Instead of accesing class members
directly (such as change_type_, forward_change_ etc), it would be better
to use appropriate accessors of the class. Currently, they are one-liners
so they will probably be inlined by the compiler and thus it should not
affect performance.
> > >
> >
> > Overkill, but if it makes you happy.
> >
>
> That was just a suggestion. There are certain pieces of review which can
be address optionally if there is a reason for it. Overkill may be a good
reason to NOT do something :-)
>
> >
> > > NameChangeRequest::validateContent: The check on FQDN is not
sufficient. The FQDN has a defined structure which should be followed. For
example, something like !''example...com!'' is not a valid FQDN but will
pass this function. I would rather suggest to use the !''isc::dns::Name!''
class to validate FQDNs. If it is however intended that the detailed check
is done on the DnsClient level, before sending a packet to DNS, it should
be noted as a comment. Nevertheless, I believe it should be well validated
here.
> > >
> > > Although, I haven't had time to go into details of DHCID, the RFC
4701 presents certain formats of DHCID. It may be good for now to check
that the DHCID is not empty, but ultimately, we would like to have a DHCID
which would be capable to verify that DHCID is valid or at least certain
part of it is valid. Please consider adding a suitable @todo comment into
this function.
> > >
> > >
> >
> > I agree that there is more validation that we could and should do. I
had considered using dns:DHCID but it carries a long a lot of extra
functionality and In the interests of getting D2 up on its feet I
deferred more detailed decisions like this and opted for a somewhat
lighter path.
> >
> > I will mark using Name and DHCID and expanding validation with TODOs.
There is still a great deal of work to do and there are larger concerns at
the moment.
>
> @TODO should be replaced with @todo, otherwise doxygen will complain.
Fixed.
>
> >
> >
> > > NameChangeRequest::setChangeType: Some compilers issue warnings when
curly brackets are not used in expressions like this one:
> > > {{{
> > > if (raw_value != chgAdd && raw_value != chgRemove) {
> > > }}}
> > >
> > > Please consider this:
> > > {{{
> > > if ((raw_value != chgAdd) && (raw_value != chgRemove)) {
> > > }}}
> >
> > Done. BTW, those are not "curly brackets" they are parens.
> >
>
> Sorry, I have learnt that from the Coding Guidelines where they use the
term !''curly braces!''. But it doesn't explain why I referred to it as
!''brackets!'' :-)
>
> <snip>
>
> > > '''ncr_unittests.cc'''
> > > NameChangeRequestTest::constructionTests: this whole test is memory
leak prone. Tests are passing if constructors throw exceptions. However,
please consider the following scenario:
> >
> > >
> > > ''Suppose there is a bug in implementation of the constructor which
allows blank FQDNs. In this case the following call:
> > > {{{
> > > EXPECT_THROW(
> > > new NameChangeRequest(chgAdd, true, true, "", "192.168.1.101",
dhcid, expiry, 1300),
> > > NcrMessageError
> > > )
> > > }}}
> > > will not trigger exception and the object will be successfully
created!
> > > Test will happily proceed to the next check, leaving the object on
the heap. You can simulate such scenario by changing FQDN to non-empty
value for a moment and running unit test through valgrind. The memory leak
is reported.
> > > In order to prevent it, please consider using boost::scoped_ptr to
automatically release the object.
> > >
> >
> > Ok, I see your point and I have done as suggested. I wasn't that
mindful with it being unit test code.
>
> Changes look ok. On reflection, I think it would be even better not to
use pointers at all:
> {{{
> EXPECT_THROW(NameChangeRequest(CHG_ADD, true, true, "",
> "192.168.1.101", dhcid, expiry, 1300),
> NcrMessageError);
>
> }}}
>
> instead of:
>
> {{{
> EXPECT_THROW(ncr.reset(new NameChangeRequest(CHG_ADD, true, true, "",
> "192.168.1.101", dhcid, expiry, 1300)), NcrMessageError);
> }}}
>
> but I am also fine with the current solution.
I agree. Should have done it that way the first time. Have changed it to
pointerless approach.
>
>
>
> >
> > > NameChangeRequestTest::dhcidTest: a slightly clearer way to
initialize !''expected_bytes!'' could be:
> > > {{{
> > > const uint8_t bytes[] = { 0x1, 0x2, 0x3, 0x4, 0xA, 0x7F, 0x8E, 0x3D
};
> > > std::vector<uint8_t>(bytes, bytes + sizeof(bytes) - 1);
> > > }}}
> >
> > Oy vey.
>
> Neat pick: There should be spaces sourrounding !''+!'' in std::equal.
>
> <snip>
>
> >
> > > Can you please suggest a !ChangeLog entry?
> >
> > ChangeLog:
> >
> > xxx [func] [tmark]
> > Added initial implementation of NameChangeRequest,
> > which embodies DNS update requests sent to DHCP-DDNS
> > by its clients.
> > (trac3007 git TBD)
> >
> >
> >
>
>
> The !ChangeLog looks fine.
>
>
> I apologize, I missed those in the previous round of review...
>
> invalidMsgChecks, validMsgChecks: Why not do the following:
> {{{
> TEST(NameChangeRequestTest, invalidMsgChecks) {
> // Iterate over the list of JSON strings, attempting to create a
> // NameChangeRequest. The attempt should throw a NcrMessageError.
> int num_msgs = sizeof(invalid_msgs)/sizeof(char*);
> for (int i = 0; i < num_msgs; i++) {
> EXPECT_THROW(NameChangeRequest::fromJSON(invalid_msgs[i]),
> NcrMessageError);
> }
> }
> }}}
I structured so it would tell you which one it failed on.
I have changed to use your structure and the "<<" for the additional
diagnostics.
>
>
> Also, please check whitespaces in: ncr_msg.h and ncr_msg_unittests.cc.
There are spurious spaces at the end of line in a few places.
Sorry, I have to remember to double check for those.
>
> The following doxygen errors are reported:
> {{{
> /home/marcin/devel/bind10/src/bin/d2/ncr_msg.cc:69: warning: no matching
class member found for
> isc::d2::NameChangeRequest::NameChangeRequest(isc::d2::NameChangeType
change_type, bool forward_change, bool reverse_change, const std::string
&fqdn, const std::string &ip_address, const isc::d2::D2Dhcid &dhcid, const
ptime &lease_expires_on, uint32_t lease_length)
> Possible candidates:
> isc::d2::NameChangeRequest::NameChangeRequest()
> isc::d2::NameChangeRequest::NameChangeRequest(NameChangeType
change_type, bool forward_change, bool reverse_change, const std::string
&fqdn, const std::string &ip_address, const D2Dhcid &dhcid, const
boost::posix_time::ptime &lease_expires_on, uint32_t lease_length)
>
> /home/marcin/devel/bind10/src/bin/d2/ncr_msg.cc:402: warning: no
matching class member found for
> void isc::d2::NameChangeRequest::setLeaseExpiresOn(const ptime &value)
> Possible candidates:
> void isc::d2::NameChangeRequest::setLeaseExpiresOn(const
boost::posix_time::ptime &value)
> void isc::d2::NameChangeRequest::setLeaseExpiresOn(const std::string
&value)
> void
isc::d2::NameChangeRequest::setLeaseExpiresOn(isc::data::ConstElementPtr
element)
>
> ...
>
> /home/marcin/devel/bind10/src/bin/d2/ncr_msg.h:137: warning: argument
'ptime' of command @param is not found in the argument list of
isc::d2::NameChangeRequest::NameChangeRequest(NameChangeType change_type,
bool forward_change, bool reverse_change, const std::string &fqdn, const
std::string &ip_address, const D2Dhcid &dhcid, const
boost::posix_time::ptime &lease_expires_on, uint32_t lease_length)
> /home/marcin/devel/bind10/src/bin/d2/ncr_msg.h:137: warning: The
following parameters of
isc::d2::NameChangeRequest::NameChangeRequest(NameChangeType change_type,
bool forward_change, bool reverse_change, const std::string &fqdn, const
std::string &ip_address, const D2Dhcid &dhcid, const
boost::posix_time::ptime &lease_expires_on, uint32_t lease_length) are not
documented:
> parameter 'lease_expires_on'
> /home/marcin/devel/bind10/src/bin/d2/ncr_msg.h:348: warning: argument
'string' of command @param is not found in the argument list of
isc::d2::NameChangeRequest::setDhcid(const std::string &value)
> /home/marcin/devel/bind10/src/bin/d2/ncr_msg.h:348: warning: The
following parameters of isc::d2::NameChangeRequest::setDhcid(const
std::string &value) are not documented:
> parameter 'value'
> /home/marcin/devel/bind10/src/bin/d2/ncr_msg.h:229: warning: Found
unknown command `\TODO'
> /home/marcin/devel/bind10/src/lib/datasrc/sqlite3_accessor.cc:899:
warning: The following parameters of
isc::datasrc::SQLite3Accessor::DiffContext::DiffContext(const
boost::shared_ptr< const SQLite3Accessor > &accessor, int zone_id,
uint32_t start, uint32_t end) are not documented:
> parameter 'accessor'
>
> ...
>
> }}}
>
> In order to reproduce it:
> {{{
> cd doc
> make devel
> less html/doxygen-error.log
> }}}
>
Issues with ncr_msg.cc and ncr_msg.h are corrected. There are others for
d2_ files, which I'll address as they are worked.
I do not want to mix them in with this ticket. Now that I know about
this, I'll do it going forward.
--
Ticket URL: <https://bind10.isc.org/ticket/3007#comment:9>
BIND 10 Development <http://bind10.isc.org>
BIND 10 Development
More information about the bind10-tickets
mailing list