summaryrefslogtreecommitdiff
path: root/blobs-multiprocess/proxies/blobs-server.py
blob: b73e0fa8ea467cd09e30b2a0af0d4e6b31aa5de7 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
#!/usr/bin/env python

# This is a multiprocessing blobs server, mostly copied from:
# https://stackoverflow.com/questions/10077745/twistedweb-on-multicore-multiprocessor

from argparse import ArgumentParser

from multiprocessing import cpu_count
from os import environ
from sys import argv, executable, stdout
from socket import AF_INET

from twisted.internet import reactor
from twisted.python import log
from twisted.web.server import Site
from twisted.web.resource import Resource

from leap.soledad.server import get_config
from leap.soledad.server import BlobsResource


def run_server(fd=None, port=None, procs=None, verbose=False):
    if args.verbose:
        log.startLogging(stdout)
        environ['SOLEDAD_LOG_TO_STDOUT'] = '1'

    config = get_config()
    path = config["blobs_path"]
    if not port:
        port = int(config["blobs_port"])

    root = Resource()
    root.putChild('blobs', BlobsResource("filesystem", path))
    factory = Site(root)

    if fd is None:
        # Create a new listening port and several other
        # processes to help out.
        if procs is None:
            procs = cpu_count()
        log.msg('A total of %d processes will listen on port %d.' % (procs, port))
        port = reactor.listenTCP(port, factory)
        for i in range(procs - 1):
            reactor.spawnProcess(
                None, executable, [executable, __file__, str(port.fileno())],
                childFDs={0: 0, 1: 1, 2: 2, port.fileno(): port.fileno()},
                env=environ)
    else:
        # Another process created the port, just start listening on it.
        log.msg('Adopting file descriptor %d...' % fd)
        port = reactor.adoptStreamPort(fd, AF_INET, factory)

    reactor.run()


def parse_args():
    parser = ArgumentParser()
    parser.add_argument('fd', nargs='?', type=int, help='A file descriptor to adopt.')
    parser.add_argument('--verbose', '-v', action='store_true', help='Output logs.')
    parser.add_argument('--port', '-p', type=int, help='The port in which to listen.')
    parser.add_argument('--procs', '-P', type=int, help='Total number of processes.')
    args = parser.parse_args()
    return args


if __name__ == '__main__':
    args = parse_args()
    run_server(fd=args.fd, port=args.port, procs=args.procs, verbose=args.verbose)