BIND 10 #2431: support flexible ordering/appearance of TTL, type and class in dns::MasterLoader
BIND 10 Development
do-not-reply at isc.org
Fri Dec 14 23:15:24 UTC 2012
#2431: support flexible ordering/appearance of TTL, type and class in
dns::MasterLoader
-------------------------------------+-------------------------------------
Reporter: jinmei | Owner:
Type: task | jinmei
Priority: medium | Status:
Component: libdns++ | reviewing
Keywords: | Milestone:
Sensitive: 0 | Sprint-20121218
Sub-Project: DNS | Resolution:
Estimated Difficulty: 5 | CVSS Scoring:
Total Hours: 0 | Defect Severity: N/A
| Feature Depending on Ticket:
| loadzone-ng
| Add Hours to Ticket: 0
| Internal?: 0
-------------------------------------+-------------------------------------
Comment (by jinmei):
'''master_loader.cc (major)'''
Overall it seems to do what it's expected to do, but I have several
suggestions and concerns.
- I'd like to avoid calling ungetToken() when possible. It's not
super cheap for strings. On a closer look, I found we should be
able to use the specific-token-type version of `getNextToken` and
avoid ungetToken() (for valid input). At least there should be a
string token for RR type, so, from the candidate of TTL/class
through RR type, we can safely use this version of `getNextToken`.
- Secondly, considering named-signzone output (always add explicit
TTL, and add it first; omit class for some), I think we should check
TTL first (BIND 9 checks the class first, but I'm not sure why).
Depending on the overhead of the case the try fails (see below),
this can affect the overall performance substantially.
- IMO the code added in this branch makes `loadIncremental` too
big and unreadable, and should better be delegated to a helper
method.
- On a related note, for RR class we only have to do check when
explicitly specified; because we know what we should use:
zone_class_.
I'm attaching a diff implementing these ideas. Please take a look.
If you think it makes sense, please incorporate it with adding more
comments and more cleanups.
Finally, a possibly controversial point. As you may have noticed in
your review on #2429, I'm concerned about exception overhead when the
try-and-error detection for TTL (and RRclass):
{{{#!cpp
try {
rrclass.reset(new RRClass(rrparam_token.getString()));
rrparam_token = lexer_.getNextToken();
} catch (const InvalidRRClass&) {
// If it's not an rrclass here, continue and try again
// after the TTL below.
}
...
try {
rrclass.reset(new RRClass(rrparam_token.getString()));
rrparam_token = lexer_.getNextToken();
} catch (const InvalidRRClass&) {
// If it's not an rrclass here, use the zone's class.
rrclass.reset(new RRClass(zone_class_));
}
}}}
This is particularly so for RR class as it's often omitted in actual
zone files (in that case we'll encounter two exceptions in your
original code). I'm also concerned about the overhead of `new`ing
the RRClass for every RR. One may argue it's premature optimization,
but if you agree with me, I'd suggest doing something similar to what
I did in #2431: introduce a "no throw" (and still minimizing
resource allocation) version of `RRClass` factory:
{{{
RRClass*
RRClass::createFromText(const string& rrclass_txt, RRClass* placeholder);
}}}
and maintain a placeholder object within `MasterLoader` so we only
have to `new` it once in the lifetime of the loader.
And, in that case, my specific suggestion is to merge the branch
without this particular optimization (while addressing other issues),
leave the ticket open, and complete it in the second phase. (I don't
like to delay our meta goal for this optimization, but I'm afraid the
optimization part won't be taken if we defer it to a separate ticket.)
'''master_loader.cc (minor)'''
- reference to exceptions in `catch` should be constified. I've
noticed this is a common point I'd have to in your code. Maybe you
want to include it in your personal (imaginary) check list. That
can be even be statically checked by a simple script. cppcheck also
generally complains about it, so running cppcheck before asking for
a review would also be a good practice. This is trivial and I fixed
it my self.
- also, variables are not necessary in `catch` if you don't need them
{{{#!cpp
} catch (const InvalidRRClass& e) { // <= no need to define
'e'
// If it's not an rrclass here, continue and try again
// after the TTL below.
}
}}}
'''master_loader_unittest.cc'''
- I'd suggest providing expected error message in `error_cases` like
the TTL-related cases do. Invalid input could fail in various ways,
so if we don't check the actual message tests can still pass even if
the error is detected in a different way than we actually intend.
- ""Invalid Rdata" is not really accurate:
{{{#!cpp
{ "www A IN 3600 192.168.2.8", NULL,
"Invalid Rdata (incorrect order of class, TTL and type)" },
}}}
In fact, the "Rdata" is valid here. If we want to keep the "Invalid
XXX" phrase, it should be "RR". But I'd rather simply say
"Incorrect order of class, TTL and type". Same for other similar
cases.
- `ttlClassTypeOrder`: it repeats a certain amount of copy of the main
.cc source, and doesn't seem to be good in terms of DRY. Can't we
simply refer to the main source and/or be more concise here?
{{{#!cpp
// We test the order and lack of TTL, class and type. Both TTL and
// class are optional and may occur in any order if they exist. TTL
// and class come before type which must exist.
//
// [<TTL>] [<class>] <type> <RDATA>
// [<class>] [<TTL>] <type> <RDATA>
}}}
- There are some other invalid cases where we should test, like:
{{{
;; omit TTL and class, and missing RDATA
www A
;; other variations of missing token (check if it covers all cases):
www
www 3600
www IN
www 3600 IN
www IN 3600
www 3600 A
www IN A
www 3600 IN A
www IN 3600 A
}}}
--
Ticket URL: <http://bind10.isc.org/ticket/2431#comment:7>
BIND 10 Development <http://bind10.isc.org>
BIND 10 Development
More information about the bind10-tickets
mailing list