dispatcher.py :  » Network » FtpCube » ftpcube-0.5.1 » libftpcube » Python Open Source

Home
Python Open Source
1.3.1.2 Python
2.Ajax
3.Aspect Oriented
4.Blog
5.Build
6.Business Application
7.Chart Report
8.Content Management Systems
9.Cryptographic
10.Database
11.Development
12.Editor
13.Email
14.ERP
15.Game 2D 3D
16.GIS
17.GUI
18.IDE
19.Installer
20.IRC
21.Issue Tracker
22.Language Interface
23.Log
24.Math
25.Media Sound Audio
26.Mobile
27.Network
28.Parser
29.PDF
30.Project Management
31.RSS
32.Search
33.Security
34.Template Engines
35.Test
36.UML
37.USB Serial
38.Web Frameworks
39.Web Server
40.Web Services
41.Web Unit
42.Wiki
43.Windows
44.XML
Python Open Source » Network » FtpCube 
FtpCube » ftpcube 0.5.1 » libftpcube » dispatcher.py
"""
FtpCube
Copyright (C) Michael Gilfix

This file is part of FtpCube.

You should have received a file COPYING containing license terms
along with this program; if not, write to Michael Gilfix
(mgilfix@eecs.tufts.edu) for a copy.

This version of FtpCube is open source; you can redistribute it and/or
modify it under the terms listed in the file COPYING.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
"""

import logger

import threading
import time
import exceptions
import traceback

class DispatcherException(exceptions.Exception):
    """Base exception for the dispatching of command objects."""

    def __init__(self, args=None):
        self.args = args

class Dispatcher(threading.Thread):
    """Command dispatcher class.
    
    This class dispatches control session commands in a control session thread.
    Multiple commands may be queued up for dispatching within the thread. This
    class is thread-safe for methods implemented in the base class. Classes
    that extend this class must make sure to protect access to shared data
    structures using the dispatch_lock mutex lock. It is recommended that command
    processing occur within the dispatch thread as much as possible and
    communication with the UI occur via the event system."""

    def __init__(self, **kwargs):
        """Creates an initializes a new thread dispatcher."""
        threading.Thread.__init__(self)
        self.setDaemon(1)

        # Try grabbing the logger argument
        try:
            self.logger = kwargs['logger']
        except KeyError:
            self.logger = None
        if self.logger and not isinstance(self.logger, logger.Logger):
            raise DispatcherException, _("Invalid logger: %(log)s") %{ 'log' : self.logger }
        
        # Initialize instance variables
        self.command_queue = [ ]
        self.current_cmd = None
        self.default_err_handler = None

        # Synchronization
        self.die = threading.Event()
        self.outbound = threading.Event()
        self.dispatch_lock = threading.Lock()

    def setDefaultErrorHandler(self, handler):
        """Sets the default error handler for errors in command execution.
        
        Error handlers set on specific command objects will override the
        default error handler set by this method. This handler should be
        of type ErrorHandler."""
        self.dispatch_lock.acquire()
        self.default_err_handler = handler
        self.dispatch_lock.release()

    def getDefaultErrorHandler(self):
        """Gets the default error handler."""
        self.dispatch_lock.acquire()
        handler = self.default_err_handler
        self.dispatch_lock.release()
        return handler

    def resetQueue(self):
        """Resets the command queue.

        This empties out (discards) the current command queue."""
        self.dispatch_lock.acquire()
        self.command_queue = [ ]
        self.outbound.set()
        self.dispatch_lock.release()

    def destroy(self):
        """Destroys the dispatcher.

        This halts the dispatcher thread on the next iteration of the
        dispatcher loop."""
        self.die.set()
        self.resetQueue()

    def run(self):
        """Main dispatcher loop."""
        while not self.die.isSet():
            cmd = None
            self.dispatch_lock.acquire()
            if self.command_queue:
                cmd = self.command_queue.pop(0)
                self.current_cmd = cmd
            else:
                self.outbound.clear()
            self.dispatch_lock.release()

            if cmd is None:
                self.outbound.wait()
                continue

            if __debug__:
                print "%s dispatching: %s" %(threading.currentThread(), cmd)

            if not isinstance(cmd, DispatcherCommand):
                self.log(logger.Logger.ERROR,
                     _("Warning: attempting to dispatch invalid command object: %(obj)s")
                     %{ 'obj' : cmd })

            try:
                # Dispatch the command object in our thread
                cmd.execute(self)
            except Exception, strerror:
                if __debug__:
                    print "Dispatcher caught an error executing command: %s: %s" \
                        %(Exception, strerror)
                if not self.die.isSet():
                    handler = cmd.getErrorHandler()
                    if isinstance(handler, ErrorHandler):
                        handler.handle(strerror, self)
                    else:
                        self.dispatch_lock.acquire()
                        default_handler = self.default_err_handler
                        self.dispatch_lock.release()
                        if isinstance(default_handler, ErrorHandler):
                            default_handler.handle(strerror, self)
                        else:
                            self.log(logger.Logger.ERROR, strerror)

        if __debug__:
            print "Terminating thread: %s" %str(self)

    def dispatch(self, command):
        """Places a command into the dispatch queue for processing."""
        self.dispatch_lock.acquire()
        self.command_queue.append(command)
        self.outbound.set()
        self.dispatch_lock.release()

    def getExecutingCommand(self):
        """Gets the current executing command.

        This also corresponds to the last command executed if the dispatcher is not
        currently busy."""
        self.dispatch_lock.acquire()
        cmd = self.current_cmd
        self.dispatch_lock.release()
        return cmd

    def busy(self):
        """Indicates whether the dispatcher is currently processing a command."""
        return self.outbound.isSet()

    def log(self, kind, msg):
        """Logger for messages related to command execution."""
        if self.logger:
            self.logger.log(kind, msg)

class DispatcherCommand:
    """Base dispatcher command interface.

    All dispatcher commands should implement this interface. Dispatcher commands
    contain the logic that represents the command within the execute() method.
    This logic executes within the thread of the dispatcher and must be aware of
    dispatcher threading concerns.
    
    Each dispatcher may have its own error handler object. The error handler
    will be called by the dispatcher in the event of execution failure."""

    def __init__(self):
        """Initializes a dispatcher with an empty error handler."""
        self.error_handler = None

    def setErrorHandler(self, handler):
        """Sets the error handler for this command object."""
        self.error_handler = handler

    def getErrorHandler(self):
        """Gets the error handler for this command object."""
        return self.error_handler

    def execute(self, dispatcher):
        """Executes the main logic of the dispatcher command."""
        raise NotImplementedError, _("DispatcherCommand class must implement execute()")

class DispatchStatus:
    """Status object for obtaining status regarding command execution.

    This interface provides a means for command objects to communicate with
    the outside world. The use of status objects are part of the command
    implementation. Long running command (like transfers) may make use of
    this status interface to execute code that will update the UI accordingly
    to reflect the latest command status."""

    def __init__(self):
        """Creates a new dispatch status object with the optional data field
        set to empty."""
        self.opt_data = None

    def setOptionalData(self, data):
        """Sets the optional data for this status object."""
        self.opt_data = data

    def getOptionalData(self):
        """Gets the optional data for this status object."""
        return self.opt_data

    def start(self):
        """Called to indicate the start of command execution."""
        raise NotImplementedError, _("DispatchStatus class must implement start()")

    def update(self, update):
        """Called to provide an update on command execution status.

        The meaning of the update argument depends on implementation."""
        raise NotImplementedError, _("DispatchStatus class must implement update()")

    def finished(self):
        """Called to indicate that command execution has finished."""
        raise NotImplementedError, _("DispatchStatus class must implement finished()")

class ErrorHandler:
    """Base error handler class."""

    def __init__(self):
        pass

    def handle(self, error, dispatcher):
        """Main logic for handling dispatch errors.

        The error argument contains a string indicating the error."""
        # Do nothing by default
        pass

class ErrorLogger(ErrorHandler):
    """Logging error handler class.

    This class logs error strings to the supplied logger. This logger may result in
    the message being logging to the command window console or to a file."""

    def __init__(self, mylogger):
        ErrorHandler.__init__(self)
        if not isinstance(mylogger, logger.Logger):
            raise TypeError, _("Unexpected logger type: %s") %repr(mylogger)
        self.logger = mylogger

    def handle(self, error, dispatcher):
        """Logs the error message to the initialized logger."""
        self.logger.log(logger.Logger.ERROR, error)
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.