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