-
Notifications
You must be signed in to change notification settings - Fork 3
Expand file tree
/
Copy pathqserver.py
More file actions
executable file
·100 lines (84 loc) · 3.31 KB
/
qserver.py
File metadata and controls
executable file
·100 lines (84 loc) · 3.31 KB
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
#!/usr/bin/env python2
from __future__ import with_statement
import os, sys, threading, signal, time
import logging, logging.handlers
from ConfigParser import ConfigParser
sys.path.append(os.path.join(os.path.dirname(__file__), "lib"))
import fcgi
from dispatcher import RequestDispatcher, Request, ExitRequest
from questserver import QuestServer
from balancer import LoadBalancer
from viewers import IViewer
def prepareLogger(logDir):
LOG_DIRNAME = logDir
if not os.path.isdir(LOG_DIRNAME):
os.makedirs(LOG_DIRNAME)
LOG_FILENAME = os.path.join(LOG_DIRNAME, "qserver.log")
handler = logging.handlers.RotatingFileHandler(LOG_FILENAME, maxBytes=50000000, backupCount=5)
handler.setFormatter(logging.Formatter("%(asctime)s\t%(name)s\t%(module)s\t%(levelname)s:\t%(message)s"))
logger = logging.getLogger()
logger.setLevel(logging.DEBUG)
logger.addHandler(handler)
class FCGIServer:
configFile = "questserver.cfg"
def __init__(self):
configurator = ConfigParser()
assert self.configFile in configurator.read(self.configFile), "Application missconfigure"
prepareLogger(configurator.get("DEFAULT", "log_dir"))
self.balancer = LoadBalancer()
self.srv = QuestServer(configurator, True)
self.working = True
Request.BASE_PATH = self.srv.basePath
IViewer.BASE_URL = self.srv.baseUrl
# Start threads
for _ in xrange(self.srv.workersCount):
threading.Thread(target=self.base_worker).start()
threading.Thread(target=self.backup_worker).start()
# Setup signal handlers
signal.signal(signal.SIGINT, self.signal_handler)
signal.signal(signal.SIGTERM, self.signal_handler)
def base_worker(self):
dispatcher = RequestDispatcher(self.srv)
while self.working:
req = self.balancer.Get()
try:
if isinstance(req, ExitRequest): return
dispatcher.dispatch(req)
except:
logging.exception("while processing request [%s]", req)
finally:
self.balancer.OnFinish(req)
def backup_worker(self):
backupTime = time.time() + 5 * 60
logging.info("next backup time: %s", time.ctime(backupTime))
while self.working:
try:
if time.time() > backupTime:
self.srv.Backup()
backupTime = time.time() + 5 * 60
logging.info("next backup time: %s", time.ctime(backupTime))
time.sleep(0.1)
except:
logging.exception("in backup loop")
def __call__(self):
while fcgi.isFCGI():
try:
req = Request(fcgi.Accept())
self.balancer.Add(req)
except:
logging.exception("bad accepted request")
def signal_handler(self, signum, frame):
logging.warning("Signal %s got. Exiting...", signum)
self.working = False
self.srv.Backup()
for _ in xrange(self.srv.workersCount):
self.balancer.Add(ExitRequest())
print "exiting..."
if __name__ == "__main__":
try:
srv = FCGIServer()
srv()
while threading.activeCount() > 1:
time.sleep(1)
except:
logging.exception("accept queries exception")