#! /usr/bin/python

from socket import *
import os
import sys
import signal

import threading

from monitor import Monitor


UNIX_SOCKET_PATH = '/tmp/cluster_monitor_sock'
COMMUNICATION_PORT = 5000


class Master:
    
    def __init__(self, socket_path, comm_port):
        self.monitor = Monitor(comm_port)
        self.workers = []
        
        self.server_socket = self.serverSocket(socket_path)
        
        self.__stop = False
        
        pass
    
    def start(self):
        # start monitoring thread
        self.monitor.start()
        
        while self.__stop != True:
            for worker in self.workers[:]:
                if worker.isAlive() != True:
                    self.workers.remove(worker)
            
            # wait for new connection
            try:
                sock, t = self.server_socket.accept()
            except:
                break
            print 'client\'s connection accepted'
            # new worker
            worker = Worker(self.monitor, sock)
            worker.start()
            self.workers.append(worker)
        
        for w in self.workers[:]:
            w.stop()
            self.workers.remove(w)
        self.server_socket.shutdown(2)
        self.monitor.stop()
        
    
    def stop(self):
        self.__stop = True
        
    
    def serverSocket(self, socket_path):
        if(os.access(socket_path, os.F_OK)):
            os.remove(socket_path)
        sock = socket(AF_UNIX, SOCK_STREAM)
        sock.bind(socket_path)
        sock.listen(5)
        return sock
    
    
    

class Worker(threading.Thread):
    def __init__(self, monitor, sock):
        threading.Thread.__init__(self)
        self.monitor = monitor
        self.sock = sock
    
    def run(self):
        while True:
            try:
                req = self.sock.recv(1024)
                if len(req) == 0:
                    break
                resp = self.monitor.request(req)
                self.sock.sendall(resp)
            except:
                break
        try:
            self.sock.shutdown(2)
        except:
            pass
        self.sock.close()
        print 'client\'s connection closed'
    
    def stop(self):
        try:
            self.sock.shutdown(2)
        except:
            pass
    





master = Master(UNIX_SOCKET_PATH, COMMUNICATION_PORT)

def sighandler(arg1, arg2):
    master.stop()
signal.signal(signal.SIGUSR1, sighandler)

master.start()
