BIND 10 #397: Port generic red-black tree (RBT) data structure from BIND-9
BIND 10 Development
do-not-reply at isc.org
Tue Dec 7 05:43:07 UTC 2010
#397: Port generic red-black tree (RBT) data structure from BIND-9
------------------------------+---------------------------------------------
Reporter: zzchen_pku | Owner: jinmei
Type: enhancement | Status: reviewing
Priority: major | Milestone:
Component: data source | Resolution:
Keywords: | Sensitive: 0
Estimatedhours: 0.0 | Hours: 0
Billable: 1 | Totalhours: 0
Internal: 0 |
------------------------------+---------------------------------------------
Comment(by jinmei):
Here are some major outstanding issues. Some of them are simply not
addressed since the previous comments; some others are a revised
discussion based on the response.
- this stuff should go to src/lib/datasrc
- class/module/file name
> I do not totally understand it, if what we will provide the class
> memory data base, we should add another abstraction, so user don't
> need to know what concrete data struct we use. but this part code is
> red black tree porting
>
Actually, there are two issues here. First: Whether we want to make the
rbt stuff externally public or we want to keep it a private helper
used only inside our .cc's. I originally thought the former, but
maybe we should at least begin with the latter approach, in which
case this point may be less critical. The second issue is that it
still affects our internal modules that use this stuff. Consider
the ZoneTable class. It will contain the "RBTree" and calls its
find() method. If we change the internal data structure from the
red black tree based one (e.g. to a B-tree like thing), the class
name "RBTree" is not correct and we'd like to change the interface
to "BTree" or something. Then we'll need to change the caller side
of the code even if the interface and the provided service
(i.e. giving a longest match for a given name) don't change. From
the user's point of view, the important point is the interface, not
the internal data structure. When naming something that can be
used by other things than that "something", we should focus on the
interface, not the internal implementation. Finally, in any case,
"_datasrc" in "rbt_datasrc.h" doesn't make sense anymore because
the defined stuff in the header file isn't actually a "data source"
itself.
- boost noncopyable
> I think we should depend less on boost compile part, but if only needs
head file, I don't see the difference between depending on one file and
more files.
>
No, the point is that boost is a moving target, and using it in a
public header file increases the risk of introducing binary backward
incompatibility. More boost header files to be included, more risks
we have. So, basically, unless it's very difficult to find a
reasonable alternative to the feature that a particular boost module
provides, we shouldn't use it in a public header file. So far, the
only exception is shared_ptr. Its benefit is too big, and due to
its complexity it's very difficult to have a non boost alternative.
A relatively more subtle exception is boost/function, which is
included from two of our public header files. Hopefully we can
remove the dependency on it eventually, but for now we have it as a
compromise. We don't use any other boost header files in our public
header files. IN the case of noncopyable, it's just a syntax sugar,
and its alternative is just a few line of additional C++ code. It's
way below the level of inevitable dependency.
Another issue is overall code consistency. If, for some reason, we
agree on using boost noncopyable, we should use it consistently
throughout the code. Using it only in a single header file is
confusing. We should either use it for all noncopyable classes or
not use it anywhere.
- exception safety: changing new to object_pool doesn't solve the
essential problem. See, e.g. nodeFission(). if the code following
the createNode() call throws an exception (and it can throw), the
allocated resource will still be hanging inside the pool, without
being used by anyone, until we destruct the entire pool. The new
code indeed "fixes" memory leak in the long run, but in practice
the memory is leaking from the user's point of view. For the code
to be really exception safe, we should clean up all newly allocated
resources immediately after exception. object_pool is primarily
for performance improvement, and the use of it may or may not be a
good idea (although I'd defer the tuning later - making such a
drastic change to an already big patch will make review harder),
but I cannot be free from the exception safety issue regardless of
the use of the pool.
- A related point: again, whether or not using object_pools,
returning an error code for the "no memory" condition is IMO not a
good idea because it's not consistent with our error handling
convention. I already pointed it out in my previous review, and
it's still outstanding.
- NXRRSET vs the notion of "shadow": I pointed this out in my
previous review as part of comment on findHelper(). It's not
addressed yet.
- suggestion: drop the idea of shadow; require type T be comparable
with NULL; replace the logic that checks whether the node is
checked to be shadow with checking T == NULL. So, for example,
instead of
{{{
if (!node->is_shadow_) {
*target = node;
ret = EXACTMATCH;
}
}}}
in findHelper(), do this:
{{{
if (node->data_ != NULL) {
*target = node;
ret = EXACTMATCH;
}
}}}
Note: this doesn't yet solve the NXRRSET case, but let's
resolve this matter later in a future sprint.
- documentation is still quite insufficient. quoting my previous
comments: "documentation in general: we need two types of
documentation: one for API users, and the other for developers who
try to read/modify the code..."
- existing (minor) point that isn't addressed:
- The diagram after the (RBTree) class definition: this should be
included in the doxygen document.
--
Ticket URL: <http://bind10.isc.org/ticket/397#comment:25>
BIND 10 Development <http://bind10.isc.org>
BIND 10 Development
More information about the bind10-tickets
mailing list