#! /usr/bin/env python
#
"""
PyHeartBeat server
While the BeatLog thread logs UDP each packet in a dictionary,
the main thread periodically scans the dictionary and prints
the IP addresses of the clients that did not send any packet
for more than the timeout
"""
HBPORT = 43278
CHECKWAIT = 30
from socket import socket, gethostbyname, AF_INET, SOCK_DGRAM
from threading import Lock, Thread, Event
from time import time, ctime, sleep
class BeatDict:
"Manage heartbeat dictionary"
def __init__(self):
self.beatDict = {}
if __debug__:
self.beatDict['127.0.0.1'] = time()
self.dictLock = Lock()
def __repr__(self):
list = ''
for key in self.beatDict.keys():
list = "%sIP address: %s - Last time: %s\n" % \
(list, key, ctime(self.beatDict[key]))
return list
def update(self, entry):
"Create or update a dictionary entry"
self.dictLock.acquire()
self.beatDict[entry] = time()
self.dictLock.release()
def extractSilent(self, howPast):
"Returns a list of entries older than howPast"
silent = []
when = time() - howPast
self.dictLock.acquire()
for key in self.beatDict.keys():
if self.beatDict[key] < when:
silent.append(key)
self.dictLock.release()
return silent
class BeatRec(Thread):
"Receive UDP packets, log them in heartbeat dictionary"
def __init__(self, goOnEvent, updateDictFunc, port):
Thread.__init__(self)
self.goOnEvent = goOnEvent
self.updateDictFunc = updateDictFunc
self.hostIP = gethostbyname('localhost')
self.port = port
self.recSocket = socket(AF_INET, SOCK_DGRAM)
self.recSocket.bind((self.hostIP, self.port))
def __repr__(self):
return "Server IP: %s\nServer port: %d\n" % \
(self.hostIP, self.port)
def run(self):
while self.goOnEvent.isSet():
if __debug__:
print "Waiting to receive..."
data, addr = self.recSocket.recvfrom(5)
if __debug__:
print "Received packet from " + `addr`
self.updateDictFunc(addr[0])
def main():
"Listen to the heartbeats and detect inactive clients"
beatRecGoOnEvent = Event()
beatRecGoOnEvent.set()
beatDictObject = BeatDict()
beatRecThread = BeatRec(beatRecGoOnEvent,
beatDictObject.update, HBPORT)
if __debug__:
print beatRecThread
beatRecThread.start()
print "PyHeartBeat server listening on port %d" % HBPORT
print "\n*** Press Ctrl-C to stop ***\n"
while 1:
try:
if __debug__:
print "Beat Dictionary"
print `beatDictObject`
silent = beatDictObject.extractSilent(CHECKWAIT)
if silent:
print "Silent clients"
print `silent`
sleep(CHECKWAIT)
except KeyboardInterrupt:
print "Exiting."
beatRecGoOnEvent.clear()
beatRecThread.join()
if __name__ == '__main__':
main()