BIND 10 #3156: Create separate base-classes for the Finite State Machine logic in NameChangeTransaction class

BIND 10 Development do-not-reply at isc.org
Thu Sep 19 19:22:44 UTC 2013


#3156: Create separate base-classes for the Finite State Machine logic in
NameChangeTransaction class
-------------------------------------+-------------------------------------
            Reporter:  tmark         |                        Owner:  tomek
                Type:  enhancement   |                       Status:
            Priority:  low           |  reviewing
           Component:  dhcp-ddns     |                    Milestone:
            Keywords:                |  Sprint-DHCP-20130918
           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
-------------------------------------+-------------------------------------
Changes (by tmark):

 * owner:  tmark => tomek


Comment:

 Replying to [comment:7 tomek]:
 > General comment: state_model is generic and can be used by other
 > components, not only d2. It should be moved somewhere to src/lib.
 > src/lib/util would be my initial pick, but it should probably be
 > consulted with folks on bind10 chatroom.

 I would prefer to move it once it has matured a bit. Having it close by
 while in the thick of D2 works is simpler.  Moving it later be won't hard
 I just don't want to move it now.

 >
 > This should be reflected by the ChangeLog entry.
 >
 > Please make sure you keep the diagrams, so they can be used for a nice
 doxygen description. I think there's a ticket for that already, isn't it?
 >
 Yes I have a ticket for  this already.
 >
 >
 > '''state_model.h'''
 >
 > File comment mentions nc_trans.h.
 >
 > "No work can done" => "No work can be done"
 >
 > argument which is "posts" => argument which it "posts"
 >
 > "runModel repeats this process until it either NOP_EVT or END_EVT events
 are posted."
 > What about FAIL_EVT?
 >
 > "must wait or ends ." => Extra space before dot.
 >
 > "To progress from from one state" => Extra "from"
 >
 > "a state and an a event" => Remove extra article.
 >
 > "postEvent method is may be" => Either is or may, not both.

 Fixed all of the above.

 >
 > StateModel::SM_STATE_MAX - shouldn't it be SM_STATE_MIN as this is the
 minimal state that derived classes should define?

 Is it half empty or half full?  I was thinking of it as the "maximum value
 a !StateModel state may have".  I did  not change this.

 >
 > runModel(): The fact that state handlers may run multiple interations of
 a state
 > change is a bit worrisome, because it is now impossible to detect
 > potential infinite loops in FSM logic. This brings in a halting
 > problem to the scene. Halting problem is NP-hard, unfortunately. Since
 > I don't have a better solution (if I had, I would likely win Turing
 > Award in the process), let the code stay as it is now.

 Yes, you can certainly hang yourself. Again, I would remind you that I did
 not start out to write a bullet proof FSM implementation.  I have been
 attempting to keep it lightweight, and even if it is a bit "manual" in
 terms of use.  Certainly, we can refine it over time.

 >
 > endModel(): "It is should be called"
 > Either "is called" or "should be called".
 >

 I would like to request a technical writer to do my documentation please.
 ;)
 Fixed.

 > verifyStateHandlerMap():
 > "a implementation" => "an implementation"
 >

 Fixed.


 > onModelFailure(): I think you should provide some generic error handler.
 It would make
 > derived implementations easier.
 >

 I'm not sure I understand.  This let's the derivation react to a model
 failure by doing whatever they need to do, beyond the model transitioning
 to END_ST/FAIL_EVT.  This is invoked when an exception is thrown during
 runModel.  The idea being that the derivation's state model should account
 for ALL errors that may occur, anything that escapes is: an invalid state,
 an invalid event, or an unhandled error.  All of these amount to a
 violation of the model itself and they all are handled from one spot.
 This is something like a "hook" that allows the derivation to do something
 if desired.  It's akin to an "onEntry" or "onExit" concept.


 > getStateLabel(), getEventLabel():
 > It would be better to implement a constructor that takes 2 map<int,
 > string> objects. The methods could be defined in base class and
 > wounldn't have to be defined in each derived class. If there are
 > problems with passing map, then perhaps a static array of
 > {{{
 > struct {
 >     int;
 >     const char*;
 >     StateHandler;
 > }
 > }}}
 > could be passed. That would eliminate the need to implement
 > getStateLabel(), getEventLabel() and probably other as well.
 >
 > addToMap: This name is confusing as it is not clear what the map is,
 > without looking into the doc. addToStateMap or simply addState() would
 > be more appropriate.
 >


 I have replaced the more manual means of specifying events and states with
 a new scheme based upon two new classes: !LabeledValue and
 !LabeledValueSet.  These two let you create a set or dictionary of unique
 numeric values that have labels.  Deriving from these two, lets you expand
 on that.  At the moment an Event is simply a !LabeledValue and they are
 stored in a !LabeledValueSet. A State derives from LabeledValue and then
 adds a handler member. States are stored in a !StateSet which is a
 derivation of !LabeledValueSet.

 StateModel now has two dictionaries, one of valid events and one of valid
 states.  Each level in a StateModel derivation hierarchy may contribute
 events and/or states as before but it is much cleaner now.

 I reworked the unit tests quite a bit.

 > '''state_model_unittests.cc'''
 > Do you think it would be useful to check if runModel() throws if there
 > was no startModel() called?

 This is now tested in the new tests.

 >
 > Also, I think the model should throw if you call addState() after
 > startModel(). Otherwise we could allow a FSM that modifies itself
 > during run. That would encourage shady tricks.
 >

 This is now enforced for both events and states.

 >
 > '''nc_trans.h'''
 > Why do you need NameChangeTransactionError anymore? Wouldn't
 > StateModelError suffice?
 >

 There are errors that can occur in NCT that do not pertain to the state
 model.
 Look at NCT's constructor for instance.


 > verifyStateHandlerMap(): This comment mostly repeats what is said for
 > StateModel::verifyStateHandlerMap(). Perhaps you could trim down the
 > comments in NameChangeTransaction.

 Obsoleted by changes above.

 >
 > If you agree to my proposal for passing map of states as an array or
 > map, then several methods wouldn't be necessary in
 > NameChangeTransaction.

 Addressed by changes above.  As an aside, I had started to go down this
 road before but decided it would likely take more time than I wanted to
 invest.  I am much happier with the overall result now though and
 subsequent derivations will be easier.  Naturally I have included a new
 diagram that depicts the changes:

 [[Image(lvset_state_model_classes.svg)]]

-- 
Ticket URL: <http://bind10.isc.org/ticket/3156#comment:8>
BIND 10 Development <http://bind10.isc.org>
BIND 10 Development


More information about the bind10-tickets mailing list