~loggerhead-team/loggerhead/trunk-rich

« back to all changes in this revision

Viewing changes to __init__.py

  • Committer: John Arbash Meinel
  • Date: 2011-02-10 00:43:37 UTC
  • mto: This revision was merged to the branch mainline in revision 426.
  • Revision ID: john@arbash-meinel.com-20110210004337-8rwedln8fgg4un16
Add a <noop> command to the RequestWorker.

This allows us to push the workers to stop immediately, in case
they are currently blocked waiting on another item in the queue.
This makes the test suite integration tests faster, but also
makes the script runner exit in a timely manner as well.

Also creating a trivial load_test script, just for example
purposes.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright 2009 Canonical Ltd
 
1
# Copyright 2009, 2010, 2011 Canonical Ltd
2
2
#
3
3
# This program is free software; you can redistribute it and/or modify
4
4
# it under the terms of the GNU General Public License as published by
26
26
 
27
27
"""Loggerhead web viewer for Bazaar branches.
28
28
 
29
 
This provides a new option "--http" to the "bzr serve" command, that 
 
29
This provides a new option "--http" to the "bzr serve" command, that
30
30
starts a web server to browse the contents of a branch.
31
31
"""
32
32
 
33
 
version_info = (1, 11, 0)
 
33
from info import (
 
34
    bzr_plugin_version as version_info,
 
35
    bzr_compatible_versions,
 
36
    )
34
37
 
35
38
if __name__ == 'bzrlib.plugins.loggerhead':
36
39
    import bzrlib
37
40
    from bzrlib.api import require_any_api
38
 
 
39
 
    require_any_api(bzrlib, [(1, 11, 0), (1, 13, 0)])
40
 
 
41
 
    # TODO: This should provide a new type of server that can be used by bzr
42
 
    # serve, maybe through a registry, rather than overriding the command.  Though
43
 
    # maybe we should keep the wrapper to work with older bzr releases, at least
44
 
    # for a bit.
 
41
    from bzrlib import commands
 
42
 
 
43
    require_any_api(bzrlib, bzr_compatible_versions)
45
44
 
46
45
    # NB: Normally plugins should lazily load almost everything, but this
47
46
    # seems reasonable to have in-line here: bzrlib.commands and options are
48
47
    # normally loaded, and the rest of loggerhead won't be loaded until serve
49
48
    # --http is run.
50
 
        
51
 
    import bzrlib.builtins
52
 
    from bzrlib.commands import get_cmd_object, register_command
53
 
    from bzrlib.option import Option
54
 
 
55
 
    _original_command = get_cmd_object('serve')
56
 
 
 
49
 
 
50
    # transport_server_registry was added in bzr 1.16. When we drop support for
 
51
    # older releases, we can remove the code to override cmd_serve.
 
52
 
 
53
    try:
 
54
        from bzrlib.transport import transport_server_registry
 
55
    except ImportError:
 
56
        transport_server_registry = None
 
57
 
 
58
    DEFAULT_HOST = '0.0.0.0'
57
59
    DEFAULT_PORT = 8080
58
 
 
59
 
    class cmd_serve(bzrlib.builtins.cmd_serve):
60
 
        __doc__ = _original_command.__doc__
61
 
 
62
 
        takes_options = _original_command.takes_options + [
63
 
            Option('http',
64
 
                help='Run an http (Loggerhead) server to browse code, '
65
 
                    'by default on port %s.' % DEFAULT_PORT)]
66
 
 
67
 
        def run(self, *args, **kw):
68
 
            if 'http' in kw:
69
 
                # loggerhead internal code will try to 'import loggerhead', so
70
 
                # let's put it on the path
71
 
                import os.path, sys
72
 
                sys.path.append(os.path.dirname(__file__))
73
 
 
74
 
                from loggerhead.apps.filesystem import BranchesFromFileSystemRoot
75
 
                from paste.httpexceptions import HTTPExceptionHandler
76
 
                from paste.httpserver import serve
77
 
                a = HTTPExceptionHandler(BranchesFromFileSystemRoot('.'))
78
 
                port = kw.get('port', DEFAULT_PORT)
79
 
                # port might be an int already...
80
 
                if isinstance(port, basestring) and ':' in port:
81
 
                    host, port = port.split(':')
 
60
    HELP = ('Loggerhead, a web-based code viewer and server. (default port: %d)' %
 
61
            (DEFAULT_PORT,))
 
62
 
 
63
    def setup_logging(config):
 
64
        import logging
 
65
        import sys
 
66
 
 
67
        logger = logging.getLogger('loggerhead')
 
68
        handler = logging.StreamHandler(sys.stderr)
 
69
        handler.setLevel(logging.DEBUG)
 
70
        logger.addHandler(handler)
 
71
        logging.getLogger('simpleTAL').addHandler(handler)
 
72
        logging.getLogger('simpleTALES').addHandler(handler)
 
73
 
 
74
 
 
75
    def _ensure_loggerhead_path():
 
76
        """Ensure that you can 'import loggerhead' and get the root."""
 
77
        # loggerhead internal code will try to 'import loggerhead', so
 
78
        # let's put it on the path if we can't find it in the existing path
 
79
        try:
 
80
            import loggerhead.apps.transport
 
81
        except ImportError:
 
82
            import os.path, sys
 
83
            sys.path.append(os.path.dirname(__file__))
 
84
 
 
85
    def serve_http(transport, host=None, port=None, inet=None):
 
86
        from paste.httpexceptions import HTTPExceptionHandler
 
87
        from paste.httpserver import serve
 
88
 
 
89
        _ensure_loggerhead_path()
 
90
 
 
91
        from loggerhead.apps.transport import BranchesFromTransportRoot
 
92
        from loggerhead.config import LoggerheadConfig
 
93
 
 
94
        if host is None:
 
95
            host = DEFAULT_HOST
 
96
        if port is None:
 
97
            port = DEFAULT_PORT
 
98
        argv = ['--host', host, '--port', str(port), '--', transport.base]
 
99
        if not transport.is_readonly():
 
100
            argv.insert(0, '--allow-writes')
 
101
        config = LoggerheadConfig(argv)
 
102
        setup_logging(config)
 
103
        app = BranchesFromTransportRoot(transport.base, config)
 
104
        app = HTTPExceptionHandler(app)
 
105
        serve(app, host=host, port=port)
 
106
 
 
107
    if transport_server_registry is not None:
 
108
        transport_server_registry.register('http', serve_http, help=HELP)
 
109
    else:
 
110
        import bzrlib.builtins
 
111
        from bzrlib.option import Option
 
112
 
 
113
        _original_command = commands.get_cmd_object('serve')
 
114
 
 
115
        class cmd_serve(bzrlib.builtins.cmd_serve):
 
116
            __doc__ = _original_command.__doc__
 
117
 
 
118
            takes_options = _original_command.takes_options + [
 
119
                Option('http', help=HELP)]
 
120
 
 
121
            def run(self, *args, **kw):
 
122
                if 'http' in kw:
 
123
                    from bzrlib.transport import get_transport
 
124
                    allow_writes = kw.get('allow_writes', False)
 
125
                    path = kw.get('directory', '.')
 
126
                    port = kw.get('port', DEFAULT_PORT)
 
127
                    # port might be an int already...
 
128
                    if isinstance(port, basestring) and ':' in port:
 
129
                        host, port = port.split(':')
 
130
                    else:
 
131
                        host = DEFAULT_HOST
 
132
                    if allow_writes:
 
133
                        transport = get_transport(path)
 
134
                    else:
 
135
                        transport = get_transport('readonly+' + path)
 
136
                    serve_http(transport, host, port)
82
137
                else:
83
 
                    host = '0.0.0.0'
84
 
                serve(a, host=host, port=port)
85
 
            else:
86
 
                super(cmd_serve, self).run(*args, **kw)
87
 
 
88
 
    register_command(cmd_serve)
 
138
                    super(cmd_serve, self).run(*args, **kw)
 
139
 
 
140
        commands.register_command(cmd_serve)
 
141
 
 
142
    class cmd_load_test_loggerhead(commands.Command):
 
143
        """Run a load test against a live loggerhead instance.
 
144
 
 
145
        Pass in the name of a script file to run. See loggerhead/load_test.py
 
146
        for a description of the file format.
 
147
        """
 
148
 
 
149
        takes_args = ["filename"]
 
150
 
 
151
        def run(self, filename):
 
152
            from bzrlib.plugins.loggerhead.loggerhead import load_test
 
153
            print 'starting script'
 
154
            script = load_test.run_script(filename)
 
155
            for worker,_  in script._threads.itervalues():
 
156
                for url, success, time in worker.stats:
 
157
                    print ' %5.3fs %s %s' % (time, str(success)[0], url)
 
158
 
 
159
    commands.register_command(cmd_load_test_loggerhead)
 
160
 
 
161
    def load_tests(standard_tests, module, loader):
 
162
        _ensure_loggerhead_path()
 
163
        standard_tests.addTests(loader.loadTestsFromModuleNames(
 
164
            ['bzrlib.plugins.loggerhead.loggerhead.tests']))
 
165
        return standard_tests