Modified: subversion/branches/ev2-export/tools/server-side/svnpubsub/svntweet.py URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/tools/server-side/svnpubsub/svntweet.py?rev=1297221&r1=1295003&r2=1297221&view=diff ============================================================================== --- subversion/branches/ev2-export/tools/server-side/svnpubsub/svntweet.py (original) +++ subversion/branches/ev2-export/tools/server-side/svnpubsub/svntweet.py Mon Mar 5 20:34:22 2012 @@ -21,7 +21,7 @@ # # Example: # svntweet.py my-config.json -# +# # With my-config.json containing stream paths and the twitter auth info: # {"stream": "http://svn-master.apache.org:2069/commits/xml", # "username": "asfcommits", @@ -90,9 +90,9 @@ class Revision: self.log = None self.date = None -class StreamHandler(handler.ContentHandler): +class StreamHandler(handler.ContentHandler): def __init__(self, bdec): - handler.ContentHandler.__init__(self) + handler.ContentHandler.__init__(self) self.bdec = bdec self.rev = None self.text_value = None @@ -115,7 +115,7 @@ class StreamHandler(handler.ContentHandl self.bdec.stillalive() def characters(self, data): if self.text_value is not None: - self.text_value = self.text_value + data + self.text_value = self.text_value + data else: self.text_value = data @@ -179,7 +179,7 @@ class BigDoEverythingClasss(object): def pageStart(self): log.msg("Stream Connection Established") self.failures = 0 - + def _restartStream(self): (self.stream, self.transport) = connectTo(self.url, self) self.stream.deferred.addBoth(self.streamDead) @@ -253,6 +253,6 @@ def main(config_file): if __name__ == "__main__": if len(sys.argv) != 2: print "invalid args, read source code" - sys.exit(0) + sys.exit(0) log.startLogging(sys.stdout) main(sys.argv[1])
Modified: subversion/branches/ev2-export/tools/server-side/svnpubsub/svnwcsub.py URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/tools/server-side/svnpubsub/svnwcsub.py?rev=1297221&r1=1295003&r2=1297221&view=diff ============================================================================== --- subversion/branches/ev2-export/tools/server-side/svnpubsub/svnwcsub.py (original) +++ subversion/branches/ev2-export/tools/server-side/svnpubsub/svnwcsub.py Mon Mar 5 20:34:22 2012 @@ -36,8 +36,9 @@ import os import re import ConfigParser import time -import logging +import logging.handlers import Queue +import optparse from twisted.internet import reactor, task, threads from twisted.internet.utils import getProcessOutput @@ -130,7 +131,7 @@ class WorkingCopy(object): uuid = info['Repository UUID'] relpath = url[len(repos):] # also has leading '/' return [relpath, url, repos, uuid] - + class HTTPStream(HTTPClientFactory): protocol = HTTPPageDownloader @@ -154,9 +155,9 @@ class Revision: self.rev = rev self.dirs_changed = [] -class StreamHandler(handler.ContentHandler): +class StreamHandler(handler.ContentHandler): def __init__(self, stream, bdec): - handler.ContentHandler.__init__(self) + handler.ContentHandler.__init__(self) self.stream = stream self.bdec = bdec self.rev = None @@ -167,7 +168,7 @@ class StreamHandler(handler.ContentHandl """ <commit revision="7"> <dirs_changed><path>/</path></dirs_changed> - </commit> + </commit> """ if name == "commit": self.rev = Revision(attrs['repository'], int(attrs['revision'])) @@ -175,7 +176,7 @@ class StreamHandler(handler.ContentHandl self.bdec.stillalive(self.stream) def characters(self, data): if self.text_value is not None: - self.text_value = self.text_value + data + self.text_value = self.text_value + data else: self.text_value = data @@ -230,7 +231,6 @@ class BigDoEverythingClasss(object): self.svnbin = config.get_value('svnbin') self.env = config.get_env() self.worker = BackgroundWorker(self.svnbin, self.env) - self.worker.start() self.service = service self.failures = 0 self.alive = time.time() @@ -333,12 +333,15 @@ class BackgroundWorker(threading.Thread) threading.Thread.__init__(self) # The main thread/process should not wait for this thread to exit. - self.daemon = True + ### compat with Python 2.5 + self.setDaemon(True) self.svnbin = svnbin self.env = env self.q = Queue.Queue() + self.has_started = False + def run(self): while True: if self.q.qsize() > BACKLOG_TOO_HIGH: @@ -360,6 +363,12 @@ class BackgroundWorker(threading.Thread) self.q.task_done() def add_work(self, operation, wc): + # Start the thread when work first arrives. Thread-start needs to + # be delayed in case the process forks itself to become a daemon. + if not self.has_started: + self.start() + self.has_started = True + self.q.put((operation, wc)) def _update(self, wc): @@ -443,21 +452,93 @@ class ReloadableConfig(ConfigParser.Safe return str(option) -def main(config_file): +def prepare_logging(logfile): + "Log to the specified file, or to stdout if None." + + if logfile: + # Rotate logs daily, keeping 7 days worth. + handler = logging.handlers.TimedRotatingFileHandler( + logfile, when='midnight', backupCount=7, + ) + else: + handler = logging.StreamHandler(sys.stdout) + + # Add a timestamp to the log records + formatter = logging.Formatter('%(asctime)s [%(levelname)s] %(message)s', + '%Y-%m-%d %H:%M:%S') + handler.setFormatter(formatter) + + # Apply the handler to the root logger + root = logging.getLogger() + root.addHandler(handler) + + ### use logging.INFO for now. switch to cmdline option or a config? + root.setLevel(logging.INFO) + + +def handle_options(options): + # Set up the logging, then process the rest of the options. + prepare_logging(options.logfile) + + if options.pidfile: + pid = os.getpid() + open(options.pidfile, 'w').write('%s\n' % pid) + logging.info('pid %d written to %s', pid, options.pidfile) + + if options.uid: + try: + uid = int(options.uid) + except ValueError: + import pwd + uid = pwd.getpwnam(options.uid)[2] + logging.info('setting uid %d', uid) + os.setuid(uid) + + if options.gid: + try: + gid = int(options.gid) + except ValueError: + import grp + gid = grp.getgrnam(options.gid)[2] + logging.info('setting gid %d', gid) + os.setgid(gid) + + if options.umask: + umask = int(options.umask, 8) + os.umask(umask) + logging.info('umask set to %03o', umask) + + +def main(args): + parser = optparse.OptionParser( + description='An SvnPubSub client to keep working copies synchronized ' + 'with a repository.', + usage='Usage: %prog [options] CONFIG_FILE', + ) + parser.add_option('--logfile', + help='filename for logging') + parser.add_option('--pidfile', + help="the process' PID will be written to this file") + parser.add_option('--uid', + help='switch to this UID before running') + parser.add_option('--gid', + help='switch to this GID before running') + parser.add_option('--umask', + help='set this (octal) umask before running') + + options, extra = parser.parse_args(args) + + if len(extra) != 1: + parser.error('CONFIG_FILE is required') + config_file = extra[0] + + # Process any provided options. + handle_options(options) + c = ReloadableConfig(config_file) big = BigDoEverythingClasss(c) reactor.run() if __name__ == "__main__": - if len(sys.argv) != 2: - print "invalid args, read source code" - sys.exit(0) - - ### use logging.INFO for now. review/adjust the calls above for the - ### proper logging level. then remove the level (to return to default). - ### future: switch to config for logfile and loglevel. - logging.basicConfig(level=logging.INFO, stream=sys.stdout, - datefmt='%Y-%m-%d %H:%M:%S', - format='%(asctime)s [%(levelname)s] %(message)s') - main(sys.argv[1]) + main(sys.argv[1:]) Modified: subversion/branches/ev2-export/tools/server-side/svnpubsub/test.conf URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/tools/server-side/svnpubsub/test.conf?rev=1297221&r1=1295003&r2=1297221&view=diff ============================================================================== --- subversion/branches/ev2-export/tools/server-side/svnpubsub/test.conf (original) +++ subversion/branches/ev2-export/tools/server-side/svnpubsub/test.conf Mon Mar 5 20:34:22 2012 @@ -1,4 +1,9 @@ -# For use with testserver.py +# For use with connecting to testserver.py [DEFAULT] +svnbin: svn streams: http://127.0.0.1:2069/commits/xml + +[env] + +[track] Modified: subversion/branches/ev2-export/tools/server-side/svnpubsub/watcher.py URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/tools/server-side/svnpubsub/watcher.py?rev=1297221&r1=1295003&r2=1297221&view=diff ============================================================================== --- subversion/branches/ev2-export/tools/server-side/svnpubsub/watcher.py (original) +++ subversion/branches/ev2-export/tools/server-side/svnpubsub/watcher.py Mon Mar 5 20:34:22 2012 @@ -53,5 +53,5 @@ def main(config_file): if __name__ == "__main__": if len(sys.argv) != 2: print "invalid args, read source code" - sys.exit(0) + sys.exit(0) main(sys.argv[1])
