Add ability to ignore process prewarming for launch time benchmark
[WebKit-https.git] / PerformanceTests / LaunchTime / feedback_server.py
1 from Queue import Queue
2 import logging
3 import os
4 import socket
5 import threading
6 import time
7
8 # This line makes sure that tornado is installed and in sys.path
9 import thirdparty.autoinstalled.tornado
10 import tornado.ioloop
11 import tornado.web
12 import tornado.websocket
13 import tornado.template
14 from tornado.httpserver import HTTPServer
15
16
17 class FeedbackServer:
18     def __init__(self):
19         self._client = None
20         self._feedback_server_thread = None
21         self._port = 9090
22         self._application = None
23         self._server_is_ready = None
24         self._io_loop = None
25         self._messages = Queue()
26         self._client_loaded = threading.Semaphore(0)
27
28     def _create_app(self):
29         return HTTPServer(tornado.web.Application([
30             (r'/ws', FeedbackServer.WSHandler(self)),
31             (r'/', FeedbackServer.MainHandler(self)),
32         ]))
33
34     def _start_server(self):
35         self._io_loop = tornado.ioloop.IOLoop()
36         self._io_loop.make_current()
37         self._application = self._create_app()
38         while True:
39             try:
40                 self._application.listen(self._port)
41                 print 'Running feedback server at http://localhost:{}'.format(self._port)
42                 break
43             except socket.error as err:
44                 self._port += 1
45             except:
46                 print 'Feedback server failed to start'
47                 break
48         self._server_is_ready.release()
49         self._io_loop.start()
50
51     def _send_all_messages(self):
52         if self._client:
53             while not self._messages.empty():
54                 message = self._messages.get()
55                 self._client.write_message(message)
56
57     def start(self):
58         self._server_is_ready = threading.Semaphore(0)
59         self._feedback_server_thread = threading.Thread(target=self._start_server)
60         self._feedback_server_thread.start()
61         self._server_is_ready.acquire()
62         return self._port
63
64     def stop(self):
65         self._client_loaded = threading.Semaphore(0)
66         self._application.stop()
67         self._io_loop.add_callback(lambda x: x.stop(), self._io_loop)
68         self._feedback_server_thread.join()
69
70     def send_message(self, new_message):
71         self._messages.put(new_message)
72         self._io_loop.add_callback(self._send_all_messages)
73
74     def wait_until_client_has_loaded(self):
75         self._client_loaded.acquire()
76
77     @staticmethod
78     def MainHandler(feedback_server):
79         class Handler(tornado.web.RequestHandler):
80             def get(self):
81                 loader = tornado.template.Loader('.')
82                 client_path = os.path.join(os.path.abspath(os.path.dirname(__file__)), 'feedback_client.html')
83                 self.write(loader.load(client_path).generate(port=feedback_server._port))
84
85         return Handler
86
87     @staticmethod
88     def WSHandler(feedback_server):
89         class Handler(tornado.websocket.WebSocketHandler):
90             def open(self):
91                 feedback_server._client = self
92                 feedback_server._client_loaded.release()
93
94             def on_close(self):
95                 feedback_server._client = None
96
97         return Handler