'''
This module implements an XMLRPC server to asynchonously receive
messages (events) from the experiment nodes.

It features a Queue and a mechanism to interact with the ExperiMaster

'''
from SimpleXMLRPCServer import SimpleXMLRPCServer
from SimpleXMLRPCServer import SimpleXMLRPCRequestHandler
import xmlrpclib
import thread
import os
import sys
import threading
from datetime import datetime

# Restrict to a particular path.
class RequestHandler(SimpleXMLRPCRequestHandler):
    rpc_paths = ('/RPC2',)
    

class eventsRPC:
    _wait_for_type = ""
    _event_was_type= ""
    
    def __init__(self, event_condition, event_log, verbose):
        self._event_condition = event_condition
        self._event_log = event_log
        self.verbose = verbose
    
    def _inject_event(self, node, timestamp, type, param):
        self.event(node,timestamp,type,param)
    
    def _clear(self):
        self._event_condition.acquire()
        for i in range(len(self._event_log)):
            self._event_log.pop()
        self._event_condition.release()
        
    def event(self, node, timestamp, type, param):
        '''
        This function is called by the RPC clients.
        It puts the received event into a list and
        notifies waiting threads that an event has
        occurred.
        '''
        if self.verbose:
            print "EH: got event %s at %s from %s " % (type,timestamp,node)
        self._event_condition.acquire()
        try:
            self._event_log.append( ( datetime.now(), node, timestamp, type, param ) )
        except:
            print "EH:ERROR"
        self._event_condition.notifyAll()
        self._event_condition.release()
            
        return 0
    
class StoppableRPCServer(SimpleXMLRPCServer):

    stopped = False
    allow_reuse_address = True

    def __init__(self, *args, **kw):
        SimpleXMLRPCServer.__init__(self, *args, **kw)
        self.register_function(lambda: 'OK', 'ping')
        self.is_finally_done = 0
        
    def serve_forever(self):
        while not self.stopped:
            try:
                self.handle_request()
            except Exception, e:
                print "Exception: ",e

        print "EH: Done"
        self.is_finally_done = 1

    def force_stop(self):
        self.stopped = True
        if self.is_finally_done==0:
            self.create_dummy_request()
        self.server_close()
        #self.create_dummy_request()


    def create_dummy_request(self):
        server = xmlrpclib.Server('http://localhost:8000')
        try:
            server.ping()
        except:
            pass
        
class EventHandler:

    def __init__(self,verbose):
        print "EH: Init"
        self.verbose = verbose
        self.event_log = []
        self.event_condition = threading.Condition()
        self.events = eventsRPC(self.event_condition, self.event_log,verbose)
    
    def __del__(self):
        pass    
        
    def inject_event(self, node, timestamp, type, param):
        print "EH: injecting event %s" %(type)
        self.events._inject_event(node, timestamp, type, param)
        print "EH: injection of event done"
        
    def event_thread(self):
        print "EH: Start"
        self.server = StoppableRPCServer(('', 8000),logRequests=False, requestHandler=RequestHandler)
        self.server.register_introspection_functions()
        self.server.register_instance( self.events )
        # Run the server's main loop
        if self.verbose:
            print "EH: Main loop running"
        try:
            self.server.serve_forever()
            print "EH: Stopped serving"
        except (KeyboardInterrupt, SystemExit):
            print "Program was terminated by CTRL+C"

    def clear_log(self):
        self.events._clear()

    def start_event_handler(self):
        # Create server 
        #'' means bind to all addresses
        thread.start_new_thread(self.event_thread, ())
        
        
    def stop_event_handler(self):
        self.server.force_stop()
'''
This module implements an XMLRPC server to asynchonously receive
messages (events) from the experiment nodes.

It features a Queue and a mechanism to interact with the ExperiMaster

'''
from SimpleXMLRPCServer import SimpleXMLRPCServer
from SimpleXMLRPCServer import SimpleXMLRPCRequestHandler
import xmlrpclib
import thread
import os
import sys
import threading
from datetime import datetime

# Restrict to a particular path.
class RequestHandler(SimpleXMLRPCRequestHandler):
    rpc_paths = ('/RPC2',)
    

class eventsRPC:
    _wait_for_type = ""
    _event_was_type= ""
    
    def __init__(self, event_condition, event_log, verbose):
        self._event_condition = event_condition
        self._event_log = event_log
        self.verbose = verbose
    
    def _inject_event(self, node, timestamp, type, param):
        self.event(node,timestamp,type,param)
    
    def _clear(self):
        self._event_condition.acquire()
        for i in range(len(self._event_log)):
            self._event_log.pop()
        self._event_condition.release()
        
    def event(self, node, timestamp, type, param):
        '''
        This function is called by the RPC clients.
        It puts the received event into a list and
        notifies waiting threads that an event has
        occurred.
        '''
        if self.verbose:
            print "EH: got event %s at %s from %s " % (type,timestamp,node)
        self._event_condition.acquire()
        try:
            self._event_log.append( ( datetime.now(), node, timestamp, type, param ) )
        except:
            print "EH:ERROR"
        self._event_condition.notifyAll()
        self._event_condition.release()
            
        return 0
    
class StoppableRPCServer(SimpleXMLRPCServer):

    stopped = False
    allow_reuse_address = True

    def __init__(self, *args, **kw):
        SimpleXMLRPCServer.__init__(self, *args, **kw)
        self.register_function(lambda: 'OK', 'ping')
        self.is_finally_done = 0
        
    def serve_forever(self):
        while not self.stopped:
            try:
                self.handle_request()
            except Exception, e:
                print "Exception: ",e

        print "EH: Done"
        self.is_finally_done = 1

    def force_stop(self):
        self.stopped = True
        if self.is_finally_done==0:
            self.create_dummy_request()
        self.server_close()
        #self.create_dummy_request()


    def create_dummy_request(self):
        server = xmlrpclib.Server('http://localhost:8000')
        try:
            server.ping()
        except:
            pass
        
class EventHandler:

    def __init__(self,verbose):
        print "EH: Init"
        self.verbose = verbose
        self.event_log = []
        self.event_condition = threading.Condition()
        self.events = eventsRPC(self.event_condition, self.event_log,verbose)
    
    def __del__(self):
        pass    
        
    def inject_event(self, node, timestamp, type, param):
        print "EH: injecting event %s" %(type)
        self.events._inject_event(node, timestamp, type, param)
        print "EH: injection of event done"
        
    def event_thread(self):
        print "EH: Start"
        self.server = StoppableRPCServer(('', 8000),logRequests=False, requestHandler=RequestHandler)
        self.server.register_introspection_functions()
        self.server.register_instance( self.events )
        # Run the server's main loop
        if self.verbose:
            print "EH: Main loop running"
        try:
            self.server.serve_forever()
            print "EH: Stopped serving"
        except (KeyboardInterrupt, SystemExit):
            print "Program was terminated by CTRL+C"

    def clear_log(self):
        self.events._clear()

    def start_event_handler(self):
        # Create server 
        #'' means bind to all addresses
        thread.start_new_thread(self.event_thread, ())
        
        
    def stop_event_handler(self):
        self.server.force_stop()
This module implements an XMLRPC server to asynchonously receive messages (events) from the experiment nodes.  It features a Queue and a mechanism to interact with the ExperiMaster # Restrict to a particular path. This function is called by the RPC clients.         It puts the received event into a list and         notifies waiting threads that an event has         occurred. #self.create_dummy_request() # Run the server's main loop # Create server #'' means bind to all addresses