BIND 10 #1183: data source refactor refactor
BIND 10 Development
do-not-reply at isc.org
Thu Aug 18 22:53:36 UTC 2011
#1183: data source refactor refactor
-------------------------------------+-------------------------------------
Reporter: jelte | Owner: jinmei
Type: task | Status: reviewing
Priority: major | Milestone:
Component: data | Sprint-20110830
source | Resolution:
Keywords: | Sensitive: 0
Defect Severity: N/A | Sub-Project: DNS
Feature Depending on Ticket: | Estimated Difficulty: 0
Add Hours to Ticket: 0 | Total Hours: 0
Internal?: 0 |
-------------------------------------+-------------------------------------
Comment (by jinmei):
First, overall I like the new version.
Second, (as usual) I made some minor fixes/cleanups directly in the branch
(pushed).
'''database.h'''
- This is not really about this branch, but is this note for getNext()
true?
{{{
* \note The order of RRs is not strictly set, but the RRs for
single
* RRset must not be interleaved with any other RRs (eg. RRsets
must be
* "together").
}}}
At least the MockAccessor for the test doesn't seem to conform this
requirement, but the test still passes. And, in fact, we cannot
always assume this especially if we allow admins to update the DB
contents directly via DBMS.
On looking into the implementation further, we don't seem to need
this requirement: for the case of find(), addOrCreate() deals with
interleaved data. In case of full iteration, I suspect we shouldn't
care: xfrout, the would-be primary user of this interface, will
simply feed the result to the xfrout stream whether or not the data
is interleaved.
- Again, not really for this branch, but based on the "keep it dumb"
principle, the 'name' argument for getRecords() should be const
std::string&, not Name.
- Once again not really for this branch, but as commented the
static_cast<void> trick seems to be unnecessarily dirty. I guess we
can safely move the definition to .cc where we can omit the
parameters, and if it's correct, I'd suggest that. Further, if
getRecords() doesn't even work this accessor is mostly useless.
Personally I'd rather simply make it pure virtual (without
definition) and force the implementor to support it (or otherwise to
give up supporting this type of database). I actually also suspect
the same argument applies to getAllRecords(), but that may be a
different topic.
- I'd avoid hardcoding magic numbers like "all 5 elements" or "the
fifth column" (it's susceptible to future changes - consider we
deprecate SIGTYPE_COLUMN in a future version, for example). Instead
I'd
say, e.g.:
{{{
* getAllRecords(), all COLUMN_COUNT elements of the array are
overwritten.
* For a 'name iterator', created with getRecords(), the
NAME_COLUMN-th column
* is untouched, since what would be added here is by
* definition already known to the caller (it already passes it as
}}}
- On a related note: now that we pass the array in a securer way,
maybe we should make the definition of the size more consistent with
the array organization by defining it in the enum rather than via a
separate const variable? i.e., instead of
{{{
+ static const size_t COLUMN_COUNT = 5;
}}}
do this:
{{{
enum RecordColumns {
TYPE_COLUMN = 0, ///< The RRType of the record (A/NS/TXT etc.)
...
NAME_COLUMN = 4, ///< The domain name of this RR
COLUMN_COUNT = 5 ///< Must be the largest value of above + 1.
};
}}}
- getRecords: This doesn't seem to be correct:
{{{
* DatabaseAccessor's ZoneIterator. It can be created based on the
name
* or the ID (returned from getZone()), what is more comfortable for
the
* database implementation. Both are provided (and are guaranteed to
match,
* the DatabaseClient first looks up the zone ID and then calls this).
}}}
shouldn't this be "based on the name *and* the ID"? And, in that
sense, the rest of this paragraph doesn't make much sense to me
either.
- Likewise, the corresponding description for getAllRecords() doesn't
make much sense:
{{{
* DatabaseAccessor's ZoneIterator. It can be created based on the
name
* or the ID (returned from getZone()), what is more comfortable for
the
}}}
It doesn't take a "name" at all at the least.
'''sqlite3_accessor.cc'''
There doesn't seem to be anything obviously wrong, but I have some
comments about the design and implementation of
SQLite3Database::Context.
- Should we allow creating multiple iterator context from a single
DatabaseClient at once? At least it won't happen when we use it
from find(). For zone iteration we might want to allow that, but in
that case I suspect we'd rather "clone" the database connection. If
we restrict the use of the iterator context to be "singleton" per
client, we can use a prepared statement, which would be a bit
faster, and it may be important in the context of find().
- As pointed out above, I'd suggest that Context() take "name" as
std::string. Also, we might want to store the passed string inside
the class. If the std::string implementation uses refcount +
copy-on-write, the overhead should be marginal, and we can then also
change SQLITE_TRANSIENT in bindName to SQLITE_STATIC.
- I'd do sqlite3_finalize() once getNext() results in SQLITE_DONE.
Then even if an application is lazy and doesn't release the context
soon we can at least release the now-unnecessary lock on the DB.
- The call to sqlite3_finalize() in bindName() doesn't seem to be
necessary; if I miss something and it's really necessary, then I
suspect we also need it in bindZoneId().
- Since convertToPlainChar() is only used from the Context class, we
could make it a private method of the class. Then we don't have to
pass dbparameters to the function. (btw, as far as I can see the
passed dbparameters should never be NULL so the NULL check seems to
be redundant).
'''database_unittest.cc'''
- this comment seems incomplete (missing closing parenthesis?)
{{{
// the error handling of find() (the other on is below in
// if the name is "exceptiononsearch" it'll raise an exception
here
}}}
(actually it doesn't parse well either)
'''sqlite3_accessor_unittest.cc'''
- Not really for this branch, but I think it's not really appropriate
to use a zone containing only one RR(set) for the getAllRecords()
test.
- Don't we need iteratorColumnCount any more? The fact that getNext()
doesn't throw is already checked in the "iterator" test.
- On a related note: I'd avoid using magic numbers in iterator tests:
{{{
const size_t size(5);
std::string data[size];
...
EXPECT_EQ("example2.com.", data[4]);
EXPECT_EQ("SOA", data[0]);
EXPECT_EQ("master.example2.com. admin.example2.com. "
"1234 3600 1800 2419200 7200", data[3]);
EXPECT_EQ("3600", data[1]);
}}}
--
Ticket URL: <http://bind10.isc.org/ticket/1183#comment:4>
BIND 10 Development <http://bind10.isc.org>
BIND 10 Development
More information about the bind10-tickets
mailing list