[Piglit] [PATCH] Added simple thread-safe logging support
Eoff, Ullysses A
ullysses.a.eoff at intel.com
Tue Jan 18 15:05:32 PST 2011
Please disregard this patch... I'm working on a different solution.
> -----Original Message-----
> From: U. Artie Eoff [mailto:ullysses.a.eoff at intel.com]
> Sent: Tuesday, January 18, 2011 11:38 AM
> To: piglit at lists.freedesktop.org
> Cc: Eoff, Ullysses A
> Subject: [PATCH] Added simple thread-safe logging support
>
> Added simple thread-safe logging support. Changed test status output
> so that
> it has single-line context. This logging technique will ensure that
> output messages are not interleaved when future support is added for
> concurrent testing. This changeset was tested with Python 2.7 on
> Linux. It should be cross platform, however, and compatible with at
> least
> Python 2.5 (someone please verify if necessary).
> ---
> framework/core.py | 14 +++++++---
> framework/log.py | 71
> +++++++++++++++++++++++++++++++++++++++++++++++++
> framework/patterns.py | 50 ++++++++++++++++++++++++++++++++++
> framework/threads.py | 45 +++++++++++++++++++++++++++++++
> piglit-run.py | 4 ++-
> 5 files changed, 179 insertions(+), 5 deletions(-)
> create mode 100644 framework/log.py
> create mode 100644 framework/patterns.py
> create mode 100644 framework/threads.py
>
> diff --git a/framework/core.py b/framework/core.py
> index b237df6..6454edf 100644
> --- a/framework/core.py
> +++ b/framework/core.py
> @@ -32,6 +32,8 @@ import sys
> import time
> import traceback
>
> +import log
> +
> __all__ = [
> 'Environment',
> 'checkDir',
> @@ -301,10 +303,14 @@ class Test:
> if len(env.exclude_filter) > 0:
> if True in map(lambda f: f.search(path) != None,
> env.exclude_filter):
> return None
> +
> + def status(msg):
> + log.Log(channel = path, msg = msg)
> +
> # Run the test
> if env.execute:
> try:
> - print "Test: %(path)s" % locals()
> + status("running...")
> time_start = time.time()
> result = self.run()
> time_end = time.time()
> @@ -322,14 +328,14 @@ class Test:
> result['exception'] = str(sys.exc_info()[0]) +
> str(sys.exc_info()[1])
> result['traceback'] = '@@@' +
> "".join(traceback.format_tb(sys.exc_info()[2]))
>
> - if result['result'] != 'pass':
> - print " result: %(result)s" % { 'result':
> result['result'] }
> + #if result['result'] != 'pass':
> + status("%(result)s" % { 'result': result['result'] })
>
> result.write(env.file, path)
> if Test.sleep:
> time.sleep(Test.sleep)
> else:
> - print "Dry-run: %(path)s" % locals()
> + status("dry-run")
>
> # Returns True iff the given error message should be ignored
> def isIgnored(self, error):
> diff --git a/framework/log.py b/framework/log.py
> new file mode 100644
> index 0000000..d69a26d
> --- /dev/null
> +++ b/framework/log.py
> @@ -0,0 +1,71 @@
> +#!/usr/bin/env python
> +#
> +# Permission is hereby granted, free of charge, to any person
> +# obtaining a copy of this software and associated documentation
> +# files (the "Software"), to deal in the Software without
> +# restriction, including without limitation the rights to use,
> +# copy, modify, merge, publish, distribute, sublicense, and/or
> +# sell copies of the Software, and to permit persons to whom the
> +# Software is furnished to do so, subject to the following
> +# conditions:
> +#
> +# This permission notice shall be included in all copies or
> +# substantial portions of the Software.
> +#
> +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
> +# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
> +# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
> +# PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHOR(S) BE
> +# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
> +# AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
> +# OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
> +# DEALINGS IN THE SOFTWARE.
> +
> +# Piglit logging
> +
> +from patterns import Singleton
> +from threads import synchronized_self
> +import logging
> +
> +def Initialize():
> + # basicConfig will not do anything if the root has any handlers
> + # so remove them
> + root = logging.getLogger()
> + handlers= root.handlers
> + for handler in handlers:
> + root.removeHandler(handler)
> +
> + format = "[%(asctime)s]:: %(name)s :: %(message)s"
> + #dateformat = "%a, %d %b %Y %H:%M:%S"
> + level = logging.INFO
> +
> + logging.basicConfig(
> + format = format,
> + #datefmt = dateformat,
> + level = level
> + )
> +
> +class Logger(Singleton):
> + @synchronized_self
> + def __LogMessage(self, logfunc, message, **kwargs):
> + [logfunc(line, **kwargs) for line in message.split('\n')]
> +
> + @synchronized_self
> + def GetLogger(self, channel = None):
> + if len(logging.root.handlers) == 0:
> + logging.basicConfig()
> + if channel is None:
> + channel = "base"
> + logger = logging.getLogger(channel)
> + return logger
> +
> + def Log(self, type = logging.INFO, msg = "", channel = None):
> + self.__LogMessage(lambda m, **kwargs:
> self.GetLogger(channel).log(type, m, **kwargs), msg)
> +
> +Log = Logger().Log
> +
> +
> +
> +
> +
> +
> diff --git a/framework/patterns.py b/framework/patterns.py
> new file mode 100644
> index 0000000..9f43e20
> --- /dev/null
> +++ b/framework/patterns.py
> @@ -0,0 +1,50 @@
> +#!/usr/bin/env python
> +#
> +# Permission is hereby granted, free of charge, to any person
> +# obtaining a copy of this software and associated documentation
> +# files (the "Software"), to deal in the Software without
> +# restriction, including without limitation the rights to use,
> +# copy, modify, merge, publish, distribute, sublicense, and/or
> +# sell copies of the Software, and to permit persons to whom the
> +# Software is furnished to do so, subject to the following
> +# conditions:
> +#
> +# This permission notice shall be included in all copies or
> +# substantial portions of the Software.
> +#
> +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
> +# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
> +# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
> +# PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHOR(S) BE
> +# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
> +# AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
> +# OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
> +# DEALINGS IN THE SOFTWARE.
> +
> +# Piglit design patterns
> +
> +
> +class Singleton(object):
> + '''
> + Modeled after
> http://www.python.org/download/releases/2.2.3/descrintro/#__new__
> + '''
> + def __new__(cls, *args, **kwargs):
> + it = cls.__dict__.get('__it__')
> + if it is not None:
> + return it
> + cls.__it__ = it = object.__new__(cls)
> + it.init(*args, **kwargs)
> + return it
> +
> + def init(self, *args, **kwargs):
> + ''' Derived classes should override this method '''
> + pass
> +
> + @classmethod
> + def GetInstance(cls, *args, **kwargs):
> + return cls(*args, **kwargs)
> +
> + @classmethod
> + def ClearInstance(cls):
> + if cls.__dict__.get('__it__') is not None:
> + del cls.__it__
> diff --git a/framework/threads.py b/framework/threads.py
> new file mode 100644
> index 0000000..1215e10
> --- /dev/null
> +++ b/framework/threads.py
> @@ -0,0 +1,45 @@
> +#!/usr/bin/env python
> +#
> +# Permission is hereby granted, free of charge, to any person
> +# obtaining a copy of this software and associated documentation
> +# files (the "Software"), to deal in the Software without
> +# restriction, including without limitation the rights to use,
> +# copy, modify, merge, publish, distribute, sublicense, and/or
> +# sell copies of the Software, and to permit persons to whom the
> +# Software is furnished to do so, subject to the following
> +# conditions:
> +#
> +# This permission notice shall be included in all copies or
> +# substantial portions of the Software.
> +#
> +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
> +# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
> +# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
> +# PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHOR(S) BE
> +# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
> +# AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
> +# OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
> +# DEALINGS IN THE SOFTWARE.
> +
> +# Piglit threads
> +
> +from threading import RLock
> +from weakref import WeakKeyDictionary
> +
> +######################################################################
> #######
> +##### Decorators
> +######################################################################
> #######
> +
> +# provides synchronized access to all instance methods of a instance
> that use this decorator
> +def synchronized_self(function):
> + def wrapper(self, *args, **kwargs):
> + synchronized_self.locks.setdefault(self, RLock()).acquire()
> + try:
> + return function(self, *args, **kwargs)
> + finally:
> + synchronized_self.locks[self].release()
> + return wrapper
> +
> +synchronized_self.locks = WeakKeyDictionary()
> +
> +
> diff --git a/piglit-run.py b/piglit-run.py
> index 9f0eca6..0f7f15b 100755
> --- a/piglit-run.py
> +++ b/piglit-run.py
> @@ -27,7 +27,7 @@ import re
> import sys
>
> import framework.core as core
> -
> +import framework.log as log
>
>
>
> #######################################################################
> ######
> @@ -85,6 +85,8 @@ def main():
> if len(args) != 2:
> usage()
>
> + log.Initialize()
> +
> profileFilename = args[0]
> resultsDir = args[1]
>
> --
> 1.7.3.4
More information about the Piglit
mailing list