sebastien - in flumotion/branches/transcoder-1: . flumotion/common
flumotion/component flumotion/component/combiners
flumotion/component/combiners/switch
flumotion/component/misc/httpfile
flumotion/component/producers/playlist flumotion/extern/log
flumotion/launch flumotion/manager flumotion/test flumotion/worker
flumotion-commit at lists.fluendo.com
flumotion-commit at lists.fluendo.com
Thu May 10 18:25:27 CEST 2007
Author: sebastien
Date: Thu May 10 18:25:19 2007
New Revision: 4931
Added:
flumotion/branches/transcoder-1/flumotion/component/combiners/ (props changed)
- copied from r4929, flumotion/trunk/flumotion/component/combiners/
flumotion/branches/transcoder-1/flumotion/component/combiners/Makefile.am
- copied unchanged from r4929, flumotion/trunk/flumotion/component/combiners/Makefile.am
flumotion/branches/transcoder-1/flumotion/component/combiners/__init__.py
- copied unchanged from r4929, flumotion/trunk/flumotion/component/combiners/__init__.py
flumotion/branches/transcoder-1/flumotion/component/combiners/switch/ (props changed)
- copied from r4929, flumotion/trunk/flumotion/component/combiners/switch/
flumotion/branches/transcoder-1/flumotion/component/combiners/switch/Makefile.am
- copied unchanged from r4929, flumotion/trunk/flumotion/component/combiners/switch/Makefile.am
flumotion/branches/transcoder-1/flumotion/component/combiners/switch/__init__.py
- copied unchanged from r4929, flumotion/trunk/flumotion/component/combiners/switch/__init__.py
flumotion/branches/transcoder-1/flumotion/component/combiners/switch/admin_gtk.py
- copied unchanged from r4929, flumotion/trunk/flumotion/component/combiners/switch/admin_gtk.py
flumotion/branches/transcoder-1/flumotion/component/combiners/switch/switch.py
- copied unchanged from r4929, flumotion/trunk/flumotion/component/combiners/switch/switch.py
flumotion/branches/transcoder-1/flumotion/component/combiners/switch/switch.xml
- copied unchanged from r4929, flumotion/trunk/flumotion/component/combiners/switch/switch.xml
Modified:
flumotion/branches/transcoder-1/ChangeLog
flumotion/branches/transcoder-1/configure.ac
flumotion/branches/transcoder-1/flumotion/common/config.py
flumotion/branches/transcoder-1/flumotion/common/enum.py
flumotion/branches/transcoder-1/flumotion/common/errors.py
flumotion/branches/transcoder-1/flumotion/component/Makefile.am
flumotion/branches/transcoder-1/flumotion/component/component.xml
flumotion/branches/transcoder-1/flumotion/component/feedcomponent010.py
flumotion/branches/transcoder-1/flumotion/component/misc/httpfile/file.py
flumotion/branches/transcoder-1/flumotion/component/producers/playlist/playlistparser.py
flumotion/branches/transcoder-1/flumotion/extern/log/ChangeLog
flumotion/branches/transcoder-1/flumotion/extern/log/log.py
flumotion/branches/transcoder-1/flumotion/extern/log/test_log.py
flumotion/branches/transcoder-1/flumotion/launch/main.py
flumotion/branches/transcoder-1/flumotion/manager/admin.py
flumotion/branches/transcoder-1/flumotion/manager/component.py
flumotion/branches/transcoder-1/flumotion/manager/depgraph.py
flumotion/branches/transcoder-1/flumotion/manager/main.py
flumotion/branches/transcoder-1/flumotion/manager/manager.py
flumotion/branches/transcoder-1/flumotion/test/test_manager_depgraph.py
flumotion/branches/transcoder-1/flumotion/test/test_misc_httpfile.py
flumotion/branches/transcoder-1/flumotion/worker/main.py
Log:
2007-05-10 Sebastien Merle <sebastien at fluendo.com>
* Merged flumotion trunk changesets up to [4929].
Modified: flumotion/branches/transcoder-1/ChangeLog
==============================================================================
--- flumotion/branches/transcoder-1/ChangeLog (original)
+++ flumotion/branches/transcoder-1/ChangeLog Thu May 10 18:25:19 2007
@@ -1,3 +1,7 @@
+2007-05-10 Sebastien Merle <sebastien at fluendo.com>
+
+ * Merged flumotion trunk changesets up to [4929].
+
2007-05-09 Sebastien Merle <sebastien at fluendo.com>
* flumotion/manager/admin.py:
@@ -26,6 +30,42 @@
* flumotion/manager/admin.py:
Added the loadComponent method.
+2007-05-10 Zaheer Abbas Merali <<zaheerabbas at merali dot org>>
+
+ * flumotion/component/Makefile.am:
+ * flumotion/component/component.xml:
+ Fix distcheck and fix bundling of switch component.
+
+2007-05-10 Zaheer Abbas Merali <<zaheerabbas at merali dot org>>
+
+ * configure.ac:
+ * flumotion/component/combiners/Makefile.am:
+ * flumotion/component/combiners/__init__.py:
+ * flumotion/component/combiners/switch/Makefile.am:
+ * flumotion/component/combiners/switch/__init__.py:
+ * flumotion/component/combiners/switch/admin_gtk.py (SwitchingNode,
+ SwitchingNode.__init__, SwitchingNode.cb_toggled,
+ SwitchingNode.setUIState, SwitchingNode.stateSet, SwitcherAdminGtk,
+ SwitcherAdminGtk.setup):
+ * flumotion/component/combiners/switch/switch.py (SwitchMedium,
+ SwitchMedium.remote_switchToMaster,
+ SwitchMedium.remote_switchToBackup, Switch, Switch.init,
+ Switch.do_check, Switch.cb, Switch.switchToMaster,
+ Switch.switchToBackup, SingleSwitch, SingleSwitch.init,
+ SingleSwitch.get_pipeline_string, SingleSwitch.configure_pipeline,
+ SingleSwitch.switchToMaster, SingleSwitch.switchToBackup, AVSwitch,
+ AVSwitch.init, AVSwitch.get_pipeline_string,
+ AVSwitch.configure_pipeline, AVSwitch.switchToMaster,
+ AVSwitch.switchToBackup):
+ * flumotion/component/combiners/switch/switch.xml:
+ Add switching components with very simple gtk admin for now.
+
+2007-05-10 Sebastien Merle <sebastien at fluendo.com>
+
+ * flumotion/common/enum.py:
+ Made the unjellyer an diffrent class than Enum, because
+ Twsited 2.0.1 need the unjellyer to be a classic style class.
+
2007-03-30 Sebastien Merle <sebastien at fluendo.com>
* flumotion/common/enum.py:
@@ -44,6 +84,51 @@
be jellyed and unjellyed. Now an enum value can be directly
used with spread without converting to int.
+2007-05-09 Andy Wingo <wingo at pobox.com>
+
+ * flumotion/worker/main.py (main):
+ * flumotion/launch/main.py (main):
+ * flumotion/manager/main.py (main): --verbose sets a baseline for
+ --debug, not overriding it. Fixes #82.
+
+ * flumotion/manager/component.py (ComponentAvatar.cleanup): Add a
+ comment.
+
+2007-05-09 Zaheer Abbas Merali <<zaheerabbas at merali dot org>>
+
+ * flumotion/test/test_manager_depgraph.py
+ (testDepGraph._createComponent):
+ Fix tests for depgraph to use the eater key.
+
+2007-05-09 Zaheer Abbas Merali <<zaheerabbas at merali dot org>>
+
+ * flumotion/component/feedcomponent010.py
+ (FeedComponent.get_eater_name_for_feedid):
+ Add helper method.
+ * flumotion/manager/depgraph.py (DepGraph.mapEatersToFeeders,
+ DepGraph.whatShouldBeStarted):
+ Migrate depgraph to use the eater key rather than the source key.
+
+2007-05-09 Michael Smith <msmith at fluendo.com>
+
+ * flumotion/component/producers/playlist/playlistparser.py:
+ Fix duration adjustment for making sources fit into timeline.
+
+2007-05-09 Thomas Vander Stichele <thomas at apestaart dot org>
+
+ * flumotion/component/misc/httpfile/file.py (File.renderAuthenticated,
+ File.do_prepareBody, MimedFileFactory, FLVFile,
+ FLVFile.do_prepareBody, FileTransfer):
+ Make sure start= requests on FLV files give me the right mime type
+ by not writing before all headers are set.
+ factor out an overridable do_prepareBody in which FLV and the like
+ can do their manipulative trickery.
+ Re-fixes #618.
+ * flumotion/test/test_misc_httpfile.py (TestTextFile.finishCallback,
+ TestDirectory.finish, TestDirectory.finish, TestDirectory.finish,
+ TestDirectory.testFLVRangeStart, TestDirectory.finish):
+ Add tests. Be more assertive.
+
2007-05-09 Michael Smith <msmith at fluendo.com>
* flumotion/component/producers/playlist/playlist.py:
Modified: flumotion/branches/transcoder-1/configure.ac
==============================================================================
--- flumotion/branches/transcoder-1/configure.ac (original)
+++ flumotion/branches/transcoder-1/configure.ac Thu May 10 18:25:19 2007
@@ -174,6 +174,8 @@
flumotion/component/effects/colorbalance/Makefile
flumotion/component/effects/volume/Makefile
flumotion/component/encoders/Makefile
+flumotion/component/combiners/Makefile
+flumotion/component/combiners/switch/Makefile
flumotion/component/consumers/Makefile
flumotion/component/consumers/disker/Makefile
flumotion/component/consumers/httpstreamer/Makefile
Modified: flumotion/branches/transcoder-1/flumotion/common/config.py
==============================================================================
--- flumotion/branches/transcoder-1/flumotion/common/config.py (original)
+++ flumotion/branches/transcoder-1/flumotion/common/config.py Thu May 10 18:25:19 2007
@@ -62,7 +62,7 @@
def _buildComponentConfig(parentName, componentType, componentName,
componentProperties, componentPlugs=None,
- eaters=None, isClockMaster=None,
+ eaters=None, isClockMaster=False,
flumotionVersion=None):
"""
Build a component configuration dictionary.
@@ -139,8 +139,7 @@
raise ConfigError("%s: unknown type '%s' for property %s"
% (componentName, definition.type, name))
checker = _property_checkers.get(definition.type)
- #Don't check for tuple because fraction are tuple but are values
- #if value and (isinstance(value, tuple) or isinstance(value, list)):
+ #Don't check for tuple because fractions are tuple values
if value and isinstance(value, list):
if not definition.multiple and len(value) > 1:
raise ConfigError("%s: multiple value specified but not "
Modified: flumotion/branches/transcoder-1/flumotion/common/enum.py
==============================================================================
--- flumotion/branches/transcoder-1/flumotion/common/enum.py (original)
+++ flumotion/branches/transcoder-1/flumotion/common/enum.py Thu May 10 18:25:19 2007
@@ -45,8 +45,8 @@
self.__enums__[value] = enum
setattr(self, enum.name, enum)
+class Enum(object, jelly.Jellyable):
-class Enum(object, jelly.Jellyable, jelly.Unjellyable):
__metaclass__ = EnumMetaClass
def __init__(self, value, name, nick=None):
self.value = value
@@ -78,19 +78,6 @@
self.value, self.name, self.nick])
return jellier.preserve(self, sxp)
- def unjellyFor(self, unjellier, jellyList):
- enumClassName, value, name, nick = jellyList[1:]
- enumClass = _enumClassRegistry.get(enumClassName, None)
- if enumClass:
- enum = enumClass.get(value)
- assert enum.name == name, "Inconsistent Enum Name"
- return enum
- self._enumClassName = enumClassName
- self.value = value
- self.name = name
- self.nick = nick
- return self
-
class EnumClass(object):
def __new__(klass, type_name, names=(), nicks=(), **extras):
@@ -121,4 +108,25 @@
_enumClassRegistry[type_name] = etype
return etype
-jelly.setUnjellyableForClass(qual(Enum), Enum)
+
+# Enum unjellyer should not be a new style class,
+# otherwise Twsited 2.0.1 will not recognise it.
+class EnumUnjellyer(jelly.Unjellyable):
+
+ def unjellyFor(self, unjellier, jellyList):
+ enumClassName, value, name, nick = jellyList[1:]
+ enumClass = _enumClassRegistry.get(enumClassName, None)
+ if enumClass:
+ enum = enumClass.get(value)
+ assert enum.name == name, "Inconsistent Enum Name"
+ return enum
+ # Become a generic Enum instance
+ self.__class__ = Enum
+ self._enumClassName = enumClassName
+ self.value = value
+ self.name = name
+ self.nick = nick
+ return self
+
+
+jelly.setUnjellyableForClass(qual(Enum), EnumUnjellyer)
Modified: flumotion/branches/transcoder-1/flumotion/common/errors.py
==============================================================================
--- flumotion/branches/transcoder-1/flumotion/common/errors.py (original)
+++ flumotion/branches/transcoder-1/flumotion/common/errors.py Thu May 10 18:25:19 2007
@@ -165,7 +165,7 @@
args[1]: str
"""
-class ComponentDuplicatedError(ComponentError):
+class ComponentAlreadyExistsError(ComponentError):
"""
A component name is already used.
"""
Modified: flumotion/branches/transcoder-1/flumotion/component/Makefile.am
==============================================================================
--- flumotion/branches/transcoder-1/flumotion/component/Makefile.am (original)
+++ flumotion/branches/transcoder-1/flumotion/component/Makefile.am Thu May 10 18:25:19 2007
@@ -17,6 +17,7 @@
SUBDIRS = \
base \
bouncers \
+ combiners \
consumers \
converters \
effects \
Modified: flumotion/branches/transcoder-1/flumotion/component/component.xml
==============================================================================
--- flumotion/branches/transcoder-1/flumotion/component/component.xml (original)
+++ flumotion/branches/transcoder-1/flumotion/component/component.xml Thu May 10 18:25:19 2007
@@ -13,6 +13,7 @@
<filename location="converters/__init__.py" />
<filename location="encoders/__init__.py" />
<filename location="muxers/__init__.py" />
+ <filename location="combiners/__init__.py" />
<filename location="consumers/__init__.py" />
<filename location="bouncers/__init__.py" />
<filename location="effects/__init__.py" />
Modified: flumotion/branches/transcoder-1/flumotion/component/feedcomponent010.py
==============================================================================
--- flumotion/branches/transcoder-1/flumotion/component/feedcomponent010.py (original)
+++ flumotion/branches/transcoder-1/flumotion/component/feedcomponent010.py Thu May 10 18:25:19 2007
@@ -1308,4 +1308,9 @@
self._gotFirstNewSegment[feedId] = True
return True
+ def get_eater_name_for_feedid(self, feedId):
+ if self._eaterMapping.has_key(feedId):
+ return self._eaterMapping[feedId]
+ return None
+
pygobject.type_register(FeedComponent)
Modified: flumotion/branches/transcoder-1/flumotion/component/misc/httpfile/file.py
==============================================================================
--- flumotion/branches/transcoder-1/flumotion/component/misc/httpfile/file.py (original)
+++ flumotion/branches/transcoder-1/flumotion/component/misc/httpfile/file.py Thu May 10 18:25:19 2007
@@ -22,17 +22,19 @@
import string
import os
+from twisted.web import resource, server, http
+from twisted.web import error as weberror, static
+from twisted.internet import defer, reactor, error, abstract
+from twisted.python import filepath
+from twisted.cred import credentials
+
+from flumotion.configure import configure
from flumotion.component import component
from flumotion.common import log, messages, errors, netutils
from flumotion.component.component import moods
from flumotion.component.misc.porter import porterclient
from flumotion.component.base import http as httpbase
-from twisted.web import resource, server, http
-from twisted.web import error as weberror, static
-from twisted.internet import defer, reactor, error, abstract
-from twisted.python import filepath
from flumotion.twisted import fdserver
-from twisted.cred import credentials
# add our own mime types to the ones parsed from /etc/mime.types
def loadMimeTypes():
@@ -103,11 +105,7 @@
return server.NOT_DONE_YET
- def renderAuthenticated(self, _, request, first=0):
- """
- @type first: int
- @param first: starting byte to send from
- """
+ def renderAuthenticated(self, _, request):
# Now that we're authenticated (or authentication wasn't requested),
# write the file (or appropriate other response) to the client.
# We override static.File to implement Range requests, and to get access
@@ -120,7 +118,7 @@
self.restat()
ext = os.path.splitext(self.basename())[1].lower()
- type = self.contentTypes.get(ext, self.defaultType)
+ contentType = self.contentTypes.get(ext, self.defaultType)
if not self.exists():
self.debug("Couldn't find resource %s", self.path)
@@ -135,12 +133,14 @@
# that the client must not issue further requests.
# We do this because future requests on this server might actually need
# to go to a different process (because of the porter)
+ request.setHeader('Server', 'Flumotion/%s' % configure.version)
request.setHeader('Connection', 'close')
# We can do range requests, in bytes.
request.setHeader('Accept-Ranges', 'bytes')
- if type:
- request.setHeader('content-type', type)
+ if contentType:
+ self.debug('content type %r' % contentType)
+ request.setHeader('content-type', contentType)
try:
f = self.openForReading()
@@ -156,6 +156,7 @@
fileSize = self.getFileSize()
# first and last byte offset we will write
+ first = 0
last = fileSize - 1
range = request.getHeader('range')
@@ -163,6 +164,7 @@
# We have a partial data request.
# for interpretation of range, see RFC 2068 14.36
# examples: bytes=500-999; bytes=-500 (suffix mode; last 500)
+ self.log('range request, %r', range)
rangeKeyValue = string.split(range, '=')
if len(rangeKeyValue) != 2:
request.setResponseCode(http.REQUESTED_RANGE_NOT_SATISFIABLE)
@@ -203,20 +205,31 @@
request.setResponseCode(http.PARTIAL_CONTENT)
request.setHeader('Content-Range', "bytes %d-%d/%d" %
(first, last, fileSize))
-
- # Start sending from the requested position in the file
- if first:
- f.seek(first)
-
- request.setHeader("Content-Length", str(last - first + 1))
+ # Start sending from the requested position in the file
+ if first:
+ f.seek(first)
+
+ self.do_prepareBody(request, f, first, last)
if request.method == 'HEAD':
- return ''
-
+ return ''
+
request._transfer = FileTransfer(f, last + 1, request)
return server.NOT_DONE_YET
+ def do_prepareBody(self, request, f, first, last):
+ """
+ I am called before the body of the response gets written,
+ and after generic header setting has been done.
+
+ I set Content-Length.
+
+ Override me to send additional headers, or to prefix the body
+ with data headers.
+ """
+ request.setHeader("Content-Length", str(last - first + 1))
+
class MimedFileFactory(log.Loggable):
"""
I create File subclasses based on the mime type of the given path.
@@ -250,16 +263,28 @@
playable.
"""
header = 'FLV\x01\x01\000\000\000\x09\000\000\000\x09'
- def renderAuthenticated(self, _, request):
- self.debug('rendering FLV')
- first = 0
+
+ def do_prepareBody(self, request, f, first, last):
+ self.log('do_prepareBody for FLV')
+ length = last - first + 1
+
+ # if there is a non-zero start get parameter, prefix the body with
+ # our FLV header
# each value is a list
start = int(request.args.get('start', ['0'])[0])
- if start:
- first = start
- request.write(self.header)
+ # range request takes precedence over our start parsing
+ if first == 0 and start:
+ self.debug('start %d passed, seeking', start)
+ f.seek(start)
+ length = last - start + 1 + len(self.header)
+
+ request.setHeader("Content-Length", str(length))
- return File.renderAuthenticated(self, _, request, first=first)
+ if request.method == 'HEAD':
+ return ''
+
+ if first == 0 and start:
+ request.write(self.header)
class FileTransfer:
"""
Modified: flumotion/branches/transcoder-1/flumotion/component/producers/playlist/playlistparser.py
==============================================================================
--- flumotion/branches/transcoder-1/flumotion/component/producers/playlist/playlistparser.py (original)
+++ flumotion/branches/transcoder-1/flumotion/component/producers/playlist/playlistparser.py Thu May 10 18:25:19 2007
@@ -89,8 +89,8 @@
while item:
if item.timestamp < newitem.timestamp:
prev = item
- elif (not next and item.timestamp >
- newitem.timestamp + newitem.duration):
+ elif (not next and item.timestamp > newitem.timestamp and
+ newitem.timestamp + newitem.duration > item.timestamp):
next = item
break
item = item.next
@@ -117,6 +117,8 @@
# Duration adjustments -> Reflect into gnonlin timeline
if prev and prev.timestamp + prev.duration > newitem.timestamp:
+ self.debug("Changing duration of previous item from %d to %d",
+ prev.duration, newitem.timestamp - prev.timestamp)
prev.duration = newitem.timestamp - prev.timestamp
if prev.asrc:
prev.asrc.props.duration = prev.duration
@@ -124,7 +126,9 @@
if prev.vsrc:
prev.vsrc.props.duration = prev.duration
prev.vsrc.props.media_duration = prev.duration
- if next and timestamp + newitem.duration > next.timestamp:
+ if next and newitem.timestamp + newitem.duration > next.timestamp:
+ self.debug("Changing duration of new item from %d to %d to fit",
+ newitem.duration, next.timestamp - newitem.timestamp)
newitem.duration = next.timestamp - newitem.timestamp
# Then we need to actually add newitem into the gnonlin timeline
Modified: flumotion/branches/transcoder-1/flumotion/extern/log/ChangeLog
==============================================================================
--- flumotion/branches/transcoder-1/flumotion/extern/log/ChangeLog (original)
+++ flumotion/branches/transcoder-1/flumotion/extern/log/ChangeLog Thu May 10 18:25:19 2007
@@ -1,3 +1,22 @@
+2007-05-09 Andy Wingo <wingo at pobox.com>
+
+ Patch by: Philippe Normand <philippe fluendo.com>
+
+ * log.py (init): Adapt to addLimitedLogHandler.
+ (addLogHandler): Only add generic log handlers.
+ (addLimitedLogHandler): New function, splits out management of
+ limited log handlers.
+ (removeLogHandler, removeLimitedLogHandler): New functions.
+
+ * test_log.py (TestLog.testLimitInvisible)
+ (TestLog.testLimitedVisible, TestLog.testFormatStrings)
+ (TestLog.testLimitedError, TestLog.testLogHandlerLimitedLevels):
+ Limited log handlers are now managed via addLimitedLogHandler.
+ (TestLog.testLogHandler)
+ (TestOwnLogHandler.testOwnLogHandlerLimited)
+ (TestOwnLogHandler.testLogHandlerAssertion): No need for
+ limited=False.
+
2007-04-30 Andy Wingo <wingo at pobox.com>
* log.py (TwistedLogObserver.emit): Write to stderr, like the
Modified: flumotion/branches/transcoder-1/flumotion/extern/log/log.py
==============================================================================
--- flumotion/branches/transcoder-1/flumotion/extern/log/log.py (original)
+++ flumotion/branches/transcoder-1/flumotion/extern/log/log.py Thu May 10 18:25:19 2007
@@ -348,7 +348,7 @@
if os.environ.has_key(envVarName):
# install a log handler that uses the value of the environment var
setDebug(os.environ[envVarName])
- addLogHandler(stderrHandler, limited=True)
+ addLimitedLogHandler(stderrHandler)
_initialized = True
@@ -394,7 +394,7 @@
_log_handlers_limited = []
_initialized = False
-def addLogHandler(func, limited=True):
+def addLogHandler(func):
"""
Add a custom log handler.
@@ -405,18 +405,65 @@
None. Use getLevelName(level) to get a printable
name for the log level.
@type func: a callable function
- @type limited: boolean
- @param limited: whether to automatically filter based on the DEBUG value
+ @raises: TypeError if func is not a callable
"""
if not callable(func):
raise TypeError, "func must be callable"
-
- if limited:
- _log_handlers_limited.append(func)
- else:
+
+ if func not in _log_handlers:
_log_handlers.append(func)
-
+
+def addLimitedLogHandler(func):
+ """
+ Add a custom log handler.
+
+ @param func: a function object
+ with prototype (level, object, category, message)
+ where level is either ERROR, WARN, INFO, DEBUG, or
+ LOG, and the rest of the arguments are strings or
+ None. Use getLevelName(level) to get a printable
+ name for the log level.
+ @type func: a callable function
+ @raises: TypeError if func is not a callable
+ """
+ if not callable(func):
+ raise TypeError, "func must be callable"
+
+ if func not in _log_handlers_limited:
+ _log_handlers_limited.append(func)
+
+def removeLogHandler(func):
+ """
+ Remove a registered log handler.
+
+ @param func: a function object
+ with prototype (level, object, category, message)
+ where level is either ERROR, WARN, INFO, DEBUG, or
+ LOG, and the rest of the arguments are strings or
+ None. Use getLevelName(level) to get a printable
+ name for the log level.
+ @type func: a callable function
+ @raises: ValueError if func is not registered
+ """
+ _log_handlers.remove(func)
+
+
+def removeLimitedLogHandler(func):
+ """
+ Remove a registered limited log handler.
+
+ @param func: a function object
+ with prototype (level, object, category, message)
+ where level is either ERROR, WARN, INFO, DEBUG, or
+ LOG, and the rest of the arguments are strings or
+ None. Use getLevelName(level) to get a printable
+ name for the log level.
+ @type func: a callable function
+ @raises: ValueError if func is not registered
+ """
+ _log_handlers_limited.remove(func)
+
# public log functions
def error(cat, format, *args):
errorObject(None, cat, format, *args)
Modified: flumotion/branches/transcoder-1/flumotion/extern/log/test_log.py
==============================================================================
--- flumotion/branches/transcoder-1/flumotion/extern/log/test_log.py (original)
+++ flumotion/branches/transcoder-1/flumotion/extern/log/test_log.py Thu May 10 18:25:19 2007
@@ -54,7 +54,7 @@
def testLimitInvisible(self):
log.setDebug("testlog:3")
- log.addLogHandler(self.handler)
+ log.addLimitedLogHandler(self.handler)
# log 2 we shouldn't get
self.tester.log("not visible")
@@ -69,7 +69,7 @@
def testLimitedVisible(self):
log.setDebug("testlog:3")
- log.addLogHandler(self.handler)
+ log.addLimitedLogHandler(self.handler)
# log 3 we should get
self.tester.info("visible")
@@ -84,7 +84,7 @@
def testFormatStrings(self):
log.setDebug("testlog:3")
- log.addLogHandler(self.handler)
+ log.addLimitedLogHandler(self.handler)
self.tester.info("%d %s", 42, 'the answer')
assert self.category == 'testlog'
@@ -93,7 +93,7 @@
def testLimitedError(self):
log.setDebug("testlog:3")
- log.addLogHandler(self.handler)
+ log.addLimitedLogHandler(self.handler)
self.assertRaises(SystemExit, self.tester.error, "error")
assert self.category == 'testlog'
@@ -102,7 +102,7 @@
def testLogHandlerLimitedLevels(self):
log.setDebug("testlog:3")
- log.addLogHandler(self.handler)
+ log.addLimitedLogHandler(self.handler)
# now try debug and log again too
log.setDebug("testlog:5")
@@ -120,7 +120,7 @@
# test that we get all log messages
def testLogHandler(self):
log.setDebug("testlog:3")
- log.addLogHandler(self.handler, limited=False)
+ log.addLogHandler(self.handler)
self.tester.log("visible")
assert self.message == 'visible'
@@ -144,13 +144,13 @@
# test if our own log handler correctly mangles the message
def testOwnLogHandlerLimited(self):
log.setDebug("testlog:3")
- log.addLogHandler(self.handler, limited=False)
+ log.addLogHandler(self.handler)
self.tester.log("visible")
assert self.message == 'override visible'
def testLogHandlerAssertion(self):
- self.assertRaises(TypeError, log.addLogHandler, None)
+ self.assertRaises(TypeError, log.addLimitedLogHandler, None)
class TestGetExceptionMessage(unittest.TestCase):
def func3(self):
Modified: flumotion/branches/transcoder-1/flumotion/launch/main.py
==============================================================================
--- flumotion/branches/transcoder-1/flumotion/launch/main.py (original)
+++ flumotion/branches/transcoder-1/flumotion/launch/main.py Thu May 10 18:25:19 2007
@@ -272,7 +272,7 @@
# verbose overrides --debug
if options.verbose:
- options.debug = "*:3"
+ log.setFluDebug("*:3")
# handle all options
if options.version:
Modified: flumotion/branches/transcoder-1/flumotion/manager/admin.py
==============================================================================
--- flumotion/branches/transcoder-1/flumotion/manager/admin.py (original)
+++ flumotion/branches/transcoder-1/flumotion/manager/admin.py Thu May 10 18:25:19 2007
@@ -411,10 +411,10 @@
def perspective_loadComponent(self, componentType, componentId,
componentProperties, workerName,
- eaters=None, isClockMaster=None):
+ eaters=None, isClockMaster=False):
"""
Load a component into the manager configuration.
- Returns a deferred that will be call with a LoadingOutcome value.
+ Returns a deferred that will be called with the component state.
@param componentType: the registered type of the component to be added
@type componentType: str
@@ -423,12 +423,13 @@
@type componentId: str
@param componentProperties: the properties of the component to be added
@type componentProperties: dict of str => str
- @param workerName: the compName of the worker where the added
+ @param workerName: the name of the worker where the added
component should run.
@type workerName: str
@param eaters: the stream eaters of the component to be added.
@type eaters: dict of str keyed list of str
@param isClockMaster: if the component to be added is clock master.
+ By default a componenet is not a clack master.
@type isClockMaster: bool
"""
return self.vishnu.loadComponent(self.remoteIdentity, componentType,
Modified: flumotion/branches/transcoder-1/flumotion/manager/component.py
==============================================================================
--- flumotion/branches/transcoder-1/flumotion/manager/component.py (original)
+++ flumotion/branches/transcoder-1/flumotion/manager/component.py Thu May 10 18:25:19 2007
@@ -99,6 +99,7 @@
Clean up when detaching.
"""
if self._ports:
+ # FIXME: doesn't seem to ever be possible
self.vishnu.releasePortsOnWorker(self.getWorkerName(),
self._ports.values())
Modified: flumotion/branches/transcoder-1/flumotion/manager/depgraph.py
==============================================================================
--- flumotion/branches/transcoder-1/flumotion/manager/depgraph.py (original)
+++ flumotion/branches/transcoder-1/flumotion/manager/depgraph.py Thu May 10 18:25:19 2007
@@ -200,46 +200,41 @@
# for this component setup, go through all the feeders in it
config = eatingComponent.get('config')
- if not config.has_key('source'):
+ if not config.has_key('eater'):
# no eaters
self.debug("Component %r has no eaters" % eatingComponent)
else:
- # source is a list of componentName[:feedName]
+ # eater is a dict of eaterName -> list of componentName[:feedName]
# with feedName defaulting to default
- # FIXME: maybe source should really be eaters and contain
- # a list of feedId
- list = config['source']
-
- # FIXME: there's a bug in config parsing - sometimes this gives
- # us one string, and sometimes a list of one string, and
- # sometimes a list
- if isinstance(list, str):
- list = [list, ]
-
- for source in list:
- feederFound = False
- feederComponentName = source.split(':')[0]
- # find the feeder
- for feedingComponent in toSetup:
- if feedingComponent.get("name") == feederComponentName:
- feederFound = True
- try:
- self._addEdge(feedingComponent, eatingComponent,
- "COMPONENTSETUP", "COMPONENTSETUP")
- except KeyError:
- # it is possible for a component to have
- # two eaters, each eating from feeders on
- # one other component
- pass
- try:
- self._addEdge(feedingComponent, eatingComponent,
- "COMPONENTSTART", "COMPONENTSTART")
- except KeyError:
- pass
-
- if not feederFound:
- raise errors.ComponentConfigError(eatingComponent,
- "No feeder exists for eater %s" % source)
+ eaters = config['eater']
+
+ for eater in eaters:
+ for feed in eaters[eater]:
+ feederFound = False
+ feederComponentName = feed.split(':')[0]
+ # find the feeder
+ for feedingComponent in toSetup:
+ if feedingComponent.get("name") == feederComponentName:
+ feederFound = True
+ try:
+ self._addEdge(feedingComponent, eatingComponent,
+ "COMPONENTSETUP", "COMPONENTSETUP")
+ except KeyError:
+ # it is possible for a component to have
+ # two eaters, each eating from feeders on
+ # one other component
+ pass
+ try:
+ self._addEdge(feedingComponent, eatingComponent,
+ "COMPONENTSTART", "COMPONENTSTART")
+ except KeyError:
+ pass
+
+ if not feederFound:
+ raise errors.ComponentConfigError(eatingComponent,
+ "No feeder exists for eater %s on component %s"
+ " feeding from %s" % (eater, eatingComponent,
+ feed))
def whatShouldBeStarted(self):
"""
Modified: flumotion/branches/transcoder-1/flumotion/manager/main.py
==============================================================================
--- flumotion/branches/transcoder-1/flumotion/manager/main.py (original)
+++ flumotion/branches/transcoder-1/flumotion/manager/main.py Thu May 10 18:25:19 2007
@@ -154,9 +154,9 @@
log.debug('manager', 'Setting configure.%s to %s' % (d, o))
setattr(configure, d, o)
- # verbose overrides --debug
+ # verbose sets a baseline for --debug
if options.verbose:
- options.debug = "*:3"
+ log.setFluDebug("*:3")
# Handle options that don't require a configuration file.
if options.version:
Modified: flumotion/branches/transcoder-1/flumotion/manager/manager.py
==============================================================================
--- flumotion/branches/transcoder-1/flumotion/manager/manager.py (original)
+++ flumotion/branches/transcoder-1/flumotion/manager/manager.py Thu May 10 18:25:19 2007
@@ -470,7 +470,9 @@
atmosphere = state.get('atmosphere')
for name, c in conf.atmosphere.components.items():
if name in [x.get('name') for x in atmosphere.get('components')]:
- self.debug('atmosphere already has component %s' % name)
+ message = 'atmosphere already has component %s' % name
+ self.debug(message)
+ raise errors.ComponentAlreadyExistsError(message)
else:
added.append(self._addComponent(c, atmosphere, identity))
@@ -487,8 +489,10 @@
components = [x.get('name') for x in flow.get('components')]
for name, c in f.components.items():
if name in components:
- self.debug('component %s already in flow %s'
+ message = ('component %s already in flow %s'
% (c.name, f.name))
+ self.debug(message)
+ raise errors.ComponentAlreadyExistsError(message)
else:
added.append(self._addComponent(c, flow, identity))
@@ -551,15 +555,11 @@
def loadComponent(self, identity, componentType, componentId,
componentProperties, workerName,
- eaters=None, isClockMaster=None):
+ eaters=None, isClockMaster=False):
"""
Load a component into the manager configuration.
- Returns a deferred that will be call with a LoadingOutcome value.
+ Returns a deferred that will be called with the component state.
- @param identity: The identity making this request. This is used by the
- adminaction logging mechanism in order to say who is
- performing the action.
- @type identity: L{flumotion.common.identity.Identity}
@param componentType: the registered type of the component to be added
@type componentType: str
@param componentId: the identifier of the component to add, should be
@@ -573,8 +573,8 @@
@param eaters: the stream eaters of the component to be added.
@type eaters: dict of str keyed list of str
@param isClockMaster: if the component to be added is clock master.
+ By default a componenet is not a clack master.
@type isClockMaster: bool
- @return a deferred
"""
self.debug('loading %s component %s on %s',
componentType, componentId, workerName)
@@ -598,7 +598,7 @@
if compName in components:
message = 'Atmosphere already has component %s' % compName
self.debug(message)
- raise errors.ComponentDuplicatedError(message)
+ raise errors.ComponentAlreadyExistsError(message)
else:
compState = self._addComponent(compConf, atmosphere, identity)
else:
@@ -616,7 +616,7 @@
message = ('Component %s already in flow %s'
% (compName, parentName))
self.debug(message)
- raise errors.ComponentDuplicatedError(message)
+ raise errors.ComponentAlreadyExistsError(message)
else:
compState = self._addComponent(compConf, flow, identity)
Modified: flumotion/branches/transcoder-1/flumotion/test/test_manager_depgraph.py
==============================================================================
--- flumotion/branches/transcoder-1/flumotion/test/test_manager_depgraph.py (original)
+++ flumotion/branches/transcoder-1/flumotion/test/test_manager_depgraph.py Thu May 10 18:25:19 2007
@@ -41,7 +41,7 @@
for eater in defs[4]:
source.append(eater)
- conf["source"] = source
+ conf["eater"] = {"default":source}
ret.set("config", conf)
return ret
Modified: flumotion/branches/transcoder-1/flumotion/test/test_misc_httpfile.py
==============================================================================
--- flumotion/branches/transcoder-1/flumotion/test/test_misc_httpfile.py (original)
+++ flumotion/branches/transcoder-1/flumotion/test/test_misc_httpfile.py Thu May 10 18:25:19 2007
@@ -82,6 +82,8 @@
self.assertEquals(request.data, data)
self.assertEquals(int(request.getHeader('Content-Length') or '0'),
length)
+ self.assertEquals(request.getHeader('content-type'),
+ 'application/octet-stream')
def finishPartialCallback(self, result, request, data, start, end):
self.finishCallback(result, request, http.PARTIAL_CONTENT, data)
@@ -199,6 +201,7 @@
self.assertEquals(self.resource.getChild('test.flv', fr).render(fr),
server.NOT_DONE_YET)
def finish(result):
+ self.assertEquals(fr.getHeader('content-type'), 'video/x-flv')
self.assertEquals(fr.data, 'a fake FLV file')
fr.finishDeferred.addCallback(finish)
@@ -209,7 +212,11 @@
self.assertEquals(self.resource.getChild('test.flv', fr).render(fr),
server.NOT_DONE_YET)
def finish(result):
- self.assertEquals(fr.data, file.FLVFile.header + 'fake FLV file')
+ self.assertEquals(fr.getHeader('content-type'), 'video/x-flv')
+ expected = file.FLVFile.header + 'fake FLV file'
+ self.assertEquals(fr.data, expected)
+ self.assertEquals(fr.getHeader('Content-Length'),
+ str(len(expected)))
fr.finishDeferred.addCallback(finish)
return fr.finishDeferred
@@ -219,7 +226,21 @@
self.assertEquals(self.resource.getChild('test.flv', fr).render(fr),
server.NOT_DONE_YET)
def finish(result):
+ self.assertEquals(fr.getHeader('content-type'), 'video/x-flv')
self.assertEquals(fr.data, 'a fake FLV file')
fr.finishDeferred.addCallback(finish)
+ return fr.finishDeferred
+ def testFLVRangeStart(self):
+ # range should take precedence over start parameter
+ fr = FakeRequest(headers={'range': 'bytes=7-'}, args={'start': [2]})
+ self.assertEquals(self.resource.getChild('test.flv', fr).render(fr),
+ server.NOT_DONE_YET)
+ def finish(result):
+ self.assertEquals(fr.getHeader('content-type'), 'video/x-flv')
+ expected = 'FLV file'
+ self.assertEquals(fr.data, expected)
+ self.assertEquals(fr.getHeader('Content-Length'),
+ str(len(expected)))
+ fr.finishDeferred.addCallback(finish)
return fr.finishDeferred
Modified: flumotion/branches/transcoder-1/flumotion/worker/main.py
==============================================================================
--- flumotion/branches/transcoder-1/flumotion/worker/main.py (original)
+++ flumotion/branches/transcoder-1/flumotion/worker/main.py Thu May 10 18:25:19 2007
@@ -168,9 +168,8 @@
log.debug('worker', 'Setting configure.%s to %s' % (d, o))
setattr(configure, d, o)
- # verbose overrides --debug; is only a command-line option
if options.verbose:
- options.debug = "*:3"
+ log.setFluDebug("*:3")
# apply the command-line debug level if is given through --verbose or -d
if options.debug:
More information about the flumotion-commit
mailing list