Exemplo n.º 1
0
    def complete_io(self, iocb, msg):
        """Called by a handler to return data to the client."""
        if _debug: IOQController._debug("complete_io %r %r", iocb, msg)

        # check to see if it is completing the active one
        if iocb is not self.active_iocb:
            raise RuntimeError, "not the current iocb"

        # normal completion
        IOController.complete_io(self, iocb, msg)

        # no longer an active iocb
        self.active_iocb = None

        # check to see if we should wait a bit
        if self.wait_time:
            # change our state
            self.state = CTRL_WAITING

            # schedule a call in the future
            task = FunctionTask(IOQController._wait_trigger, self)
            task.install_task(_time() + self.wait_time)

        else:
            # change our state
            self.state = CTRL_IDLE

            # look for more to do
            deferred(IOQController._trigger, self)
Exemplo n.º 2
0
    def complete_io(self, iocb, msg):
        """Called by a handler to return data to the client."""
        if _debug: IOQController._debug("complete_io %r %r", iocb, msg)

        # check to see if it is completing the active one
        if iocb is not self.active_iocb:
            raise RuntimeError, "not the current iocb"

        # normal completion
        IOController.complete_io(self, iocb, msg)

        # no longer an active iocb
        self.active_iocb = None

        # check to see if we should wait a bit
        if self.wait_time:
            # change our state
            self.state = CTRL_WAITING

            # schedule a call in the future
            task = FunctionTask(IOQController._wait_trigger, self)
            task.install_task(_time() + self.wait_time)

        else:
            # change our state
            self.state = CTRL_IDLE

            # look for more to do
            deferred(IOQController._trigger, self)
Exemplo n.º 3
0
    def process_io(self, iocb):
        if _debug: SomethingController._debug("process_io %r", iocb)

        # simulate taking some time to complete this request
        task_delta = random.random() * 3.0
        print("{}, {}, {:4.2f}s".format(iocb.args, iocb.kwargs, task_delta))

        task = FunctionTask(self.complete_io, iocb, True)
        task.install_task(delta=task_delta)
        if _debug: SomethingController._debug("    - task: %r", task)
Exemplo n.º 4
0
    def set_timeout(self, delay, err=TimeoutError):
        """Called to set a transaction timer."""
        if _debug:
            IOCB._debug("set_timeout(%d) %r err=%r", self.ioID, delay, err)

        # if one has already been created, cancel it
        if self.ioTimeout:
            self.ioTimeout.suspend_task()
        else:
            self.ioTimeout = FunctionTask(self.abort, err)

        # (re)schedule it
        self.ioTimeout.install_task(_time() + delay)
Exemplo n.º 5
0
    def test_function_task_immediate(self):
        if _debug: TestTimeMachine._debug("test_function_task_immediate")
        global sample_task_function_called

        # create a function task
        ft = FunctionTask(sample_task_function)
        sample_task_function_called = []

        # reset the time machine, install the task, let it run
        reset_time_machine()
        ft.install_task(0.0)
        run_time_machine(60.0)

        # function called, 60 seconds have passed
        assert almost_equal(sample_task_function_called, [0.0])
        assert time_machine.current_time == 60.0
Exemplo n.º 6
0
    def test_function_task_immediate(self):
        if _debug: TestTimeMachine._debug("test_function_task_immediate")
        global sample_task_function_called

        # create a function task
        ft = FunctionTask(sample_task_function)
        sample_task_function_called = 0

        # reset the time machine, install the task, let it run
        reset_time_machine()
        ft.install_task(0.0)
        run_time_machine(60.0)

        # function called, no time has passed
        assert sample_task_function_called == 1
        assert time_machine.current_time == 0.0
Exemplo n.º 7
0
    def test_function_task_immediate(self):
        if _debug:
            TestTimeMachine._debug("test_function_task_immediate")
        global sample_task_function_called

        # create a function task
        ft = FunctionTask(sample_task_function)
        sample_task_function_called = 0

        # reset the time machine, install the task, let it run
        reset_time_machine()
        ft.install_task(0.0)
        run_time_machine(60.0)

        # function called, no time has passed
        assert sample_task_function_called == 1
        assert time_machine.current_time == 0.0
Exemplo n.º 8
0
    def test_function_task_delay(self):
        if _debug: TestTimeMachine._debug("test_function_task_delay")
        global sample_task_function_called

        sample_delay = 10.0

        # create a function task
        ft = FunctionTask(sample_task_function)
        sample_task_function_called = []

        # reset the time machine, install the task, let it run
        reset_time_machine()
        ft.install_task(sample_delay)
        run_time_machine(60.0)

        # function called, no time has passed
        assert almost_equal(sample_task_function_called, [sample_delay])
        assert time_machine.current_time == sample_delay
Exemplo n.º 9
0
    def set_timeout(self, delay, err=TimeoutError):
        """Called to set a transaction timer."""
        if _debug: IOCB._debug("set_timeout(%d) %r err=%r", self.ioID, delay, err)

        # if one has already been created, cancel it
        if self.ioTimeout:
            self.ioTimeout.suspend_task()
        else:
            self.ioTimeout = FunctionTask(self.abort, err)

        # (re)schedule it
        self.ioTimeout.install_task(_time() + delay)
Exemplo n.º 10
0
class IOCB(DebugContents):

    _debugContents = \
        ( 'args', 'kwargs'
        , 'ioState', 'ioResponse-', 'ioError'
        , 'ioController', 'ioServerRef', 'ioControllerRef', 'ioClientID', 'ioClientAddr'
        , 'ioComplete', 'ioCallback+', 'ioQueue', 'ioPriority', 'ioTimeout'
        )

    def __init__(self, *args, **kwargs):
        global _identNext

        # lock the identity sequence number
        _identLock.acquire()

        # generate a unique identity for this block
        ioID = _identNext
        _identNext += 1

        # release the lock
        _identLock.release()

        # debugging postponed until ID acquired
        if _debug: IOCB._debug("__init__(%d) %r %r", ioID, args, kwargs)

        # save the ID
        self.ioID = ioID

        # save the request parameters
        self.args = args
        self.kwargs = kwargs

        # start with an idle request
        self.ioState = IDLE
        self.ioResponse = None
        self.ioError = None

        # blocks are bound to a controller
        self.ioController = None

        # blocks could reference a local or remote server
        self.ioServerRef = None
        self.ioControllerRef = None
        self.ioClientID = None
        self.ioClientAddr = None

        # each block gets a completion event
        self.ioComplete = threading.Event()
        self.ioComplete.clear()

        # applications can set a callback functions
        self.ioCallback = []

        # request is not currently queued
        self.ioQueue = None

        # extract the priority if it was given
        self.ioPriority = kwargs.get('_priority', 0)
        if '_priority' in kwargs:
            if _debug: IOCB._debug("    - ioPriority: %r", self.ioPriority)
            del kwargs['_priority']

        # request has no timeout
        self.ioTimeout = None

    def add_callback(self, fn, *args, **kwargs):
        """Pass a function to be called when IO is complete."""
        if _debug: IOCB._debug("add_callback(%d) %r %r %r", self.ioID, fn, args, kwargs)

        # store it
        self.ioCallback.append((fn, args, kwargs))

        # already complete?
        if self.ioComplete.isSet():
            self.trigger()

    def wait(self, *args):
        """Wait for the completion event to be set."""
        if _debug: IOCB._debug("wait(%d) %r", self.ioID, args)

        # waiting from a non-daemon thread could be trouble
        self.ioComplete.wait(*args)

    def trigger(self):
        """Set the event and make the callback."""
        if _debug: IOCB._debug("trigger(%d)", self.ioID)

        # if it's queued, remove it from its queue
        if self.ioQueue:
            if _debug: IOCB._debug("    - dequeue")
            self.ioQueue.remove(self)

        # if there's a timer, cancel it
        if self.ioTimeout:
            if _debug: IOCB._debug("    - cancel timeout")
            self.ioTimeout.suspend_task()

        # set the completion event
        self.ioComplete.set()

        # make the callback
        for fn, args, kwargs in self.ioCallback:
            if _debug: IOCB._debug("    - callback fn: %r %r %r", fn, args, kwargs)
            fn(self, *args, **kwargs)

    def complete(self, msg):
        """Called to complete a transaction, usually when process_io has
        shipped the IOCB off to some other thread or function."""
        if _debug: IOCB._debug("complete(%d) %r", self.ioID, msg)

        if self.ioController:
            # pass to controller
            self.ioController.complete_io(self, msg)
        else:
            # just fill in the data
            self.ioState = COMPLETED
            self.ioResponse = msg
            self.trigger()

    def abort(self, err):
        """Called by a client to abort a transaction."""
        if _debug: IOCB._debug("abort(%d) %r", self.ioID, err)

        if self.ioController:
            # pass to controller
            self.ioController.abort_io(self, err)
        elif self.ioState < COMPLETED:
            # just fill in the data
            self.ioState = ABORTED
            self.ioError = err
            self.trigger()

    def set_timeout(self, delay, err=TimeoutError):
        """Called to set a transaction timer."""
        if _debug: IOCB._debug("set_timeout(%d) %r err=%r", self.ioID, delay, err)

        # if one has already been created, cancel it
        if self.ioTimeout:
            self.ioTimeout.suspend_task()
        else:
            self.ioTimeout = FunctionTask(self.abort, err)

        # (re)schedule it
        self.ioTimeout.install_task(_time() + delay)

    def __repr__(self):
        xid = id(self)
        if (xid < 0): xid += (1L << 32)

        sname = self.__module__ + '.' + self.__class__.__name__
        desc = "(%d)" % (self.ioID,)

        return '<' + sname + desc + ' instance at 0x%08x' % (xid,) + '>'
Exemplo n.º 11
0
class IOCB(DebugContents):

    _debugContents = \
        ( 'args', 'kwargs'
        , 'ioState', 'ioResponse-', 'ioError'
        , 'ioController', 'ioServerRef', 'ioControllerRef', 'ioClientID', 'ioClientAddr'
        , 'ioComplete', 'ioCallback+', 'ioQueue', 'ioPriority', 'ioTimeout'
        )

    def __init__(self, *args, **kwargs):
        global _identNext

        # lock the identity sequence number
        _identLock.acquire()

        # generate a unique identity for this block
        ioID = _identNext
        _identNext += 1

        # release the lock
        _identLock.release()

        # debugging postponed until ID acquired
        if _debug: IOCB._debug("__init__(%d) %r %r", ioID, args, kwargs)

        # save the ID
        self.ioID = ioID

        # save the request parameters
        self.args = args
        self.kwargs = kwargs

        # start with an idle request
        self.ioState = IDLE
        self.ioResponse = None
        self.ioError = None

        # blocks are bound to a controller
        self.ioController = None

        # blocks could reference a local or remote server
        self.ioServerRef = None
        self.ioControllerRef = None
        self.ioClientID = None
        self.ioClientAddr = None

        # each block gets a completion event
        self.ioComplete = threading.Event()
        self.ioComplete.clear()

        # applications can set a callback functions
        self.ioCallback = []

        # request is not currently queued
        self.ioQueue = None

        # extract the priority if it was given
        self.ioPriority = kwargs.get('_priority', 0)
        if '_priority' in kwargs:
            if _debug: IOCB._debug("    - ioPriority: %r", self.ioPriority)
            del kwargs['_priority']

        # request has no timeout
        self.ioTimeout = None

    def add_callback(self, fn, *args, **kwargs):
        """Pass a function to be called when IO is complete."""
        if _debug:
            IOCB._debug("add_callback(%d) %r %r %r", self.ioID, fn, args,
                        kwargs)

        # store it
        self.ioCallback.append((fn, args, kwargs))

        # already complete?
        if self.ioComplete.isSet():
            self.trigger()

    def wait(self, *args):
        """Wait for the completion event to be set."""
        if _debug: IOCB._debug("wait(%d) %r", self.ioID, args)

        # waiting from a non-daemon thread could be trouble
        self.ioComplete.wait(*args)

    def trigger(self):
        """Set the event and make the callback."""
        if _debug: IOCB._debug("trigger(%d)", self.ioID)

        # if it's queued, remove it from its queue
        if self.ioQueue:
            if _debug: IOCB._debug("    - dequeue")
            self.ioQueue.remove(self)

        # if there's a timer, cancel it
        if self.ioTimeout:
            if _debug: IOCB._debug("    - cancel timeout")
            self.ioTimeout.suspend_task()

        # set the completion event
        self.ioComplete.set()

        # make the callback
        for fn, args, kwargs in self.ioCallback:
            if _debug:
                IOCB._debug("    - callback fn: %r %r %r", fn, args, kwargs)
            fn(self, *args, **kwargs)

    def complete(self, msg):
        """Called to complete a transaction, usually when process_io has
        shipped the IOCB off to some other thread or function."""
        if _debug: IOCB._debug("complete(%d) %r", self.ioID, msg)

        if self.ioController:
            # pass to controller
            self.ioController.complete_io(self, msg)
        else:
            # just fill in the data
            self.ioState = COMPLETED
            self.ioResponse = msg
            self.trigger()

    def abort(self, err):
        """Called by a client to abort a transaction."""
        if _debug: IOCB._debug("abort(%d) %r", self.ioID, err)

        if self.ioController:
            # pass to controller
            self.ioController.abort_io(self, err)
        elif self.ioState < COMPLETED:
            # just fill in the data
            self.ioState = ABORTED
            self.ioError = err
            self.trigger()

    def set_timeout(self, delay, err=TimeoutError):
        """Called to set a transaction timer."""
        if _debug:
            IOCB._debug("set_timeout(%d) %r err=%r", self.ioID, delay, err)

        # if one has already been created, cancel it
        if self.ioTimeout:
            self.ioTimeout.suspend_task()
        else:
            self.ioTimeout = FunctionTask(self.abort, err)

        # (re)schedule it
        self.ioTimeout.install_task(_time() + delay)

    def __repr__(self):
        xid = id(self)
        if (xid < 0): xid += (1L << 32)

        sname = self.__module__ + '.' + self.__class__.__name__
        desc = "(%d)" % (self.ioID, )

        return '<' + sname + desc + ' instance at 0x%08x' % (xid, ) + '>'