if stat['group'] != 'Actions':
out.write("<tr><th>Statistic</th><th>Value</th></tr>\n")
else:
- out.write("<tr><th>Action</th><th>Sent</th><th>OK</th><th>Failed</th><th>Received</th><th>Error</th></tr>\n")
+ out.write("<tr><th>Action</th><th>Started</th><th>Sent</th><th>OK</th><th>Failed</th><th>Received</th><th>Error</th></tr>\n")
old_group = stat['group']
if stat['group'] != 'Actions':
out.write("<tr title='" + stat['tip'] + "'><td>" + stat['desc'] + '</td><td>' + str(stat['value']) + '</td></tr>\n')
actions.sort()
for action in actions:
out.write("<tr><td>" + action + "</td>")
- for i in xrange(5):
+ for i in xrange(6):
out.write("<td>" + str(stat['value'][action][i]) + "</td>")
out.write('</tr>\n')
@ivar sort: used to sort nodes by their proximity to the target
"""
- def __init__(self, caller, target, callback, config, action, num_results = None):
+ def __init__(self, caller, target, callback, config, stats, action, num_results = None):
"""Initialize the action.
@type caller: L{khashmir.Khashmir}
@param callback: the method to call with the results
@type config: C{dictionary}
@param config: the configuration variables for the DHT
+ @type stats: L{stats.StatsLogger}
+ @param stats: the statistics gatherer
@type action: C{string}
@param action: the name of the action to call on remote nodes
@type num_results: C{int}
self.target = target
self.config = config
self.action = action
+ stats.startedAction(action)
self.num = intify(target)
self.queried = {}
self.answered = {}
class FindNode(ActionBase):
"""Find the closest nodes to the key."""
- def __init__(self, caller, target, callback, config, action="findNode"):
- ActionBase.__init__(self, caller, target, callback, config, action)
+ def __init__(self, caller, target, callback, config, stats, action="findNode"):
+ ActionBase.__init__(self, caller, target, callback, config, stats, action)
def processResponse(self, dict):
"""Save the token received from each node."""
class FindValue(ActionBase):
"""Find the closest nodes to the key and check for values."""
- def __init__(self, caller, target, callback, config, action="findValue"):
- ActionBase.__init__(self, caller, target, callback, config, action)
+ def __init__(self, caller, target, callback, config, stats, action="findValue"):
+ ActionBase.__init__(self, caller, target, callback, config, stats, action)
def processResponse(self, dict):
"""Save the number of values each node has."""
class GetValue(ActionBase):
"""Retrieve values from a list of nodes."""
- def __init__(self, caller, target, local_results, num_results, callback, config, action="getValue"):
+ def __init__(self, caller, target, local_results, num_results, callback, config, stats, action="getValue"):
"""Initialize the action with the locally available results.
@type local_results: C{list} of C{string}
@param local_results: the values that were available in this node
"""
- ActionBase.__init__(self, caller, target, callback, config, action, num_results)
+ ActionBase.__init__(self, caller, target, callback, config, stats, action, num_results)
if local_results:
for result in local_results:
self.results[result] = 1
class StoreValue(ActionBase):
"""Store a value in a list of nodes."""
- def __init__(self, caller, target, value, num_results, callback, config, action="storeValue"):
+ def __init__(self, caller, target, value, num_results, callback, config, stats, action="storeValue"):
"""Initialize the action with the value to store.
@type value: C{string}
@param value: the value to store in the nodes
"""
- ActionBase.__init__(self, caller, target, callback, config, action, num_results)
+ ActionBase.__init__(self, caller, target, callback, config, stats, action, num_results)
self.value = value
def getNodesToProcess(self):
d.callback(nodes)
else:
# Start the finding nodes action
- state = FindNode(self, id, d.callback, self.config)
+ state = FindNode(self, id, d.callback, self.config, self.stats)
reactor.callLater(0, state.goWithNodes, nodes)
def insertNode(self, node, contacted = True):
self.table.justSeenNode(old.id)
# Bucket is full, check to see if old node is still available
+ self.stats.startedAction('ping')
df = old.ping(self.node.id)
df.addCallbacks(_notStaleNodeHandler, _staleNodeHandler)
elif callback:
callback(None)
+ self.stats.startedAction('join')
df = node.join(self.node.id)
df.addCallbacks(_pongHandler, _defaultPong)
d.addCallback(callback)
# Search for others starting with the locally found ones
- state = FindValue(self, key, d.callback, self.config)
+ state = FindValue(self, key, d.callback, self.config, self.stats)
reactor.callLater(0, state.goWithNodes, nodes)
def valueForKey(self, key, callback, searchlocal = True):
def _getValueForKey(nodes, key=key, local_values=l, response=callback, self=self):
"""Use the found nodes to send requests for values to."""
- state = GetValue(self, key, local_values, self.config['RETRIEVE_VALUES'], response, self.config)
+ state = GetValue(self, key, local_values, self.config['RETRIEVE_VALUES'], response, self.config, self.stats)
reactor.callLater(0, state.goWithNodes, nodes)
# First lookup nodes that have values for the key
"""Default callback that does nothing."""
pass
response = _storedValueHandler
- action = StoreValue(self, key, value, self.config['STORE_REDUNDANCY'], response, self.config)
+ action = StoreValue(self, key, value, self.config['STORE_REDUNDANCY'], response, self.config, self.stats)
reactor.callLater(0, action.goWithNodes, nodes)
# First find the K closest nodes to operate on.
return stats
+ #{ Called by the action
+ def startedAction(self, action):
+ """Record that an action was started.
+
+ @param action: the name of the action
+ """
+ act = self.actions.setdefault(action, [0, 0, 0, 0, 0, 0])
+ act[0] += 1
+
#{ Called by the transport
def sentAction(self, action):
"""Record that an action was attempted.
@param action: the name of the action
"""
- act = self.actions.setdefault(action, [0, 0, 0, 0, 0])
- act[0] += 1
+ act = self.actions.setdefault(action, [0, 0, 0, 0, 0, 0])
+ act[1] += 1
def responseAction(self, response, action):
"""Record that a response to an action was received.
@param action: the name of the action
@return: the response (for use in deferreds)
"""
- act = self.actions.setdefault(action, [0, 0, 0, 0, 0])
- act[1] += 1
+ act = self.actions.setdefault(action, [0, 0, 0, 0, 0, 0])
+ act[2] += 1
return response
def failedAction(self, response, action):
@param action: the name of the action
@return: the response (for use in deferreds)
"""
- act = self.actions.setdefault(action, [0, 0, 0, 0, 0])
- act[2] += 1
+ act = self.actions.setdefault(action, [0, 0, 0, 0, 0, 0])
+ act[3] += 1
return response
def receivedAction(self, action):
@param action: the name of the action
"""
self.reachable = True
- act = self.actions.setdefault(action, [0, 0, 0, 0, 0])
- act[3] += 1
+ act = self.actions.setdefault(action, [0, 0, 0, 0, 0, 0])
+ act[4] += 1
def errorAction(self, action):
"""Record that a received action resulted in an error.
@param action: the name of the action
"""
- act = self.actions.setdefault(action, [0, 0, 0, 0, 0])
- act[4] += 1
+ act = self.actions.setdefault(action, [0, 0, 0, 0, 0, 0])
+ act[5] += 1
def sentBytes(self, bytes):
"""Record that a single packet of some bytes was sent.