include serialize.repy

# send a probe message to each neighbor
def probe_neighbors(port):

  for neighborip in mycontext["neighborlist"]:
    mycontext['sendtime'][neighborip] = getruntime()
    # Serialize the data to send
    serialized = serialize_serializedata(encode_latencies(getmyip(), mycontext["neighborlist"], mycontext['latency'].copy()))
    sendmess(neighborip, port, 'ping',getmyip(),port)

    sendmess(neighborip, port,'share'+serialized)
    # sleep in between messages to prevent us from getting a huge number of 
    # responses all at once...
    sleep(.5)

  # Call me again in 10 seconds
  while True:
    try:
      settimer(10,probe_neighbors,(port,))
      return
    except Exception, e:
      if "Resource 'events'" in str(e):
        # there are too many events scheduled, I should wait and try again
        sleep(.5)
        continue
      raise
  

# Handle an incoming message
def got_message(srcip,srcport,mess,ch):
  if mess == 'ping':
    sendmess(srcip,srcport,'pong')
  elif mess == 'pong':
    # elapsed time is now - time when I sent the ping
    mycontext['latency'][srcip] = getruntime() - mycontext['sendtime'][srcip]

  elif mess.startswith('share'):
    mycontext['row'][srcip] = mess[len('share'):]


def encode_latencies(srcip, neighborlist, latencylist):
  latdict = {}
  for neighborip in neighborlist:
    if neighborip in latencylist:
      latdict[neighborip] = str(latencylist[neighborip])[:10]
    else:
      latdict[neighborip] = "N/A"
  return latdict


def send_all(connobj, data):
  while data != "":
    amount_sent = connobj.send(data)
    data = data[amount_sent:]
  
  
def push_latencies(srcip, srcport, connobj, ch, listench):
  latdict = {}
  for nodeip in mycontext['neighborlist']:
    if nodeip in mycontext['row']:
      latdict[nodeip] = serialize_deserializedata(mycontext['row'][nodeip])

  str_to_send = serialize_serializedata(latdict)
  print str_to_send
  send_all(connobj, str_to_send)
  connobj.close()
    

  
if callfunc == 'initialize':

  # this holds the response information (i.e. when nodes responded)
  mycontext['latency'] = {}

  # this remembers when we sent a probe
  mycontext['sendtime'] = {}

  # this remembers row data from the other nodes
  mycontext['row'] = {}
  
  # get the nodes to probe
  mycontext['neighborlist'] = []

  for line in file("neighboriplist.txt"):
    mycontext['neighborlist'].append(line.strip())

  ip = getmyip() 
  if len(callargs) != 1:
    raise Exception, "Must specify the port to use"
  pingport = int(callargs[0])

  # call gotmessage whenever receiving a message
  recvmess(ip,pingport,got_message)

  probe_neighbors(pingport)

  # we want to register a function to show a status webpage (TCP port)
  pageport = int(callargs[0])
  waitforconn(ip,pageport,push_latencies)
