From: JINMEI Tatuya Date: Wed, 5 Oct 2011 07:37:29 +0000 (-0700) Subject: [1261] overall comment update X-Git-Tag: perftcpdns_before_epoll~37^2~21^2~13^2~8 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=fcd39b6e84665a033d7ee4c06bd904e2b416c53a;p=thirdparty%2Fkea.git [1261] overall comment update --- diff --git a/src/bin/xfrin/tests/xfrin_test.py b/src/bin/xfrin/tests/xfrin_test.py index e55bab393d..b013b2ef9e 100644 --- a/src/bin/xfrin/tests/xfrin_test.py +++ b/src/bin/xfrin/tests/xfrin_test.py @@ -422,6 +422,7 @@ class TestXfrinIXFRAdd(TestXfrinState): self.assertEqual([], self.conn._diff.get_buffer()) def test_handle_new_delete(self): + self.conn._end_serial = 1234 # SOA RR whose serial is the current one means we are going to a new # difference, starting with removing that SOA. self.conn._diff.add_data(self.ns_rrset) # put some dummy change diff --git a/src/bin/xfrin/xfrin.py.in b/src/bin/xfrin/xfrin.py.in index 5d4082e138..01ca8d3458 100755 --- a/src/bin/xfrin/xfrin.py.in +++ b/src/bin/xfrin/xfrin.py.in @@ -144,26 +144,70 @@ class XfrinState: response RRs have already been received. NOTE: the AXFR part of the state machine is incomplete at this point. - This implementation uses the state design patter, where each state - is represented as a subclass of the base XfrinState class. The base - class defines two abstract interfaces: handle_rr() and finish_message(). - These methods handle specific part of XFR protocols and (if necessary) - perform the state transition. + The following diagram summarizes the state transition. After sending + the query, xfrin starts the process with the InitialSOA state (all + IXFR/AXFR response begins with an SOA). When it reaches IXFREnd + (or AXFREnd, which is not yet implemented and not shown here), the + process successfully completes. + + + (recv SOA) (AXFR-style IXFR) + InitialSOA------->FirstData------------->AXFR + | (non SOA, delete) + (pure IXFR,| +-------+ + keep handling)| (Delete SOA) V | + + ->IXFRDeleteSOA------>IXFRDelete--+ + ^ | + (see SOA, not end, | (see SOA)| + commit, keep handling) | | + | V + +---------IXFRAdd<----------+IXFRAddSOA + (non SOA, add)| ^ | (Add SOA) + ----------+ | + |(see SOA w/ end serial, commit changes) + V + IXFREnd + + This implementation uses the state design pattern, where each state + is represented as a subclass of the base XfrinState class. Each concrete + subclass of XfrinState is assumed to define two methods: handle_rr() and + finish_message(). These methods handle specific part of XFR protocols + and (if necessary) perform the state transition. + + Conceptually, XfrinState and its subclasses are a "friend" of + XfrinConnection and are assumed to be allowed to access its internal + information (even though Python does not have a strict access control + between different classes). The XfrinState and its subclasses are designed to be stateless, and can be used as singleton objects. For now, however, we always instantiate a new object for every state transition, partly because the introduction of singleton will make a code bit complicated, and partly because the overhead of object instantiotion wouldn't be significant for xfrin. + ''' def set_xfrstate(self, conn, new_state): '''Set the XfrConnection to a given new state. As a "friend" class, this method intentionally gets access to the connection's "private" method. + ''' conn._XfrinConnection__set_xfrstate(new_state) + def handle_rr(self, conn): + '''Handle one RR of an XFR response message. + + Depending on the state, the RR is generally added or deleted in the + corresponding data source, or in some special cases indicates + a specifi transition, such as starting a new IXFR difference + sequence or completing the session. + + All subclass has their specific behaviors for this method, so + there is no default definition. + ''' + pass + def finish_message(self, conn): '''Perform any final processing after handling all RRs of a response. @@ -183,9 +227,10 @@ class XfrinInitialSOA(XfrinState): conn._end_serial = get_soa_serial(rr.get_rdata()[0]) # FIXME: we need to check the serial is actually greater than ours. - # To do so, however, we need a way to find records from datasource. - # Complete that part later as a separate task. (Always performing - # xfr could be inefficient, but shouldn't do any harm otherwise) + # To do so, however, we need to implement serial number arithmetic. + # Although it wouldn't be a big task, we'll leave it for a separate + # task for now. (Always performing xfr could be inefficient, but + # shouldn't do any harm otherwise) self.set_xfrstate(conn, XfrinFirstData()) return True @@ -298,11 +343,16 @@ class XfrinConnection(asyncore.dispatcher): ''' asyncore.dispatcher.__init__(self, map=sock_map) + + # The XFR state. Coceptually this is purely private, so we emphasize + # the fact by the double underscore. Other classes are assumed to + # get access to this via get_xfrstate(), and only XfrinState classes + # are assumed to be allowed to modify it via __set_xfrstate(). self.__state = None + # Requested transfer type (RRType.AXFR or RRType.IXFR). The actual # transfer type may differ due to IXFR->AXFR fallback: self._request_type = None - self._end_serial = None # essentially private # Zone parameters self._zone_name = zone_name