activemq-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From "Hiram Chirino" <hi...@hiramchirino.com>
Subject Re: svn commit: r565392 [1/2] - in /activemq/trunk/log_analyzer_tool: ./ loganalyzerengine/ loganalyzergui/ screenshots/
Date Tue, 14 Aug 2007 13:15:58 GMT
Apache Headers???

On 8/13/07, rajdavies@apache.org <rajdavies@apache.org> wrote:
> Author: rajdavies
> Date: Mon Aug 13 09:03:25 2007
> New Revision: 565392
>
> URL: http://svn.apache.org/viewvc?view=rev&rev=565392
> Log:
> Added the log analyser tool to svn - for http://issues.apache.org/activemq/browse/AMQ-1361
>
> Added:
>     activemq/trunk/log_analyzer_tool/
>     activemq/trunk/log_analyzer_tool/Main.py   (with props)
>     activemq/trunk/log_analyzer_tool/README.txt   (with props)
>     activemq/trunk/log_analyzer_tool/loganalyzerengine/
>     activemq/trunk/log_analyzer_tool/loganalyzerengine/Connection.py   (with props)
>     activemq/trunk/log_analyzer_tool/loganalyzerengine/Connection.pyc   (with props)
>     activemq/trunk/log_analyzer_tool/loganalyzerengine/Consumer.py   (with props)
>     activemq/trunk/log_analyzer_tool/loganalyzerengine/Consumer.pyc   (with props)
>     activemq/trunk/log_analyzer_tool/loganalyzerengine/LogFile.py   (with props)
>     activemq/trunk/log_analyzer_tool/loganalyzerengine/LogFile.pyc   (with props)
>     activemq/trunk/log_analyzer_tool/loganalyzerengine/LogParser.py   (with props)
>     activemq/trunk/log_analyzer_tool/loganalyzerengine/LogParser.pyc   (with props)
>     activemq/trunk/log_analyzer_tool/loganalyzerengine/Message.py   (with props)
>     activemq/trunk/log_analyzer_tool/loganalyzerengine/Message.pyc   (with props)
>     activemq/trunk/log_analyzer_tool/loganalyzerengine/Producer.py   (with props)
>     activemq/trunk/log_analyzer_tool/loganalyzerengine/Producer.pyc   (with props)
>     activemq/trunk/log_analyzer_tool/loganalyzerengine/__init__.py   (with props)
>     activemq/trunk/log_analyzer_tool/loganalyzerengine/__init__.pyc   (with props)
>     activemq/trunk/log_analyzer_tool/loganalyzergui/
>     activemq/trunk/log_analyzer_tool/loganalyzergui/Application.py   (with props)
>     activemq/trunk/log_analyzer_tool/loganalyzergui/Application.pyc   (with props)
>     activemq/trunk/log_analyzer_tool/loganalyzergui/DirectoryPanel.py   (with props)
>     activemq/trunk/log_analyzer_tool/loganalyzergui/DirectoryPanel.pyc   (with props)
>     activemq/trunk/log_analyzer_tool/loganalyzergui/IncorrectSequenceList.py   (with props)
>     activemq/trunk/log_analyzer_tool/loganalyzergui/IncorrectSequenceList.pyc   (with props)
>     activemq/trunk/log_analyzer_tool/loganalyzergui/IncorrectSequencePanel.py   (with props)
>     activemq/trunk/log_analyzer_tool/loganalyzergui/IncorrectSequencePanel.pyc   (with props)
>     activemq/trunk/log_analyzer_tool/loganalyzergui/MessageTravelPanel.py   (with props)
>     activemq/trunk/log_analyzer_tool/loganalyzergui/MessageTravelPanel.pyc   (with props)
>     activemq/trunk/log_analyzer_tool/loganalyzergui/MessageTravelText.py   (with props)
>     activemq/trunk/log_analyzer_tool/loganalyzergui/MessageTravelText.pyc   (with props)
>     activemq/trunk/log_analyzer_tool/loganalyzergui/TabbedPanel.py   (with props)
>     activemq/trunk/log_analyzer_tool/loganalyzergui/TabbedPanel.pyc   (with props)
>     activemq/trunk/log_analyzer_tool/loganalyzergui/ViewClientsPanel.py   (with props)
>     activemq/trunk/log_analyzer_tool/loganalyzergui/ViewClientsPanel.pyc   (with props)
>     activemq/trunk/log_analyzer_tool/loganalyzergui/ViewConnectionsPanel.py   (with props)
>     activemq/trunk/log_analyzer_tool/loganalyzergui/ViewConnectionsPanel.pyc   (with props)
>     activemq/trunk/log_analyzer_tool/loganalyzergui/ViewFilesPanel.py   (with props)
>     activemq/trunk/log_analyzer_tool/loganalyzergui/ViewFilesPanel.pyc   (with props)
>     activemq/trunk/log_analyzer_tool/loganalyzergui/__init__.py   (with props)
>     activemq/trunk/log_analyzer_tool/loganalyzergui/__init__.pyc   (with props)
>     activemq/trunk/log_analyzer_tool/run.bat   (with props)
>     activemq/trunk/log_analyzer_tool/run.sh   (with props)
>     activemq/trunk/log_analyzer_tool/screenshots/
>     activemq/trunk/log_analyzer_tool/screenshots/1.png   (with props)
>     activemq/trunk/log_analyzer_tool/screenshots/2.png   (with props)
>     activemq/trunk/log_analyzer_tool/screenshots/3.png   (with props)
>     activemq/trunk/log_analyzer_tool/screenshots/4.png   (with props)
>     activemq/trunk/log_analyzer_tool/screenshots/5.png   (with props)
>
> Added: activemq/trunk/log_analyzer_tool/Main.py
> URL: http://svn.apache.org/viewvc/activemq/trunk/log_analyzer_tool/Main.py?view=auto&rev=565392
> ==============================================================================
> --- activemq/trunk/log_analyzer_tool/Main.py (added)
> +++ activemq/trunk/log_analyzer_tool/Main.py Mon Aug 13 09:03:25 2007
> @@ -0,0 +1,14 @@
> +"""
> +Module Main
> +"""
> +from loganalyzergui.Application import Application
> +
> +def main():
> +    """
> +    Entrance point for the application
> +    """
> +    app = Application(0)
> +    app.MainLoop()
> +
> +if __name__ == '__main__':
> +    main()
> \ No newline at end of file
>
> Propchange: activemq/trunk/log_analyzer_tool/Main.py
> ------------------------------------------------------------------------------
>     svn:executable = *
>
> Added: activemq/trunk/log_analyzer_tool/README.txt
> URL: http://svn.apache.org/viewvc/activemq/trunk/log_analyzer_tool/README.txt?view=auto&rev=565392
> ==============================================================================
> --- activemq/trunk/log_analyzer_tool/README.txt (added)
> +++ activemq/trunk/log_analyzer_tool/README.txt Mon Aug 13 09:03:25 2007
> @@ -0,0 +1,64 @@
> +Readme file for the LogAnalyzer application.
> +
> +1. Requirements:
> +-Python 2.5.1 (http://www.python.org/download/releases/2.5.1/ or your favorite package)
> +-wxPython 2.8.4 (http://www.wxpython.org/download.php or your favorite package)
> +
> +2. How to execute:
> +Run 'python Main.py'.
> +
> +3. Some instructions:
> +-This tool will analyze ActiveMQ log files that have been produced
> +using the 'custom' transport log format. To analyze the files,
> +put them in a directory, choose that directory and click 'Parse'.
> +Please don't put any other kind of files in the same directory
> +(sub-directories won't cause any problem, but the files inside
> +them will not be analyzed).
> +For example, imagine you have a setup with 4 machines: 1 has producers,
> +2 are brokers, and 1 has consumers. As long as you have 1 JVM per machine,
> +you should have 4 log files. Call the files p.log, b1.log, b2.log,
> +and c.log, for example. Put the 4 files in the same directory,
> +choose that directory and click the 'Parse' button.
> +
> +-The first tab of the tool shows incorrect situations at transport level:
> +(i) Messages that were sent through a connection, but were not received
> +at the other end.
> +(ii) Messages that were received through a connection, but were not sent
> +(probably you are missing the log file of the JVM that sent the message).
> +(iii) Messages that are sent 2 times through the same connection.
> +(iv) Messages that were sent 2 times by the same JVM, but through
> +different connections.
> +By clicking the 'Show results with short ids' checkbox, you can switch
> +between the real connection / producer id used by ActiveMQ,
> +or a unique integer assigned by the tool.
> +Often it's easier to compare and browse with this integers than with
> +the original id's which are often long strings.
> +The 'Message id' column shows 2 things: the id of the producer that
> +originally issued the message, and the 'Producer Sequence Id' of a message.
> +These 2 items identify a message in a unique way.
> +
> +You can use the checkboxes to filter per type.
> +You can also filter by a given connection (but then problems of type (iv)
> +will not appear because they 'belong' to more than one connection).
> +You can input a 'long id' (the original ActiveMQ id) or a 'short id'
> +(a short integer assigned by the tool to each connection).
> +
> +-The second tab of the tool allows you to get a lot of information
> +about a single message. Input the producer id of the original producer
> +of the message, and the message's 'Producer Sequence Id'.
> +You can choose to use the original ActiveMQ producer id (long id)
> +or the short integer assigned to a producer by the tool.
> +You can also use the 'Jump to Message Browsing' button of the 1st tab
> +to see the information about the problems of a given message
> +without having to copy the message id manually.
> +In this tab you can also use the 'Show results with short ids' checkbox.
> +
> +-The third tab gives a summary of the clients (producer and consumers)
> +which appear in the log files. Each client is identified by a short id,
> +and belongs to a connection (whose 'short id' and 'long id' are shown).
> +
> +-The fourth tab gives a summary of the connections involved,
> +and the clients that belong to them.
> +
> +-The fifth tab gives a summary of the log files analyzed,
> +and the connections in each of the files.
> \ No newline at end of file
>
> Propchange: activemq/trunk/log_analyzer_tool/README.txt
> ------------------------------------------------------------------------------
>     svn:eol-style = native
>
> Propchange: activemq/trunk/log_analyzer_tool/README.txt
> ------------------------------------------------------------------------------
>     svn:executable = *
>
> Added: activemq/trunk/log_analyzer_tool/loganalyzerengine/Connection.py
> URL: http://svn.apache.org/viewvc/activemq/trunk/log_analyzer_tool/loganalyzerengine/Connection.py?view=auto&rev=565392
> ==============================================================================
> --- activemq/trunk/log_analyzer_tool/loganalyzerengine/Connection.py (added)
> +++ activemq/trunk/log_analyzer_tool/loganalyzerengine/Connection.py Mon Aug 13 09:03:25 2007
> @@ -0,0 +1,337 @@
> +"""
> +Module Connection
> +"""
> +import itertools
> +
> +class Connection(object):
> +    """
> +    This class represents an ActiveMQ Connection.
> +    It also stores a collection of the connections
> +    that have been read in the log files.
> +
> +    A Connection's id is the ActiveMQConnection's id. Since this is usually a long
> +    alphanumerical string, it is called 'longId'.
> +    Each new Connection gets also assigned an integer 'shortId' automatically.
> +    The function of this 'shortId' is to make understanding of displayed data easier.
> +
> +    A Connection has 2 LogFile members, who represent:
> +    -the log file of the JVM that initiates a connection.
> +    -the log file of the JVM that receives a connection request.
> +
> +    The purpose of every Connection is to store the following data:
> +
> +        -messages sent through this connection, as a dictionary where the
> +        key is a tuple (message, direction) and the value is
> +        a list of timestamps. If the message was sent only one time (normal case),
> +        the timestamp list will have 1 item only.
> +
> +        -messages received through this connection, as a dictionary
> +        analogous to the previous one.
> +
> +        -messages sent but not received through this connection, as a list of
> +        tuples (storedMessage, ntimes, timestamps).
> +        'storedMessage' is a (message, direction) tuple
> +        ntimes, an integer, is the number of times a message was sent but not received
> +        timestamps is a list of timestamps of when the message was sent or received.
> +        For a message to be in this list, ntimes must be >= 1.
> +
> +        -messages received but not sent through this connection.
> +        Analog to previous point.
> +
> +        -messages sent more than 2 more times through this connection, as a list of
> +        tuples (storedMessage, ntimes, timestamps).
> +        'storedMessage' is a (message, direction) tuple
> +        ntimes, an integer, is the number of times a message was sent.
> +        timestamps is a list of timestamps of when the message was sent.
> +        For a message to be in this list, ntimes must be >= 2.
> +
> +        -messages received more than 2 more times through this connection.
> +        Identical structure to the previous point.
> +
> +    The 'direction' value is either True or False.
> +    True represents that the message was sent from the JVM writing to the
> +    'from' file, to the JVM writing to the 'to' file.
> +    False represents the opposite.
> +    """
> +
> +    #dictionary whose keys are connection ids, and whose values
> +    #are Connection objects
> +    connections = {}
> +    nConnections = 0
> +    connectionIdList = []
> +
> +    def __init__(self, longId, fromFile = None, toFile = None):
> +        """
> +        Constructs a Connection object.
> +        longId : string
> +        fromFile: LogFile object
> +        to: LogFile object
> +        The ActiveMQConnection's id has to be provided.
> +        Optionally, 2 LogFile objects can be provided.
> +        The 'from' file is the log file of the JVM that initiates a connection.
> +        The 'to' file is the log file of the JVM that receives a connection request.
> +
> +        A new connection gets automatically a new 'shortId', which is an integer.
> +        The longId gets also stored in a list of longIds.
> +
> +        Returns a Connection object.
> +        """
> +
> +        self.longId = longId
> +        self.fromFile = fromFile
> +        self.toFile = toFile
> +
> +        self.shortId = Connection.nConnections
> +        Connection.connectionIdList.append(longId)
> +        Connection.nConnections += 1
> +
> +        self.producers = set()
> +        self.consumers = set()
> +
> +        self.sent = {}
> +        self.received = {}
> +
> +        self.duplicateSent = None
> +        self.duplicateReceived = None
> +        self.sentButNotReceived = None
> +        self.receivedButNotSent = None
> +
> +        self.calculated = False
> +
> +    @classmethod
> +    def clearData(cls):
> +        """
> +        Deletes all information read about connections.
> +
> +        Returns nothing.
> +        """
> +
> +        cls.connections.clear()
> +        cls.nConnections = 0
> +        del cls.connectionIdList[:]
> +
> +    @classmethod
> +    def getConnectionByLongId(cls, longId):
> +        """
> +        Retrieves the connection whose id is 'longId'.
> +        If there is no connection with this id, a new
> +        one is created with this id.
> +
> +        Returns a Connection object.
> +        """
> +
> +        if longId not in cls.connections:
> +            cls.connections[longId] = Connection(longId)
> +
> +        return cls.connections[longId]
> +
> +    @classmethod
> +    def getConnectionByShortId(cls, shortId):
> +        """
> +        Retrieves the connection whose shortId is 'shortId'.
> +        If there is no connection with this id,
> +        an IndexError exception will be thrown.
> +
> +        Returns a Connection object.
> +        Throws an IndexError if the short id does not exist.
> +        """
> +
> +        return cls.connections[cls.connectionIdList[shortId]]
> +
> +    @classmethod
> +    def shortIdToLongId(cls, shortId):
> +        """
> +        Transforms a connection's short id to a long id.
> +        Returns the long id.
> +        Throws an IndexError if the short id does not exist.
> +        """
> +        return cls.connectionIdList[shortId]
> +
> +    @classmethod
> +    def longIdToShortId(cls, longId):
> +        """
> +        Transforms a connection's long id to a short id.
> +        Returns the short id.
> +        Throws an KeyError if the short id does not exist.
> +        """
> +        try:
> +            return cls.connections[longId].shortId
> +        except KeyError:
> +            print longId
> +            print cls.connections
> +            raise
> +
> +    @classmethod
> +    def setFrom(cls, longId, fromFile):
> +        """
> +        Sets the 'from' LogFile object for the connection whose id is 'longId'.
> +        The 'from' file is the log file of the JVM that initiates a connection.
> +        If there is not yet a connection whose id is 'longId', a new one is
> +        created with this longId and this 'from' file.
> +
> +        Returns nothing.
> +        """
> +
> +        if longId not in cls.connections:
> +            cls.connections[longId] = Connection(longId, fromFile = fromFile)
> +        else:
> +            cls.connections[longId].fromFile = fromFile
> +
> +    @classmethod
> +    def setTo(cls, longId, toFile):
> +        """
> +        Sets the 'to' LogFile object for the connection whose id is 'longId'.
> +        The 'to' file is the log file of the JVM that receives a connection request.
> +        If there is not yet a connection whose id is 'longId', a new one is
> +        created with this longId and this 'to' file.
> +
> +        Returns nothing.
> +        """
> +
> +        if longId not in cls.connections:
> +            cls.connections[longId] = Connection(longId, toFile = toFile)
> +        else:
> +            cls.connections[longId].toFile = toFile
> +
> +
> +
> +    @classmethod
> +    def exists(cls, longId):
> +        """
> +        Returns if there is a connection whose id is 'longId'
> +        """
> +
> +        return longId in cls.connections
> +
> +
> +
> +    def addProducer(self, producer):
> +        """
> +        Adds a producer to the set of this connection's producers.
> +        Returns nothing.
> +        """
> +        self.producers.add(producer)
> +
> +    def addConsumer(self, consumer):
> +        """
> +        Adds a consumer to the set of this connection's consumers.
> +        Returns nothing.
> +        """
> +        self.consumers.add(consumer)
> +
> +    def addSentMessage(self, message, direction, timestamp):
> +        """
> +        Adds a message to the set of messages sent through this connection.
> +            message: a Message object
> +            direction: True if this message was sent from self.fromFile to self.to
> +                       False if this message was sent from self.toFile to self.fromFile
> +            timestamp: a string with the time this message was sent
> +
> +        If the message has already been sent in this direction, it gets added to the
> +        collection of duplicate sent messages.
> +
> +        Returns nothing.
> +        """
> +
> +        storedMessage = (message, direction)
> +
> +        if storedMessage in self.sent:
> +            self.sent[storedMessage].append(timestamp)
> +        else:
> +            self.sent[storedMessage] = [timestamp]
> +
> +    def addReceivedMessage(self, message, direction, timestamp):
> +        """
> +        Adds a message to the set of messages received through this connection.
> +            message: a message object
> +            direction: True if this message was sent from self.fromFile to self.to
> +                       False if this message was sent from self.toFile to self.fromFile
> +            timestamp: a string with the time this message was sent
> +
> +        If the message has already been received in this direction, it gets added to the
> +        collection of duplicate received messages.
> +
> +        Returns nothing.
> +        """
> +
> +        storedMessage = (message, direction)
> +
> +        if storedMessage in self.received:
> +            self.received[storedMessage].append(timestamp)
> +        else:
> +            self.received[storedMessage] = [timestamp]
> +
> +    def getErrors(self):
> +        """
> +        Processes the data previously gathered to find incorrect situations.
> +
> +        Returns a 4-tuple with:
> +            -collection of sent but not received messages, through this Connection.
> +            This collection is a list of (storedMessage, ntimes, timestamps) tuples where:
> +               *'storedMessage' is a (message, direction) tuple.
> +               *'ntimes' is an integer, representing how many times the message was sent but not received.
> +               *'timestamps' is a list of strings with the timestamps when this message was sent / received.
> +
> +            -collection of received but not sent messages, through this Connection.
> +            This collection is a list of (storedMessage, ntimes, timestamps) tuples where:
> +               *'storedMessage' is a (message, direction) tuple.
> +               *'ntimes' is an integer, representing how many times the message was received but not sent.
> +               *'timestamps' is a list of strings with the timestamps when this message was sent / received.
> +
> +            -collection of duplicate sent messages, through this Connection.
> +            This collection is a list of (message, timestamps) tuples where:
> +               *'storedMessage' is a (shortId, commandId, direction) tuple.
> +               *'ntimes' is an integer, representing how many times the message sent.
> +               *'timestamps' is a list of strings with the timestamps when this message was sent.
> +
> +            -collection of duplicate received messages, through this Connection.
> +            This collection is a list of (message, timestamps) tuples where:
> +               *'storedMessage' is a (message, direction) tuple.
> +               *'ntimes' is an integer, representing how many times the message received.
> +               *'timestamps' is a list of strings with the timestamps when this message was received.
> +
> +        The data is only calculated once, and then successive calls of this method return always
> +        the same erros unles self.calculated is set to False.
> +        """
> +
> +        if not self.calculated:
> +            self.sentButNotReceived = []
> +            for message, timestamps in self.sent.iteritems():
> +                if message not in self.received:
> +                    self.sentButNotReceived.append((message, len(timestamps), timestamps))
> +                else:
> +                    difference = len(timestamps) - len(self.received[message])
> +                    if difference > 0:
> +                        self.sentButNotReceived.append((message, difference,
> +                                                        itertools.chain(timestamps, self.received[message])))
> +
> +            self.receivedButNotSent = []
> +            for message, timestamps in self.received.iteritems():
> +                if message not in self.sent:
> +                    self.receivedButNotSent.append((message, len(timestamps), timestamps))
> +                else:
> +                    difference = len(timestamps) - len(self.sent[message])
> +                    if difference > 0:
> +                        self.receivedButNotSent.append((message, difference,
> +                                                        itertools.chain(timestamps, self.sent[message])))
> +
> +            self.duplicateSent = [(message, len(timestamps), timestamps)
> +                                  for message, timestamps in self.sent.iteritems() if len(timestamps) > 1]
> +            self.duplicateReceived  = [(message, len(timestamps), timestamps)
> +                                       for message, timestamps in self.received.iteritems() if len(timestamps) > 1]
> +
> +            self.sentButNotReceived.sort(key = lambda message: (message[0][0].producer.shortId, message[0][0].prodSeqId))
> +            self.receivedButNotSent.sort(key = lambda message: (message[0][0].producer.shortId, message[0][0].prodSeqId))
> +            self.duplicateSent.sort(key = lambda message: (message[0][0].producer.shortId, message[0][0].prodSeqId))
> +            self.duplicateReceived.sort(key = lambda message: (message[0][0].producer.shortId, message[0][0].prodSeqId))
> +
> +            self.calculated = True
> +
> +        return self.sentButNotReceived, self.receivedButNotSent, self.duplicateSent, self.duplicateReceived
> +
> +    def __str__(self):
> +        """
> +        Represents this Connection object as a string.
> +        """
> +
> +        return ''.join([self.longId, ' from:', str(self.fromFile), ' to:', str(self.toFile)])
> \ No newline at end of file
>
> Propchange: activemq/trunk/log_analyzer_tool/loganalyzerengine/Connection.py
> ------------------------------------------------------------------------------
>     svn:executable = *
>
> Added: activemq/trunk/log_analyzer_tool/loganalyzerengine/Connection.pyc
> URL: http://svn.apache.org/viewvc/activemq/trunk/log_analyzer_tool/loganalyzerengine/Connection.pyc?view=auto&rev=565392
> ==============================================================================
> Binary file - no diff available.
>
> Propchange: activemq/trunk/log_analyzer_tool/loganalyzerengine/Connection.pyc
> ------------------------------------------------------------------------------
>     svn:executable = *
>
> Propchange: activemq/trunk/log_analyzer_tool/loganalyzerengine/Connection.pyc
> ------------------------------------------------------------------------------
>     svn:mime-type = application/octet-stream
>
> Added: activemq/trunk/log_analyzer_tool/loganalyzerengine/Consumer.py
> URL: http://svn.apache.org/viewvc/activemq/trunk/log_analyzer_tool/loganalyzerengine/Consumer.py?view=auto&rev=565392
> ==============================================================================
> --- activemq/trunk/log_analyzer_tool/loganalyzerengine/Consumer.py (added)
> +++ activemq/trunk/log_analyzer_tool/loganalyzerengine/Consumer.py Mon Aug 13 09:03:25 2007
> @@ -0,0 +1,76 @@
> +"""
> +Module Consumer
> +"""
> +
> +class Consumer(object):
> +    """
> +    This class represents an ActiveMQ Consumer.
> +    Each consumer is identified by its long id.
> +    However each consumer also has a short id (an integer) to identify it more easily.
> +    """
> +
> +    nConsumers = 0
> +    consumerIdList = []
> +    consumers = {}
> +
> +    def __init__(self, longId):
> +        """
> +        Constructor
> +        """
> +
> +        self.longId = longId
> +        self.shortId = Consumer.nConsumers
> +
> +        self.connectionId, sessionId, value = longId.rsplit(':', 2)
> +        self.sessionId = int(sessionId)
> +        self.value = int(value)
> +
> +        Consumer.consumers[longId] = self
> +        Consumer.consumerIdList.append(self.longId)
> +        Consumer.nConsumers += 1
> +
> +    @classmethod
> +    def clearData(cls):
> +        """
> +        Deletes all information read about Consumers.
> +
> +        Returns nothing.
> +        """
> +
> +        cls.consumers.clear()
> +        cls.nConsumers = 0
> +        del cls.consumerIdList[:]
> +
> +    @classmethod
> +    def getConsumerByLongId(cls, longId):
> +        """
> +        Returns a consumer given its long id.
> +        If there is no consumer with this long id yet, it will be created.
> +        """
> +
> +        if longId not in cls.consumers:
> +            cls.consumers[longId] = Consumer(longId)
> +
> +        return cls.consumers[longId]
> +
> +    @classmethod
> +    def shortIdToLongId(cls, shortId):
> +        """
> +        Transforms a consumer's short id to a long id.
> +
> +        Returns a long id.
> +        Throws an IndexError if the short id does not exist.
> +        """
> +
> +        return cls.consumerIdList[shortId]
> +
> +    @classmethod
> +    def longIdToShortId(cls, longId):
> +        """
> +        Transforms a consumer's long id to a short id.
> +
> +        Returns a long id.
> +        Throws an KeyError if the long id does not exist.
> +        """
> +        return cls.consumers[longId].shortId
> +
>
> Propchange: activemq/trunk/log_analyzer_tool/loganalyzerengine/Consumer.py
> ------------------------------------------------------------------------------
>     svn:executable = *
>
> Added: activemq/trunk/log_analyzer_tool/loganalyzerengine/Consumer.pyc
> URL: http://svn.apache.org/viewvc/activemq/trunk/log_analyzer_tool/loganalyzerengine/Consumer.pyc?view=auto&rev=565392
> ==============================================================================
> Binary file - no diff available.
>
> Propchange: activemq/trunk/log_analyzer_tool/loganalyzerengine/Consumer.pyc
> ------------------------------------------------------------------------------
>     svn:executable = *
>
> Propchange: activemq/trunk/log_analyzer_tool/loganalyzerengine/Consumer.pyc
> ------------------------------------------------------------------------------
>     svn:mime-type = application/octet-stream
>
> Added: activemq/trunk/log_analyzer_tool/loganalyzerengine/LogFile.py
> URL: http://svn.apache.org/viewvc/activemq/trunk/log_analyzer_tool/loganalyzerengine/LogFile.py?view=auto&rev=565392
> ==============================================================================
> --- activemq/trunk/log_analyzer_tool/loganalyzerengine/LogFile.py (added)
> +++ activemq/trunk/log_analyzer_tool/loganalyzerengine/LogFile.py Mon Aug 13 09:03:25 2007
> @@ -0,0 +1,187 @@
> +"""
> +Module LogFile
> +"""
> +import os
> +
> +class LogFile(object):
> +    """
> +    Class that represents an ActiveMQ log file read by the application.
> +    It also stores a list of all the LogFile objects.
> +
> +    A LogFile object stores the following information:
> +    -A list of 'outgoing' Connection objects that represent the connections
> +    created by the JVM that writes this LogFile.
> +    -A list of 'incoming' Connection objects that represent the connections
> +    requests received by the JVM that writes this LogFile.
> +
> +    -A dictionary of messages that were sent in this file.
> +    The keys are Message objects and the values
> +    are lists of timestamps of when the message was sent.
> +    -A list of messages that were received in this file.
> +    The keys are Message objects and the values
> +    are lists of timestamps of when the message was received.
> +
> +    -A list of messages that were sent in this file more than 1 time (duplicates)
> +    The list is made of (message, ntimes, timestamps) tuples.
> +    -A list of messages that were received in this file more than 1 time (duplicates),
> +    analogous to the previous structure.
> +    """
> +
> +    logfiles = []
> +
> +    def __init__(self, path):
> +        """
> +        Constructs a LogFile object.
> +        path: a string with the path to the ActiveMQ log file.
> +        """
> +
> +        self.__path = os.path.abspath(path)
> +        self.file = open(self.__path, 'r')
> +        self.outgoing = []
> +        self.incoming = []
> +
> +        self.sent = {}
> +        self.received = {}
> +
> +        self.duplicateReceived = None
> +        self.duplicateSent = None
> +
> +        self.calculated = False
> +
> +        LogFile.logfiles.append(self)
> +
> +    @classmethod
> +    def clearData(cls):
> +        """
> +        Class method erases all the LogFile objects stored in the LogFile class.
> +        Returns nothing.
> +        """
> +
> +        del cls.logfiles[:]
> +
> +    @classmethod
> +    def closeFiles(cls):
> +        """
> +        Class method that closes all the LogFile objects stored in the LogFile class.
> +        Returns nothing.
> +        """
> +
> +        for logFile in cls.logfiles:
> +            logFile.file.close()
> +
> +
> +
> +    def addOutgoingConnection(self, con):
> +        """
> +        Adds an 'outgoing' Connection object to this LogFile.
> +        Returns nothing.
> +        """
> +
> +        self.outgoing.append(con)
> +
> +    def addIncomingConnection(self, con):
> +        """
> +        Adds an 'incoming' Connection object to this LogFile.
> +        Returns nothing.
> +        """
> +
> +        self.incoming.append(con)
> +
> +    def addSentMessage(self, message, timestamp):
> +        """
> +        Adds a message to the set of messages that were sent thtough this file.
> +        If a message gets sent 2 times, it gets added to the set of duplicate sent messages.
> +        message: a Message object.
> +        timestamp: a string with the time where this message was sent.
> +
> +        Returns nothing.
> +        """
> +
> +        if message in self.sent:
> +            self.sent[message].append(timestamp)
> +        else:
> +            self.sent[message] = [timestamp]
> +
> +    def addReceivedMessage(self, message, timestamp):
> +        """
> +        Adds a message to the set of messages that were received in this file.
> +        If a message gets sent 2 times, it gets added to the set of duplicate received messages.
> +        message: a Message object.
> +        timestamp: a string with the time where this message was sent.
> +
> +        Returns nothing.
> +        """
> +
> +        #message = (shortProdId, prodSeqId, False)
> +        if message in self.received:
> +            self.received[message].append(timestamp)
> +        else:
> +            self.received[message] = [timestamp]
> +
> +    def getErrors(self):
> +        """
> +        Returns a 2-tuple with:
> +            -a list of (message, ntimes, timestamps) tuples, with the duplicate sent messages
> +            that appear in more than one connection in this file.
> +            'message' is a Message object.
> +            'ntimes' is an integer stating how many times the message was sent ( always >= 2)
> +            'timestamps' is a list of timestamps with the instants the message was sent.
> +
> +            -a list of (message, ntimes, timestamps) tuples, with the duplicate received messages
> +            that appear in more than one connection in this file.
> +            Structure analogous to previous one.
> +
> +        The data is only calculated once, and then successive calls of this method return always
> +        the same erros unles self.calculated is set to False.
> +        """
> +
> +        if not self.calculated:
> +
> +            duplicateSentTemp = [(message, len(timestamps), timestamps)
> +                                 for message, timestamps in self.sent.iteritems() if len(timestamps) > 1]
> +            self.duplicateSent = []
> +
> +            for message, _, timestamps in duplicateSentTemp:
> +                connections = []
> +                for connection, direction in message.sendingConnections:
> +                    if direction and connection.fromFile == self       \
> +                    or not direction and connection.toFile == self:
> +                        connections.append(connection)
> +                if len(connections) > 1:
> +                    self.duplicateSent.append((message, len(timestamps), timestamps))
> +
> +            duplicateReceivedTemp = [(message, len(timestamps), timestamps)
> +                                      for message, timestamps in self.received.iteritems() if len(timestamps) > 1]
> +            self.duplicateReceived = []
> +
> +            for message, _, timestamps in duplicateReceivedTemp:
> +                connections = []
> +                for connection, direction in message.receivingConnections:
> +                    if direction and connection.toFile == self       \
> +                    or not direction and connection.fromFile == self:
> +                        connections.append(connection)
> +                if len(connections) > 1:
> +                    self.duplicateReceived.append((message, len(timestamps), timestamps))
> +
> +            self.duplicateSent.sort(key = lambda message: (message[0].producer.shortId, message[0].prodSeqId))
> +            self.duplicateReceived.sort(key = lambda message: (message[0].producer.shortId, message[0].prodSeqId))
> +
> +            self.calculated = True
> +
> +        return self.duplicateSent, self.duplicateReceived
> +
> +    def close(self):
> +        """
> +        Closes the underlying file.
> +        Returns nothing.
> +        """
> +
> +        self.file.close()
> +
> +    def __str__(self):
> +        """
> +        Returns a string representation of this object.
> +        """
> +
> +        return self.__path
> +
>
> Propchange: activemq/trunk/log_analyzer_tool/loganalyzerengine/LogFile.py
> ------------------------------------------------------------------------------
>     svn:executable = *
>
> Added: activemq/trunk/log_analyzer_tool/loganalyzerengine/LogFile.pyc
> URL: http://svn.apache.org/viewvc/activemq/trunk/log_analyzer_tool/loganalyzerengine/LogFile.pyc?view=auto&rev=565392
> ==============================================================================
> Binary file - no diff available.
>
> Propchange: activemq/trunk/log_analyzer_tool/loganalyzerengine/LogFile.pyc
> ------------------------------------------------------------------------------
>     svn:executable = *
>
> Propchange: activemq/trunk/log_analyzer_tool/loganalyzerengine/LogFile.pyc
> ------------------------------------------------------------------------------
>     svn:mime-type = application/octet-stream
>
> Added: activemq/trunk/log_analyzer_tool/loganalyzerengine/LogParser.py
> URL: http://svn.apache.org/viewvc/activemq/trunk/log_analyzer_tool/loganalyzerengine/LogParser.py?view=auto&rev=565392
> ==============================================================================
> --- activemq/trunk/log_analyzer_tool/loganalyzerengine/LogParser.py (added)
> +++ activemq/trunk/log_analyzer_tool/loganalyzerengine/LogParser.py Mon Aug 13 09:03:25 2007
> @@ -0,0 +1,188 @@
> +"""
> +Module LogParser
> +"""
> +import os, sys, time
> +
> +from LogFile import LogFile
> +from Connection import Connection
> +from Producer import Producer
> +from Consumer import Consumer
> +from Message import Message
> +
> +MESSAGE_TYPES = frozenset(['ActiveMQBytesMessage', 'ActiveMQTextMessage'])
> +DISPATCH_MESSAGE = 'MessageDispatch'
> +ADVISORY_TEXT = 'Advisory'
> +CONSUMER_TEXT = 'toConsumer:'
> +
> +class LogParser(object):
> +    """
> +    This class is in charge of parsing the log files and storing the data
> +    as Connection, LogFile and Message objects.
> +    """
> +
> +    instance = None
> +
> +    @classmethod
> +    def getInstance(cls):
> +        """
> +        Returns the sole instance of the class.
> +        """
> +
> +        if cls.instance is None:
> +            cls.instance = LogParser()
> +        return cls.instance
> +
> +    @classmethod
> +    def deleteInstance(cls):
> +        """
> +        Deletes the sole instance of the class
> +        """
> +
> +        cls.instance = None
> +
> +    def parse (self, logFile):
> +        """
> +        Parses the information in a log file.
> +        logFile should be a LogFile object.
> +
> +        Returns nothing.
> +        """
> +        try:
> +            for line in logFile.file:
> +                loggedMessage = line.partition('$$ ')[2]
> +                if loggedMessage != '':
> +                    spacedStrings = loggedMessage.split()
> +
> +                    if spacedStrings[1] == 'ConnectionInfo':
> +                        connectionId = spacedStrings[3]
> +
> +                        if spacedStrings[0] == 'SENDING:':
> +                            logFile.addOutgoingConnection(Connection.getConnectionByLongId(connectionId))
> +                            Connection.setFrom(connectionId, logFile)
> +
> +                        elif spacedStrings[0] == 'RECEIVED:':
> +                            logFile.addIncomingConnection(Connection.getConnectionByLongId(connectionId))
> +                            Connection.setTo(connectionId, logFile)
> +
> +                        else:
> +                            raise Exception('Exception: ConnectionInfo: not SENDING or RECEIVED')
> +
> +                    elif spacedStrings[1] in MESSAGE_TYPES or spacedStrings[1] == DISPATCH_MESSAGE:
> +                        timestamp = line[0:23]
> +                        commaValues = spacedStrings[3].split(',')
> +
> +                        messageId = commaValues[0]
> +                        producerId = messageId[:messageId.rindex(':')]
> +
> +                        connection = Connection.getConnectionByLongId(commaValues[2]) #commaValues[2] = connectionId
> +                        producer = Producer.getProducerByLongId(producerId)
> +                        producerConnection = Connection.getConnectionByLongId(producerId.rsplit(':', 2)[0]) #producerConnectionId
> +                        message = Message.getMessage(producer,
> +                                                     int(messageId[messageId.rindex(':') + 1:]), #producerSequenceId
> +                                                     commaValues[-1] == ADVISORY_TEXT)
> +
> +                        producerConnection.addProducer(producer)
> +
> +                        if spacedStrings[1] in MESSAGE_TYPES:
> +
> +                            if spacedStrings[0] == 'SENDING:':
> +
> +                                direction = (logFile == connection.fromFile)
> +                                connection.addSentMessage(message, direction, timestamp)
> +                                logFile.addSentMessage(message, timestamp)
> +                                message.addSendingConnection(connection, direction, connection,
> +                                                             int(commaValues[1]), timestamp) #commaValues[1] = commandId
> +
> +                            elif spacedStrings[0] == 'RECEIVED:':
> +
> +                                direction = (logFile == connection.toFile)
> +                                connection.addReceivedMessage(message, direction, timestamp)
> +                                logFile.addReceivedMessage(message, timestamp)
> +                                message.addReceivingConnection(connection, direction, connection,
> +                                                               int(commaValues[1]), timestamp) #commaValues[1] = commandId
> +
> +                        elif spacedStrings[1] == DISPATCH_MESSAGE:
> +
> +                            #additional parsing to get the consumer
> +                            consumerId = spacedStrings[4][len(CONSUMER_TEXT):]
> +                            consumer = Consumer.getConsumerByLongId(consumerId)
> +                            consumerConnection = Connection.getConnectionByLongId(':'.join(consumerId.split(':')[:3]))
> +                            consumerConnection.addConsumer(consumer)
> +
> +                            if spacedStrings[0] == 'SENDING:':
> +
> +                                direction = (logFile == connection.fromFile)
> +                                consumerConnection.addSentMessage(message, direction, timestamp)
> +                                logFile.addSentMessage(message, timestamp)
> +                                message.addSendingConnection(consumerConnection, direction, connection,
> +                                                             int(commaValues[1]), timestamp) #commaValues[1] = commandId
> +
> +                            elif spacedStrings[0] == 'RECEIVED:':
> +
> +                                direction = (logFile == connection.toFile)
> +                                consumerConnection.addReceivedMessage(message, direction, timestamp)
> +                                logFile.addReceivedMessage(message, timestamp)
> +                                message.addReceivingConnection(consumerConnection, direction, connection,
> +                                                               int(commaValues[1]), timestamp) #commaValues[1] = commandId
> +
> +        except Exception:
> +            print logFile, line
> +            raise
> +
> +
> +    def clearData(self):
> +        """
> +        Clears all the data parsed.
> +        """
> +
> +        Connection.clearData()
> +        Producer.clearData()
> +        Consumer.clearData()
> +        Message.clearData()
> +        LogFile.clearData()
> +
> +    def parseDirectory(self, directory):
> +        """
> +        Parses a directory of log files.
> +        """
> +
> +        self.clearData()
> +
> +        fileNames = os.walk(directory).next()[2]
> +        logFiles = [LogFile(directory + os.sep + fileName) for fileName in fileNames]
> +
> +        for logFile in logFiles:
> +            self.parse(logFile)
> +
> +        LogFile.closeFiles()
> +
> +def main():
> +    """
> +    Entrance point for the command line test.
> +    """
> +
> +    if len(sys.argv) != 2:
> +        print 'Usage: python LogParser.py directory'
> +    else:
> +        startTime = time.time()
> +        LogParser.getInstance().parseDirectory(sys.argv[1])
> +        LogParser.deleteInstance()
> +        print str(Message.messageCount) + ' messages parsed'
> +        print 'in ' + str(time.time() - startTime) + ' seconds'
> +
> +        print 'press a key'
> +        sys.stdin.read(3)
> +
> +        startTime = time.time()
> +        for connection in Connection.connections.itervalues():
> +            connection.getErrors()
> +
> +        for logFile in LogFile.logfiles:
> +            logFile.getErrors()
> +
> +        print 'additional: ' + str(time.time() - startTime) + ' seconds'
> +        time.sleep(36000)
> +
> +if __name__ == '__main__':
> +    main()
> +
> \ No newline at end of file
>
> Propchange: activemq/trunk/log_analyzer_tool/loganalyzerengine/LogParser.py
> ------------------------------------------------------------------------------
>     svn:executable = *
>
> Added: activemq/trunk/log_analyzer_tool/loganalyzerengine/LogParser.pyc
> URL: http://svn.apache.org/viewvc/activemq/trunk/log_analyzer_tool/loganalyzerengine/LogParser.pyc?view=auto&rev=565392
> ==============================================================================
> Binary file - no diff available.
>
> Propchange: activemq/trunk/log_analyzer_tool/loganalyzerengine/LogParser.pyc
> ------------------------------------------------------------------------------
>     svn:executable = *
>
> Propchange: activemq/trunk/log_analyzer_tool/loganalyzerengine/LogParser.pyc
> ------------------------------------------------------------------------------
>     svn:mime-type = application/octet-stream
>
> Added: activemq/trunk/log_analyzer_tool/loganalyzerengine/Message.py
> URL: http://svn.apache.org/viewvc/activemq/trunk/log_analyzer_tool/loganalyzerengine/Message.py?view=auto&rev=565392
> ==============================================================================
> --- activemq/trunk/log_analyzer_tool/loganalyzerengine/Message.py (added)
> +++ activemq/trunk/log_analyzer_tool/loganalyzerengine/Message.py Mon Aug 13 09:03:25 2007
> @@ -0,0 +1,120 @@
> +"""
> +Module Message
> +"""
> +
> +class Message(object):
> +    """
> +    Objects of this class represent ActiveMQ messages.
> +    They are used to store the 'travel path' of every message.
> +    This class also stores a collection of all the Message objects.
> +    """
> +
> +    messages = {}
> +    messageCount = 0
> +
> +    def __init__(self, producer, prodSeqId, advisory):
> +        """
> +        Constructs a message object, given a producer and producer sequence id.
> +        """
> +
> +        self.producer = producer
> +        self.prodSeqId = prodSeqId
> +        self.advisory = advisory
> +        self.sendingConnections = {}
> +        self.receivingConnections = {}
> +
> +        Message.messageCount += 1
> +
> +    @classmethod
> +    def clearData(cls):
> +        """
> +        Deletes all the messages.
> +        Returns nothing.
> +        """
> +
> +        cls.messages.clear()
> +        cls.messageCount = 0
> +
> +    @classmethod
> +    def getMessage(cls, producer, prodSeqId, advisory = False):
> +        """
> +        Returns the Message object identified by (producer, prodSeqId)
> +        where producer is a producer object and prodSeqId is a producer sequence id
> +        message was first sent.
> +
> +        If the Message object does not exist, it will be created.
> +        Returns a Message object.
> +        """
> +
> +        messageId = (producer, prodSeqId)
> +
> +        if messageId not in cls.messages:
> +            cls.messages[messageId] = Message(producer, prodSeqId, advisory)
> +
> +        return cls.messages[messageId]
> +
> +    @classmethod
> +    def exists(cls, producer, prodSeqId):
> +        """
> +        Returns if there is a Message object identified by (producer, prodSeqId)
> +        """
> +
> +        return (producer, prodSeqId) in cls.messages
> +
> +    def addSendingConnection(self, connection, direction, mostRecentConId, commandId, timestamp):
> +        """
> +        Adds a connection to the set of connections through which this message was sent.
> +        The 'direction' argument is True if the message was sent from the file
> +        connection.fromFile to the file connection.toFile, and False otherwise.
> +        'timestamp' is a string with the moment this message was sent trough the connection.
> +
> +        Returns nothing.
> +        """
> +
> +        storedConnection = (connection, direction)
> +        if storedConnection in self.sendingConnections:
> +            self.sendingConnections[storedConnection].append((mostRecentConId, commandId, timestamp))
> +        else:
> +            self.sendingConnections[storedConnection] = [(mostRecentConId, commandId, timestamp)]
> +
> +    def addReceivingConnection(self, connection, direction, mostRecentConId, commandId, timestamp):
> +        """
> +        Adds a connection to the set of connections where this message was received.
> +        The 'direction' argument is True if the message was sent from the file
> +        connection.fromFile to the file connection.toFile, and False otherwise.
> +        'timestamp' is a string with the moment this message was received trough the connection.
> +
> +        Returns nothing.
> +        """
> +
> +        storedConnection = (connection, direction)
> +        if storedConnection in self.receivingConnections:
> +            self.receivingConnections[storedConnection].append((mostRecentConId, commandId, timestamp))
> +        else:
> +            self.receivingConnections[storedConnection] = [(mostRecentConId, commandId, timestamp)]
> +
> +    def getFiles(self):
> +        """
> +        Returns a 2-tuple with the following 2 sets:
> +            -set of LogFile objects where this message was sent.
> +            -set of LogFile objects where this message was received.
> +        """
> +
> +        sendingFiles = set()
> +        receivingFiles = set()
> +
> +        for connection, direction in self.sendingConnections:
> +
> +            if direction:
> +                sendingFiles.add(connection.fromFile)
> +            else:
> +                sendingFiles.add(connection.toFile)
> +
> +        for connection, direction in self.receivingConnections:
> +
> +            if direction:
> +                receivingFiles.add(connection.toFile)
> +            else:
> +                receivingFiles.add(connection.fromFile)
> +
> +        return sendingFiles, receivingFiles
> \ No newline at end of file
>
> Propchange: activemq/trunk/log_analyzer_tool/loganalyzerengine/Message.py
> ------------------------------------------------------------------------------
>     svn:executable = *
>
> Added: activemq/trunk/log_analyzer_tool/loganalyzerengine/Message.pyc
> URL: http://svn.apache.org/viewvc/activemq/trunk/log_analyzer_tool/loganalyzerengine/Message.pyc?view=auto&rev=565392
> ==============================================================================
> Binary file - no diff available.
>
> Propchange: activemq/trunk/log_analyzer_tool/loganalyzerengine/Message.pyc
> ------------------------------------------------------------------------------
>     svn:executable = *
>
> Propchange: activemq/trunk/log_analyzer_tool/loganalyzerengine/Message.pyc
> ------------------------------------------------------------------------------
>     svn:mime-type = application/octet-stream
>
> Added: activemq/trunk/log_analyzer_tool/loganalyzerengine/Producer.py
> URL: http://svn.apache.org/viewvc/activemq/trunk/log_analyzer_tool/loganalyzerengine/Producer.py?view=auto&rev=565392
> ==============================================================================
> --- activemq/trunk/log_analyzer_tool/loganalyzerengine/Producer.py (added)
> +++ activemq/trunk/log_analyzer_tool/loganalyzerengine/Producer.py Mon Aug 13 09:03:25 2007
> @@ -0,0 +1,94 @@
> +"""
> +Module Producer
> +"""
> +
> +class Producer(object):
> +    """
> +    This class represents an ActiveMQ Producer.
> +    Each producer is identified by its long id.
> +    However each producer also has a short id (an integer) to identify it more easily.
> +    """
> +
> +    nProducers = 0
> +    producerIdList = []
> +    producers = {}
> +
> +    def __init__(self, longId):
> +        """
> +        Constructor
> +        """
> +
> +        self.longId = longId
> +        self.shortId = Producer.nProducers
> +
> +        self.connectionId, sessionId, value = longId.rsplit(':', 2)
> +        self.sessionId = int(sessionId)
> +        self.value = int(value)
> +
> +        Producer.producers[longId] = self
> +        Producer.producerIdList.append(self.longId)
> +        Producer.nProducers += 1
> +
> +    @classmethod
> +    def clearData(cls):
> +        """
> +        Deletes all information read about producers.
> +
> +        Returns nothing.
> +        """
> +
> +        cls.producers.clear()
> +        cls.nProducers = 0
> +        del cls.producerIdList[:]
> +
> +    @classmethod
> +    def getProducerByLongId(cls, longId):
> +        """
> +        Returns a producer given its long id.
> +        If there is no producer with this long id yet, it will be created.
> +        """
> +
> +        if longId not in cls.producers:
> +            cls.producers[longId] = Producer(longId)
> +
> +        return cls.producers[longId]
> +
> +    @classmethod
> +    def getProducerByShortId(cls, shortId):
> +        """
> +        Returns a producer given its short id.
> +        If there is no producer with thi short id yet, IndexError will be thrown.
> +        """
> +
> +        return cls.producers[cls.producerIdList[shortId]]
> +
> +    @classmethod
> +    def exists(cls, longid):
> +        """
> +        Returns if a producer with the given long id exists.
> +        """
> +
> +        return longid in cls.producers
> +
> +    @classmethod
> +    def shortIdToLongId(cls, shortId):
> +        """
> +        Transforms a producer's short id to a long id.
> +
> +        Returns a long id.
> +        Throws an IndexError if the short id does not exist.
> +        """
> +
> +        return cls.producerIdList[shortId]
> +
> +    @classmethod
> +    def longIdToShortId(cls, longId):
> +        """
> +        Transforms a producer's long id to a short id.
> +
> +        Returns a long id.
> +        Throws an KeyError if the long id does not exist.
> +        """
> +        return cls.producers[longId].shortId
> +
> +
> \ No newline at end of file
>
> Propchange: activemq/trunk/log_analyzer_tool/loganalyzerengine/Producer.py
> ------------------------------------------------------------------------------
>     svn:executable = *
>
> Added: activemq/trunk/log_analyzer_tool/loganalyzerengine/Producer.pyc
> URL: http://svn.apache.org/viewvc/activemq/trunk/log_analyzer_tool/loganalyzerengine/Producer.pyc?view=auto&rev=565392
> ==============================================================================
> Binary file - no diff available.
>
> Propchange: activemq/trunk/log_analyzer_tool/loganalyzerengine/Producer.pyc
> ------------------------------------------------------------------------------
>     svn:executable = *
>
> Propchange: activemq/trunk/log_analyzer_tool/loganalyzerengine/Producer.pyc
> ------------------------------------------------------------------------------
>     svn:mime-type = application/octet-stream
>
> Added: activemq/trunk/log_analyzer_tool/loganalyzerengine/__init__.py
> URL: http://svn.apache.org/viewvc/activemq/trunk/log_analyzer_tool/loganalyzerengine/__init__.py?view=auto&rev=565392
> ==============================================================================
>     (empty)
>
> Propchange: activemq/trunk/log_analyzer_tool/loganalyzerengine/__init__.py
> ------------------------------------------------------------------------------
>     svn:executable = *
>
> Added: activemq/trunk/log_analyzer_tool/loganalyzerengine/__init__.pyc
> URL: http://svn.apache.org/viewvc/activemq/trunk/log_analyzer_tool/loganalyzerengine/__init__.pyc?view=auto&rev=565392
> ==============================================================================
> Binary file - no diff available.
>
> Propchange: activemq/trunk/log_analyzer_tool/loganalyzerengine/__init__.pyc
> ------------------------------------------------------------------------------
>     svn:executable = *
>
> Propchange: activemq/trunk/log_analyzer_tool/loganalyzerengine/__init__.pyc
> ------------------------------------------------------------------------------
>     svn:mime-type = application/octet-stream
>
> Added: activemq/trunk/log_analyzer_tool/loganalyzergui/Application.py
> URL: http://svn.apache.org/viewvc/activemq/trunk/log_analyzer_tool/loganalyzergui/Application.py?view=auto&rev=565392
> ==============================================================================
> --- activemq/trunk/log_analyzer_tool/loganalyzergui/Application.py (added)
> +++ activemq/trunk/log_analyzer_tool/loganalyzergui/Application.py Mon Aug 13 09:03:25 2007
> @@ -0,0 +1,71 @@
> +"""
> +Module Application
> +"""
> +import wx
> +from DirectoryPanel import DirectoryPanel
> +from TabbedPanel import TabbedPanel
> +
> +class MainPanel(wx.Panel):
> +    """
> +    Panel contained into the window of the application.
> +    It contains a DirectoryPanel and a TabbedPanel.
> +
> +    """
> +
> +    def __init__(self, parent):
> +        """
> +        Constructor
> +        """
> +
> +        wx.Panel.__init__(self, parent, -1)
> +
> +        self.tabbedPanel = TabbedPanel(self)
> +
> +        sizer = wx.BoxSizer(wx.VERTICAL)
> +        sizer.Add(DirectoryPanel(self), 0, wx.EXPAND|wx.ALL, 5)
> +        sizer.Add(self.tabbedPanel, 1, wx.EXPAND)
> +        self.SetSizer(sizer)
> +
> +    def logDataUpdated(self):
> +        """
> +        Method to be called when the parsed data has been updated.
> +        The Panel will notify its children components.
> +        """
> +
> +        self.tabbedPanel.logDataUpdated()
> +
> +class MainFrame(wx.Frame):
> +    """
> +    This class represents the window of the application.
> +    It contains a MainPanel object.
> +    We need to add a wx.Panel to a wx.Frame to avoid
> +    graphical problems in Windows.
> +    """
> +
> +    def __init__(self, parent):
> +        """
> +        Constructor
> +        """
> +
> +        wx.Frame.__init__(self, parent, 100,
> +                          'ActiveMQ Log Analyzer Tool', size=(1024,800))
> +#        ib = wx.IconBundle()
> +#        ib.AddIconFromFile("logparser.ico", wx.BITMAP_TYPE_ANY)
> +#        self.SetIcons(ib)
> +        sizer = wx.BoxSizer(wx.VERTICAL)
> +        sizer.Add(MainPanel(self), 1, wx.EXPAND)
> +        self.SetSizer(sizer)
> +        self.Centre()
> +        self.Show(True)
> +
> +class Application(wx.App):
> +    """
> +    Main class of the application
> +    """
> +
> +    def OnInit(self):
> +        """
> +        To be executed when Application is launched
> +        """
> +        MainFrame(None)
> +        return True
>
> Propchange: activemq/trunk/log_analyzer_tool/loganalyzergui/Application.py
> ------------------------------------------------------------------------------
>     svn:executable = *
>
> Added: activemq/trunk/log_analyzer_tool/loganalyzergui/Application.pyc
> URL: http://svn.apache.org/viewvc/activemq/trunk/log_analyzer_tool/loganalyzergui/Application.pyc?view=auto&rev=565392
> ==============================================================================
> Binary file - no diff available.
>
> Propchange: activemq/trunk/log_analyzer_tool/loganalyzergui/Application.pyc
> ------------------------------------------------------------------------------
>     svn:executable = *
>
> Propchange: activemq/trunk/log_analyzer_tool/loganalyzergui/Application.pyc
> ------------------------------------------------------------------------------
>     svn:mime-type = application/octet-stream
>
> Added: activemq/trunk/log_analyzer_tool/loganalyzergui/DirectoryPanel.py
> URL: http://svn.apache.org/viewvc/activemq/trunk/log_analyzer_tool/loganalyzergui/DirectoryPanel.py?view=auto&rev=565392
> ==============================================================================
> --- activemq/trunk/log_analyzer_tool/loganalyzergui/DirectoryPanel.py (added)
> +++ activemq/trunk/log_analyzer_tool/loganalyzergui/DirectoryPanel.py Mon Aug 13 09:03:25 2007
> @@ -0,0 +1,61 @@
> +"""
> +Module DirectoryPanel
> +"""
> +import wx
> +import os
> +
> +from loganalyzerengine.LogParser import LogParser
> +
> +class DirectoryPanel(wx.Panel):
> +    """
> +    Panel to choose the directory with the log files to be parsed,
> +    and launch the parsing / analyzing process.
> +    """
> +
> +    def __init__(self, parent):
> +        """
> +        Constructor
> +        """
> +
> +        wx.Panel.__init__(self, parent, -1)
> +        self.mainPanel = parent
> +        self.textctrl = wx.TextCtrl(self, -1, 'C:\logs')
> +
> +        self.lastDirectoryOpen = ''
> +
> +        sizer = wx.BoxSizer(wx.HORIZONTAL)
> +        sizer.Add(wx.StaticText(self, -1, 'Directory'), 0, wx.CENTER|wx.RIGHT, 5)
> +        sizer.Add(self.textctrl, 1, wx.CENTER|wx.RIGHT, 5)
> +        sizer.Add(wx.Button(self, 100 , 'Choose'), 0, wx.CENTER|wx.RIGHT, 5)
> +        sizer.Add(wx.Button(self, 101 , 'Parse'), 0, wx.CENTER)
> +
> +        self.Bind(wx.EVT_BUTTON, self.OnChoose, id=100)
> +        self.Bind(wx.EVT_BUTTON, self.OnParse, id=101)
> +
> +        self.SetSizer(sizer)
> +
> +    def OnChoose(self, event):
> +        """
> +        Action to be executed when the 'Choose' button is pressed.
> +        """
> +
> +        dialog = wx.DirDialog(self, defaultPath=self.lastDirectoryOpen)
> +        if dialog.ShowModal() == wx.ID_OK:
> +            self.textctrl.SetValue(dialog.GetPath())
> +            self.lastDirectoryOpen = dialog.GetPath()
> +        else:
> +            wx.MessageDialog(self, 'Please choose an appropiate directory', style=wx.OK).ShowModal()
> +
> +    def OnParse(self, event):
> +        """
> +        Action to be executed when the 'Parse' button is pressed.
> +        """
> +
> +        path = self.textctrl.GetValue()
> +        if os.path.isdir(path):
> +            LogParser.getInstance().parseDirectory(path)
> +            self.mainPanel.logDataUpdated()
> +            LogParser.deleteInstance()
> +        else:
> +            wx.MessageDialog(self, 'That directory does not exist', style=wx.OK).ShowModal()
> +
> \ No newline at end of file
>
> Propchange: activemq/trunk/log_analyzer_tool/loganalyzergui/DirectoryPanel.py
> ------------------------------------------------------------------------------
>     svn:executable = *
>
> Added: activemq/trunk/log_analyzer_tool/loganalyzergui/DirectoryPanel.pyc
> URL: http://svn.apache.org/viewvc/activemq/trunk/log_analyzer_tool/loganalyzergui/DirectoryPanel.pyc?view=auto&rev=565392
> ==============================================================================
> Binary file - no diff available.
>
> Propchange: activemq/trunk/log_analyzer_tool/loganalyzergui/DirectoryPanel.pyc
> ------------------------------------------------------------------------------
>     svn:executable = *
>
> Propchange: activemq/trunk/log_analyzer_tool/loganalyzergui/DirectoryPanel.pyc
> ------------------------------------------------------------------------------
>     svn:mime-type = application/octet-stream
>
> Added: activemq/trunk/log_analyzer_tool/loganalyzergui/IncorrectSequenceList.py
> URL: http://svn.apache.org/viewvc/activemq/trunk/log_analyzer_tool/loganalyzergui/IncorrectSequenceList.py?view=auto&rev=565392
> ==============================================================================
> --- activemq/trunk/log_analyzer_tool/loganalyzergui/IncorrectSequenceList.py (added)
> +++ activemq/trunk/log_analyzer_tool/loganalyzergui/IncorrectSequenceList.py Mon Aug 13 09:03:25 2007
> @@ -0,0 +1,184 @@
> +"""
> +Module IncorrectSequenceList
> +"""
> +import wx
> +from loganalyzerengine.Connection import Connection
> +from loganalyzerengine.LogFile import LogFile
> +
> +def advisoryString(message):
> +    """
> +    Helper method
> +    """
> +
> +    if message.advisory:
> +        return ' (ADVISORY)'
> +    else:
> +        return ''
> +
> +
> +class IncorrectSequenceList(wx.ListCtrl):
> +    """
> +    List of the incorrect events detected after parsing the logs.
> +    """
> +
> +    def __init__(self, parent):
> +        """
> +        Constructor
> +        """
> +
> +        wx.ListCtrl.__init__(self, parent, -1,
> +                             style=wx.LC_REPORT|wx.LC_SINGLE_SEL|wx.LC_HRULES|wx.LC_VRULES)
> +
> +        self.incorrectSequencePanel = parent
> +
> +        self.datapresent = False
> +        self.connectionForFilter = None
> +
> +        self.InsertColumn(0, 'Type')
> +        self.InsertColumn(1, 'Connection id / File')
> +        self.InsertColumn(2, 'Message id (prod id | prod seq id)')
> +        self.InsertColumn(3, 'ntimes')
> +        self.InsertColumn(4, 'timestamps')
> +
> +        self.SetColumnWidth(0, 150)
> +        self.SetColumnWidth(1, 250)
> +        self.SetColumnWidth(2, 300)
> +        self.SetColumnWidth(3, 100)
> +        self.SetColumnWidth(4, 300)
> +
> +
> +    def logDataUpdated(self):
> +        """
> +        This method must be called to notify the list that the parsed data
> +        has changed.
> +        """
> +
> +        self.datapresent = True
> +        self.updateList()
> +
> +    def checkConnectionForFilter(self):
> +        """
> +        Returns True if the connection that was inputed by the user
> +        to filter the events is valid.
> +        self.connectionForFilter is a (string, boolean) tuple.
> +        The boolean value is True if the string is a shortId, and False if it is a long id.
> +        """
> +
> +        if self.connectionForFilter is None:
> +            return False
> +
> +        if self.connectionForFilter[1]:
> +            #shortId
> +            return self.connectionForFilter[0].isdigit() and \
> +                   int(self.connectionForFilter[0]) > -1 and \
> +                   int(self.connectionForFilter[0]) < len(Connection.connectionIdList)
> +
> +        else:
> +            #longId
> +            return self.connectionForFilter[0] in Connection.connections
> +
> +    def updateList(self):
> +        """
> +        Updates the display of the list of incorrect events
> +        """
> +
> +        self.DeleteAllItems()
> +        if self.datapresent:
> +            options = self.incorrectSequencePanel.options
> +
> +            row = 0
> +
> +            # we construct a list of connection long ids to be displayed,
> +            # depending on the filter desired
> +            if self.checkConnectionForFilter():
> +                if self.connectionForFilter[1]:
> +                    #shortId
> +                    connectionIds = [Connection.connectionIdList[int(self.connectionForFilter[0])]]
> +                else:
> +                    connectionIds = [self.connectionForFilter[0]]
> +            else:
> +                if self.connectionForFilter is None or self.connectionForFilter[0] == '':
> +                    connectionIds = Connection.connections.keys()
> +                else:
> +                    connectionIds = []
> +
> +            # we display the problems tied to connections
> +            showShortIDs = options['showShortIds']
> +
> +            for longId in connectionIds:
> +
> +                # we display long or short ids depending on the option chosen
> +                connection = Connection.getConnectionByLongId(longId)
> +                errors = connection.getErrors()
> +
> +                if showShortIDs:
> +                    printedConnectionId = connection.shortId
> +                else:
> +                    printedConnectionId = longId
> +
> +                # sent but not received messages
> +                if options['sentButNotReceived']:
> +                    for storedMessage, n, timestamps in errors[0]:
> +                        message = storedMessage[0]
> +                        self.insertRow(row, 'sentButNotReceived' + advisoryString(message), printedConnectionId,
> +                                       message.producer.shortId if showShortIDs else message.producer.longId,
> +                                       message.prodSeqId, n, timestamps, wx.WHITE)
> +                        row += 1
> +
> +                # received but not sent messages
> +                if options['receivedButNotSent']:
> +                    for storedMessage, n, timestamps in errors[1]:
> +                        message = storedMessage[0]
> +                        self.insertRow(row, 'receivedButNotSent' + advisoryString(message), printedConnectionId,
> +                                       message.producer.shortId if showShortIDs else message.producer.longId,
> +                                       message.prodSeqId, n, timestamps, wx.WHITE)
> +                        row += 1
> +
> +                # duplicate sent or received messages through a connection
> +                if options['duplicateInConnection']:
> +                    for storedMessage, n, timestamps in errors[2]:
> +                        message = storedMessage[0]
> +                        self.insertRow(row, 'duplicateSentInConnection' + advisoryString(message), printedConnectionId,
> +                                       message.producer.shortId if showShortIDs else message.producer.longId,
> +                                       message.prodSeqId, n, timestamps, wx.WHITE)
> +                        row += 1
> +
> +                    for storedMessage, n, timestamps in errors[3]:
> +                        message = storedMessage[0]
> +                        self.insertRow(row, 'duplicateReceivedInConnection' + advisoryString(message), printedConnectionId,
> +                                       message.producer.shortId if showShortIDs else message.producer.longId,
> +                                       message.prodSeqId, n, timestamps, wx.WHITE)
> +                        row += 1
> +
> +            # duplicate sent or received messages in the same log file.
> +            # right now they are only shown when the connection filter is not used.
> +            if options['duplicateInFile'] and not self.checkConnectionForFilter() and \
> +            (self.connectionForFilter is None or self.connectionForFilter[0] == ''):
> +                for logfile in LogFile.logfiles:
> +                    errors = logfile.getErrors()
> +
> +                    for message, n, timestamps in errors[0]:
> +                        self.insertRow(row, 'duplicateSentInFile' + advisoryString(message), str(logfile),
> +                                       message.producer.shortId if showShortIDs else message.producer.longId,
> +                                       message.prodSeqId, n, timestamps, wx.WHITE)
> +                        row += 1
> +
> +                    for message, n, timestamps in errors[1]:
> +                        self.insertRow(row, 'duplicateReceivedInFile' + advisoryString(message), str(logfile),
> +                                       message.producer.shortId if showShortIDs else message.producer.longId,
> +                                       message.prodSeqId, n, timestamps, wx.WHITE)
> +                        row += 1
> +
> +    def insertRow(self, rownumber, typeOfError, connectionId, producerId, producerSequenceId, n, timestamps, col):
> +        """
> +        Helper method to insert a row into the list
> +        """
> +
> +        self.InsertStringItem(rownumber, typeOfError)
> +        self.SetStringItem(rownumber, 1, str(connectionId))
> +        self.SetStringItem(rownumber, 2, str(producerId) + ' | ' + str(producerSequenceId))
> +        self.SetStringItem(rownumber, 3, str(n))
> +        self.SetStringItem(rownumber, 4, ' | '.join(timestamps))
> +        self.SetItemBackgroundColour(rownumber, col)
> +
> +
> \ No newline at end of file
>
> Propchange: activemq/trunk/log_analyzer_tool/loganalyzergui/IncorrectSequenceList.py
> ------------------------------------------------------------------------------
>     svn:executable = *
>
> Added: activemq/trunk/log_analyzer_tool/loganalyzergui/IncorrectSequenceList.pyc
> URL: http://svn.apache.org/viewvc/activemq/trunk/log_analyzer_tool/loganalyzergui/IncorrectSequenceList.pyc?view=auto&rev=565392
> ==============================================================================
> Binary file - no diff available.
>
> Propchange: activemq/trunk/log_analyzer_tool/loganalyzergui/IncorrectSequenceList.pyc
> ------------------------------------------------------------------------------
>     svn:executable = *
>
> Propchange: activemq/trunk/log_analyzer_tool/loganalyzergui/IncorrectSequenceList.pyc
> ------------------------------------------------------------------------------
>     svn:mime-type = application/octet-stream
>
> Added: activemq/trunk/log_analyzer_tool/loganalyzergui/IncorrectSequencePanel.py
> URL: http://svn.apache.org/viewvc/activemq/trunk/log_analyzer_tool/loganalyzergui/IncorrectSequencePanel.py?view=auto&rev=565392
> ==============================================================================
> --- activemq/trunk/log_analyzer_tool/loganalyzergui/IncorrectSequencePanel.py (added)
> +++ activemq/trunk/log_analyzer_tool/loganalyzergui/IncorrectSequencePanel.py Mon Aug 13 09:03:25 2007
> @@ -0,0 +1,135 @@
> +"""
> +Module IncorrectSequencePanel
> +"""
> +import wx
> +from IncorrectSequenceList import IncorrectSequenceList
> +
> +class IncorrectSequencePanel(wx.Panel):
> +    """
> +    This panel contains a list of incorrect events dectected by the parsing,
> +    and many controls to filter which events appear.
> +    Also the user can change if long ids (original ActiveMQConnection id strings, long)
> +    or short ids (a different integer for each connection) is desired.
> +    """
> +
> +    def __init__(self, parent):
> +        """
> +        Constructor
> +        """
> +
> +        wx.Panel.__init__(self, parent, -1)
> +
> +        self.parent = parent
> +        self.options = {}
> +
> +        self.incorrectSequenceList = IncorrectSequenceList(self)
> +        self.showShortIds = wx.CheckBox(self, 100, 'Show results with short ids')
> +        self.sentButNotReceived = wx.CheckBox(self, 101, 'Sent but not received')
> +        self.receivedButNotSent = wx.CheckBox(self, 102, 'Received but not sent')
> +        self.duplicateInConnection = wx.CheckBox(self, 103, 'Duplicate in connection')
> +        self.duplicateInFile = wx.CheckBox(self, 104, 'Duplicate in log file')
> +        self.connectionText = wx.TextCtrl(self, -1, '')
> +        self.rbshortId = wx.RadioButton(self, -1, style=wx.RB_GROUP, label="Short id")
> +        self.rblongId = wx.RadioButton(self, -1, label="Long id")
> +
> +        self.showShortIds.SetValue(True)
> +        self.sentButNotReceived.SetValue(True)
> +        self.receivedButNotSent.SetValue(True)
> +        self.duplicateInConnection.SetValue(True)
> +        self.duplicateInFile.SetValue(True)
> +
> +        sizer = wx.BoxSizer(wx.VERTICAL)
> +
> +        sizer2 = wx.GridSizer()
> +        sizer2 = wx.GridSizer(2, 2, 5, 5)
> +        sizer2.AddMany([self.sentButNotReceived,
> +                        self.receivedButNotSent,
> +                        self.duplicateInConnection,
> +                        self.duplicateInFile
> +                       ])
> +
> +        sizer3 = wx.BoxSizer(wx.HORIZONTAL)
> +        sizerrb = wx.BoxSizer(wx.VERTICAL)
> +        sizerrb.Add(self.rbshortId, 0, wx.DOWN, 5)
> +        sizerrb.Add(self.rblongId, 0)
> +        sizer3.Add(wx.StaticText(self, -1, 'Filter by connection\n(leave blank to view all)'), 0, wx.CENTER|wx.RIGHT, 5)
> +        sizer3.Add(self.connectionText, 1, wx.CENTER|wx.RIGHT, 5)
> +        sizer3.Add(sizerrb, 0, wx.CENTER|wx.RIGHT, 5)
> +        sizer3.Add(wx.Button(self, 105, 'Filter'), 0, wx.CENTER)
> +
> +        sizer4 = wx.BoxSizer(wx.HORIZONTAL)
> +        sizer4.Add(sizer2, 0, wx.CENTER)
> +        sizer4.Add(sizer3, 1, wx.EXPAND|wx.CENTER|wx.LEFT, 20)
> +
> +        sizer.Add(sizer4, 0, wx.EXPAND|wx.ALL, 5)
> +
> +        sizer5 = wx.BoxSizer(wx.HORIZONTAL)
> +        sizer5.Add(self.showShortIds, 0, wx.RIGHT|wx.CENTER, 5)
> +        sizer5.Add(wx.Button(self, 106, 'Jump to Message Browsing'), 0, wx.CENTER)
> +
> +        sizer.Add(sizer5, 0, wx.ALL, 5)
> +
> +        sizer.Add(self.incorrectSequenceList, 1, wx.EXPAND)
> +
> +        self.Bind(wx.EVT_CHECKBOX, self.OptionsChanged, id=100)
> +        self.Bind(wx.EVT_CHECKBOX, self.OptionsChanged, id=101)
> +        self.Bind(wx.EVT_CHECKBOX, self.OptionsChanged, id=102)
> +        self.Bind(wx.EVT_CHECKBOX, self.OptionsChanged, id=103)
> +        self.Bind(wx.EVT_CHECKBOX, self.OptionsChanged, id=104)
> +        self.Bind(wx.EVT_BUTTON, self.OnFilter, id=105)
> +        self.Bind(wx.EVT_BUTTON, self.OnJump, id=106)
> +
> +        self.parseOptions()
> +
> +        self.SetSizer(sizer)
> +
> +    def logDataUpdated(self):
> +        """
> +        This method must be called to notify the panel that the parsed data has been updated.
> +        It will in turn notify the list.
> +        """
> +
> +        self.incorrectSequenceList.logDataUpdated()
> +
> +    def parseOptions(self):
> +        """
> +        Stores the values of the various checkboxes into self.options.
> +        """
> +
> +        self.options['showShortIds'] = self.showShortIds.IsChecked()
> +        self.options['sentButNotReceived'] = self.sentButNotReceived.IsChecked()
> +        self.options['receivedButNotSent'] = self.receivedButNotSent.IsChecked()
> +        self.options['duplicateInConnection'] = self.duplicateInConnection.IsChecked()
> +        self.options['duplicateInFile'] = self.duplicateInFile.IsChecked()
> +
> +    def OptionsChanged(self, event):
> +        """
> +        Action to be executed every time one of the checkboxes is clicked.
> +        It calls parseOptions() and then updates the display of incorrect events.
> +        """
> +
> +        self.parseOptions()
> +        self.incorrectSequenceList.updateList()
> +
> +    def OnFilter(self, event):
> +        """
> +        Action to be executed every time the button 'filter' is pressed.
> +        """
> +
> +        self.incorrectSequenceList.connectionForFilter = (self.connectionText.GetValue(), self.rbshortId.GetValue())
> +        self.OptionsChanged(event)
> +
> +    def OnJump(self, event):
> +        """
> +        Action to be executed when the 'jump' button is pressed.
> +        """
> +
> +        if self.incorrectSequenceList.GetFirstSelected() != -1:
> +            connectionId, messageId = self.incorrectSequenceList.GetItem(self.incorrectSequenceList.GetFirstSelected(), 2).GetText().split(' | ')
> +            self.parent.GetParent().browsingMessagesPanel.textctrl1.SetValue(connectionId)
> +            self.parent.GetParent().browsingMessagesPanel.textctrl2.SetValue(messageId)
> +            self.parent.GetParent().browsingMessagesPanel.rbshortId.SetValue(self.showShortIds.GetValue())
> +            self.parent.GetParent().browsingMessagesPanel.rblongId.SetValue(not self.showShortIds.GetValue())
> +            self.parent.GetParent().browsingMessagesPanel.displayMessageInfo(event)
> +
> +            self.parent.SetSelection(1)
> \ No newline at end of file
>
> Propchange: activemq/trunk/log_analyzer_tool/loganalyzergui/IncorrectSequencePanel.py
> ------------------------------------------------------------------------------
>     svn:executable = *
>
> Added: activemq/trunk/log_analyzer_tool/loganalyzergui/IncorrectSequencePanel.pyc
> URL: http://svn.apache.org/viewvc/activemq/trunk/log_analyzer_tool/loganalyzergui/IncorrectSequencePanel.pyc?view=auto&rev=565392
> ==============================================================================
> Binary file - no diff available.
>
> Propchange: activemq/trunk/log_analyzer_tool/loganalyzergui/IncorrectSequencePanel.pyc
> ------------------------------------------------------------------------------
>     svn:executable = *
>
> Propchange: activemq/trunk/log_analyzer_tool/loganalyzergui/IncorrectSequencePanel.pyc
> ------------------------------------------------------------------------------
>     svn:mime-type = application/octet-stream
>
> Added: activemq/trunk/log_analyzer_tool/loganalyzergui/MessageTravelPanel.py
> URL: http://svn.apache.org/viewvc/activemq/trunk/log_analyzer_tool/loganalyzergui/MessageTravelPanel.py?view=auto&rev=565392
> ==============================================================================
> --- activemq/trunk/log_analyzer_tool/loganalyzergui/MessageTravelPanel.py (added)
> +++ activemq/trunk/log_analyzer_tool/loganalyzergui/MessageTravelPanel.py Mon Aug 13 09:03:25 2007
> @@ -0,0 +1,66 @@
> +"""
> +Module MessageTravelPanel
> +"""
> +import wx
> +from MessageTravelText import MessageTravelText
> +
> +class MessageTravelPanel(wx.Panel):
> +    """
> +    The function of this panel is to show the travel history of a message.
> +    This means the connections that the message went through.
> +    """
> +
> +    def __init__(self, parent):
> +        """
> +        Constructor
> +        """
> +
> +        wx.Panel.__init__(self, parent, -1)
> +
> +        self.rbshortId = wx.RadioButton(self, -1, style=wx.RB_GROUP, label="Short id")
> +        self.rblongId = wx.RadioButton(self, -1, label="Long id")
> +        self.textctrl1 = wx.TextCtrl(self, -1, '')
> +        self.textctrl2 = wx.TextCtrl(self, -1, '')
> +        self.chkshowshortId = wx.CheckBox(self, 100, 'Show result with short ids')
> +        self.messageTravelPanel = MessageTravelText(self)
> +
> +        self.chkshowshortId.SetValue(True)
> +
> +        sizerrb = wx.BoxSizer(wx.VERTICAL)
> +        sizerrb.Add(self.rbshortId, 0, wx.DOWN, 5)
> +        sizerrb.Add(self.rblongId, 0)
> +
> +        sizerinput = wx.BoxSizer(wx.HORIZONTAL)
> +        sizerinput.Add(sizerrb, 0, wx.RIGHT, 5)
> +        sizerinput.Add(wx.StaticText(self, -1, 'Producer id'), 0, wx.CENTER|wx.RIGHT, 5)
> +        sizerinput.Add(self.textctrl1, 2, wx.CENTER|wx.RIGHT, 5)
> +        sizerinput.Add(wx.StaticText(self, -1, 'Producer Sequence id'), 0, wx.CENTER|wx.RIGHT, 5)
> +        sizerinput.Add(self.textctrl2, 1, wx.CENTER|wx.RIGHT, 5)
> +        sizerinput.Add(wx.Button(self, 101 , 'Browse'), 0, wx.CENTER)
> +
> +        sizer = wx.BoxSizer(wx.VERTICAL)
> +        sizer.Add(sizerinput, 0, wx.EXPAND|wx.ALL, 5)
> +        sizer.Add(self.chkshowshortId, 0, wx.LEFT|wx.UP, 5)
> +        sizer.Add(self.messageTravelPanel, 1, wx.EXPAND|wx.ALL, 5)
> +
> +        self.Bind(wx.EVT_CHECKBOX, self.displayMessageInfo, id=100)
> +        self.Bind(wx.EVT_BUTTON, self.displayMessageInfo, id=101)
> +
> +        self.SetSizer(sizer)
> +
> +    def displayMessageInfo(self, event):
> +        """
> +        Action to be executed when the 'Browse' button is pushed.
> +        """
> +
> +        self.messageTravelPanel.displayMessageInfo(self.textctrl1.GetValue(),
> +                                                 self.textctrl2.GetValue(),
> +                                                 self.rbshortId.GetValue())
> +
> +    def logDataUpdated(self):
> +        """
> +        This method must be called to notify the panel that the parsed data has been updated.
> +        It will in turn notify the message travel panel.
> +        """
> +
> +        self.messageTravelPanel.logDataUpdated()
> \ No newline at end of file
>
> Propchange: activemq/trunk/log_analyzer_tool/loganalyzergui/MessageTravelPanel.py
> ------------------------------------------------------------------------------
>     svn:executable = *
>
> Added: activemq/trunk/log_analyzer_tool/loganalyzergui/MessageTravelPanel.pyc
> URL: http://svn.apache.org/viewvc/activemq/trunk/log_analyzer_tool/loganalyzergui/MessageTravelPanel.pyc?view=auto&rev=565392
> ==============================================================================
> Binary file - no diff available.
>
> Propchange: activemq/trunk/log_analyzer_tool/loganalyzergui/MessageTravelPanel.pyc
> ------------------------------------------------------------------------------
>     svn:executable = *
>
> Propchange: activemq/trunk/log_analyzer_tool/loganalyzergui/MessageTravelPanel.pyc
> ------------------------------------------------------------------------------
>     svn:mime-type = application/octet-stream
>
>
>


-- 
Regards,
Hiram

Blog: http://hiramchirino.com

Mime
View raw message