File: inspector.py

package info (click to toggle)
tarantool 2.6.0-1.4
  • links: PTS, VCS
  • area: main
  • in suites: sid, trixie
  • size: 85,412 kB
  • sloc: ansic: 513,775; cpp: 69,493; sh: 25,650; python: 19,190; perl: 14,973; makefile: 4,178; yacc: 1,329; sql: 1,074; pascal: 620; ruby: 190; awk: 18; lisp: 7
file content (115 lines) | stat: -rw-r--r-- 3,392 bytes parent folder | download | duplicates (3)
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
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
import os
import yaml
import traceback

import gevent
from gevent.lock import Semaphore
from gevent.server import StreamServer

from lib.utils import find_port
from lib.colorer import color_stdout

from lib.tarantool_server import TarantoolStartError


# Module initialization
#######################


def gevent_propagate_exc():
    """Don't print backtraces and propagate the exception to the parent
    greenlet when Ctrl+C or startup fail hit the process when the active
    greenlet is one of the StreamServer owned.
    """
    ghub = gevent.get_hub()
    for exc_t in [KeyboardInterrupt, TarantoolStartError]:
        if exc_t not in ghub.NOT_ERROR:
            ghub.NOT_ERROR = ghub.NOT_ERROR + (exc_t,)
        if exc_t not in ghub.SYSTEM_ERROR:
            ghub.SYSTEM_ERROR = ghub.SYSTEM_ERROR + (exc_t,)


gevent_propagate_exc()


# TarantoolInspector
####################


class TarantoolInspector(StreamServer):
    """
    Tarantool inspector daemon. Usage:
    inspector = TarantoolInspector('localhost', 8080)
    inspector.start()
    # run some tests
    inspector.stop()
    """

    def __init__(self, host, port):
        # When specific port range was acquired for current worker, don't allow
        # OS set port for us that isn't from specified range.
        if port == 0:
            port = find_port()
        super(TarantoolInspector, self).__init__((host, port))
        self.parser = None

    def start(self):
        super(TarantoolInspector, self).start()
        os.environ['INSPECTOR_HOST'] = str(self.server_host)
        os.environ['INSPECTOR_PORT'] = str(self.server_port)

    def stop(self):
        del os.environ['INSPECTOR_HOST']
        del os.environ['INSPECTOR_PORT']

    def set_parser(self, parser):
        self.parser = parser
        self.sem = Semaphore()

    @staticmethod
    def readline(socket, delimiter='\n', size=4096):
        result = ''
        data = True

        while data:
            try:
                data = socket.recv(size)
            except IOError:
                # catch instance halt connection refused errors
                data = ''
            result += data

            while result.find(delimiter) != -1:
                line, result = result.split(delimiter, 1)
                yield line
        return

    def handle(self, socket, addr):
        if self.parser is None:
            raise AttributeError('Parser is not defined')
        self.sem.acquire()

        for line in self.readline(socket):
            try:
                result = self.parser.parse_preprocessor(line)
            except (KeyboardInterrupt, TarantoolStartError):
                # propagate to the main greenlet
                raise
            except Exception as e:
                self.parser.kill_current_test()
                color_stdout('\nTarantoolInpector.handle() received the ' +
                             'following error:\n' + traceback.format_exc() +
                             '\n', schema='error')
                result = {"error": repr(e)}
            if result is None:
                result = True
            result = yaml.dump(result)
            if not result.endswith('...\n'):
                result = result + '...\n'
            socket.sendall(result)

        self.sem.release()

    def cleanup_nondefault(self):
        if self.parser:
            self.parser.cleanup_nondefault()