def evaluate_credit()

in tools/scraper/amqp_detail.py [0:0]


    def evaluate_credit(self):
        for conn in self.rtr.conn_list:
            id = self.rtr.conn_id(conn)
            conn_detail = self.rtr.details.conn_details[id]
            for sess in conn_detail.session_list:
                for link in sess.link_list:
                    # ignore links without starting attach
                    if link.frame_list[0].data.name != "attach":
                        link.counts.credit_not_evaluated += 1
                        sess.counts.credit_not_evaluated += 1
                        conn_detail.counts.credit_not_evaluated += 1
                        break
                    # process flaggage
                    look_for_sender_delivery_id = True
                    dir_of_xfer = ''
                    dir_of_flow = ''
                    current_delivery = 0  # next transfer expected id
                    delivery_limit = 0  # first unreachable delivery id from flow
                    n_attaches = 0
                    tod_of_second_attach = None
                    multiframe_in_progress = False
                    init_stall = True
                    credit_stall = False
                    tod_of_no_credit = None
                    tod_of_shutdown = None
                    # record info about initial attach
                    is_rcvr = link.frame_list[0].data.is_receiver
                    o_dir = link.frame_list[0].data.direction
                    # derive info about where to look for credit and transfer id
                    #  role dir  transfers flow w/credit case
                    #  ---- ---- --------- ------------- ----
                    #  rcvr  <-   ->        <-            A
                    #  rcvr  ->   <-        ->            B
                    #  sndr  <-   <-        ->            B
                    #  sndr  ->   ->        <-            A
                    #
                    if (((is_rcvr) and (o_dir == text.direction_in())) or
                            ((not is_rcvr) and (o_dir == text.direction_out()))):
                        # case A
                        dir_of_xfer = text.direction_out()
                        dir_of_flow = text.direction_in()
                    else:
                        # case B
                        dir_of_xfer = text.direction_in()
                        dir_of_flow = text.direction_out()

                    for plf in link.frame_list:
                        # initial credit delay starts at reception of second attach
                        if n_attaches < 2:
                            if plf.data.name == "attach":
                                n_attaches += 1
                                if n_attaches == 2:
                                    tod_of_second_attach = plf.datetime
                        if look_for_sender_delivery_id:
                            if plf.data.name == "attach" and not plf.data.is_receiver:
                                current_delivery = int(plf.data.described_type.dict.get("initial-delivery_count", "0"), 0)
                                delivery_limit = current_delivery
                                look_for_sender_delivery_id = False

                        if plf.data.name == "flow":
                            if plf.data.direction == dir_of_flow:
                                # a flow in the normal direction updates the delivery limit
                                dc = plf.data.described_type.dict.get("delivery-count", "0")
                                lc = plf.data.described_type.dict.get("link-credit", "0")
                                delivery_limit = int(dc, 0) + int(lc, 0)  # TODO: wrap at 32-bits
                                if n_attaches < 2:
                                    # a working flow before sender attach - cancel initial stall
                                    init_stall = False
                                if init_stall:
                                    init_stall = False
                                    dur = plf.datetime - tod_of_second_attach
                                    link.counts.initial_no_credit_duration = dur
                                    sess.counts.initial_no_credit_duration += dur
                                    conn_detail.counts.initial_no_credit_duration += dur
                                if credit_stall and delivery_limit > current_delivery:  # TODO: wrap
                                    credit_stall = False
                                    plf.data.web_show_str += " <span style=\"background-color:%s\">credit restored</span>" % common.color_of("no_credit")
                                    dur = plf.datetime - tod_of_no_credit
                                    link.counts.no_credit_duration += dur
                                    sess.counts.no_credit_duration += dur
                                    conn_detail.counts.no_credit_duration += dur
                            else:
                                # flow in the opposite direction updates the senders current delivery
                                # normally used to consume credit in response to a drain from receiver
                                current_delivery = int(plf.data.described_type.dict.get("initial-delivery_count", "0"), 0)

                        elif plf.data.transfer:
                            if plf.data.direction == dir_of_xfer:
                                if not plf.data.transfer_more:
                                    # consider the transfer to have arrived when last transfer seen
                                    current_delivery += 1  # TODO: wrap at 32-bits
                                    if current_delivery == delivery_limit:
                                        link.counts.no_credit += 1
                                        sess.counts.no_credit += 1
                                        conn_detail.counts.no_credit += 1
                                        plf.data.transfer_exhausted_credit = True
                                        credit_stall = True
                                        plf.data.web_show_str += " <span style=\"background-color:%s\">no more credit</span>" % common.color_of("no_credit")
                                        tod_of_no_credit = plf.datetime
                                    else:
                                        pass  # still have credit
                                    multiframe_in_progress = False
                                else:
                                    # transfers with 'more' set don't consume credit
                                    multiframe_in_progress = True
                            else:
                                pass   # transfer in wrong direction??

                        elif plf.data.name == "detach":
                            tod_of_shutdown = plf.datetime
                            break

                    # clean up lingering credit stall
                    if init_stall or credit_stall:
                        if tod_of_shutdown is None:
                            # find first end or close and call that shutdown time
                            for plf in sess.session_frame_list:
                                if plf.data.name == "end":
                                    tod_of_shutdown = plf.datetime
                                    break
                            if tod_of_shutdown is None:
                                for plf in conn_detail.unaccounted_frame_list:
                                    if plf.data.name == "close":
                                        tod_of_shutdown = plf.datetime
                                        break
                                if tod_of_shutdown is None:
                                    # Hmmm, no shutdown. Use last link frame
                                    tod_of_shutdown = link.frame_list[-1].datetime
                        if tod_of_second_attach is None:
                            # Hmmm, no second attach. Use first link frame time
                            tod_of_second_attach = link.frame_list[0].datetime
                        if init_stall:
                            dur = tod_of_shutdown - tod_of_second_attach
                            link.counts.initial_no_credit_duration = dur
                            sess.counts.initial_no_credit_duration += dur
                            conn_detail.counts.initial_no_credit_duration += dur
                        if credit_stall:  # TODO: wrap
                            dur = tod_of_shutdown - tod_of_no_credit
                            link.counts.no_credit_duration += dur
                            sess.counts.no_credit_duration += dur
                            conn_detail.counts.no_credit_duration += dur

                    # record multiframe transfer that didn't complete
                    if multiframe_in_progress:
                        link.counts.incomplete += 1
                        sess.counts.incomplete += 1
                        conn_detail.counts.incomplete += 1