BIND 10 #2974: Implement Hooks Framework (part 1) - all but library loading and unloading
BIND 10 Development
do-not-reply at isc.org
Wed Jun 12 16:10:35 UTC 2013
#2974: Implement Hooks Framework (part 1) - all but library loading and unloading
-------------------------------------+-------------------------------------
Reporter: stephen | Owner: tomek
Type: task | Status:
Priority: medium | reviewing
Component: Unclassified | Milestone:
Keywords: | Sprint-DHCP-20130620
Sensitive: 0 | Resolution:
Sub-Project: DHCP | CVSS Scoring:
Estimated Difficulty: 0 | Defect Severity: N/A
Total Hours: 0 | Feature Depending on Ticket:
| Add Hours to Ticket: 0
| Internal?: 0
-------------------------------------+-------------------------------------
Comment (by tomek):
'''src/lib/util/hooks/callout_manager.h'''
I would have preferred if that was done as a separate ticket, but since it
is here, I'll review it.
The design does not allow for extra libraries to be loaded at runtime.
This is something we need to be ready for. You start a server, then
configure it to use one library, then configure it to use another one. You
can't assume that the number of libraries is constant.
Who is intended user of the public methods in !CallOutManager: server-side
code or user library?
I assume it is server code, right? Again, I have trouble understanding how
the intended usage model looks like. Who is going to call
setLibraryIndex()? I'm concerned with the fact that the registerCallout()
may be called by the user library, right? Yet at the same time in the same
public scope we have method setLibraryIndex() that user library must not
call. You can add applicability statements, but they are not worth
anything. There will always be someone who thinks he is smart by playing
tricks ("my library must always be called first, so I'll set library index
to 0. Ha!").
Please make it private and define as a friend for
!CalloutHandle::getContextForLibrary(). Otherwise library developers will
mess with it.
The functions in .h file are getting bigger and bigger. It is more
difficult to understand the code if it is split between .cc and .h (for
example when I seach where function X is called I need to do it twice,
once for each file). And of course it is less efficient from the
compilation perspective. The same code is included many, many times.
'''src/lib/util/hooks/callout_manager.cc'''
CalloutManager::registerCallout() Isn't the
checkLibraryIndex(current_library_) check redundant? It was already
checked when setting up current_library_.
Why do you require to have the callouts from the same library be grouped
together? Michal gave specific example when he wants them to be out of
order: the encryption + signing. I would remove the whole for loop from
registerCallout().
callCallouts() - There's a saying that the disign is not complete when
there is noting else to add, but when there is nothing else left to be
taken away. This method has almost good design :) In the current code,
you'll do vector copy every time. There's 27 hook points for DHCPv6,
multiplied by 16000 (current number of transactions per second) gives you
432 thousand copies per second. I can't let that happen. Fortunately,
there's a very easy solution:
Forbid installing new callout on a hook point from the callout called from
the same hook point.
Easy to communicate to library developers and easy to enforce. In
callCallouts() store i value in current_hook_being_processed_. In
registerCallout() add a check if someone tries to install a callout on the
hook point that is currently being process, then throw exception. The same
should be true for deregistering callout.
deregisterCallout() - that's a tricky removal code. I think I understand
how it works, but isn't there a simpler way to remove something from a
vector?
'''src/lib/util/tests/callout_manager_unittest.cc'''
!CalloutManagerTest constructor. I don't like the fact that there are 4
hook points defined and there is a maximum of 4 libraries. One of those
values should be changed to avoid confusion. You do not set callout_value_
in constructor.
Brilliant trick for recording callouts order :)
Why are those callouts named manager_X? I think they should be called
callout_X (or userlib_X). They represent callouts from a user library.
Naming them manager is a bit misleading. There will always be just one
manager.
!CalloutManagerTest.!CallCalloutsError: I'm somewhat uneasy with the fact
that the first library that returns an error will cause other libraries to
not be called. What if the first library is logger and it reports error,
because partition for logs is full? Then the code will stop calling
libraries for access control, host reservations etc. That would
essentially disable hooks and the server would continue to run in its
"vanilla" form. This would make a very fragile system, with easily
triggered domino effect. The first library that falls over will trip all
others as well.
Skip flag is not tested.
There are no tests that check that the same callout can be
registered/called/deregistered on different hook points.
(!CalloutManagerTest.!CallCalloutsSuccess checks that to some degree)
Outstanding tests (callout_handle, handles_unittest) will be reviewed in
the next comment.
--
Ticket URL: <http://bind10.isc.org/ticket/2974#comment:7>
BIND 10 Development <http://bind10.isc.org>
BIND 10 Development
More information about the bind10-tickets
mailing list