-
Notifications
You must be signed in to change notification settings - Fork 3
/
gwg-server.py
112 lines (96 loc) · 3.66 KB
/
gwg-server.py
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
#!/usr/bin/env python
from enum import Enum, unique
import socketserver
import sys
import threading
import time
from config import config
from gwg import find_valid_points, load_map_points, get_data_from_nearest_point
@unique
class GWGServerState(Enum):
INITIALIZING = (1,)
DISTRIBUTING = (2,)
FINALIZING = 3
# try:
# val = next(self.factory.pool)
# point, id = val
# lat, lon = point
# export = "DATA:{}:{}:{}".format(lat, lon, id)
# self.sendLine(export.encode("utf-8"))
# except StopIteration:
# self.factory.transitionState()
class GWGServerHandler(socketserver.StreamRequestHandler):
def handle(self):
response = "TAW"
if self.server.state is None:
response = "ALEPH"
elif self.server.state == GWGServerState.INITIALIZING:
response = "INIT"
elif self.server.state == GWGServerState.DISTRIBUTING:
try:
val = next(self.server.pool)
point, id = val
lat, lon = point
response = "DATA:{}:{}:{}".format(lat, lon, id)
except StopIteration:
self.server.transitionState()
elif self.server.state == GWGServerState.FINALIZING:
response = "DONE"
else:
response = "TAW"
self.wfile.write(bytes(response, "utf-8"))
class GWGServer(socketserver.ThreadingMixIn, socketserver.TCPServer):
def __init__(self, server_addr, handler):
socketserver.TCPServer.__init__(self, server_addr, handler)
self.state = None
self.pool = None
self.white_rabbit = False
def transitionState(self, error=False):
if error:
self.state = GWGServerState.FINALIZING
else:
if self.state is None:
self.state = GWGServerState.INITIALIZING
elif self.state == GWGServerState.INITIALIZING:
self.state = GWGServerState.DISTRIBUTING
elif self.state == GWGServerState.DISTRIBUTING:
self.state = GWGServerState.FINALIZING
def initializeData(self):
self.pool = initialize_data()
self.transitionState()
def initialize_data():
print("Server data initializing.")
all_valid_points = [find_valid_points(entry) for entry in config["mapping"]]
valid_points = list(all_valid_points[0].intersection(*all_valid_points[1:]))
print("> Number of valid points: {}".format(len(valid_points)))
prop_map, multipoint = load_map_points(valid_points, config["station_id_field"])
if "samples" not in config or config["samples"] is None:
config["samples"] = len(valid_points)
station_ids = [
get_data_from_nearest_point(p, prop_map, multipoint)
for p in valid_points[: config["samples"]]
]
print("Server data initialization complete.")
return iter(station_ids)
if __name__ == "__main__":
host = sys.argv[1]
port = int(sys.argv[2])
server = GWGServer((host, port), GWGServerHandler)
with server:
start_time = time.monotonic()
main_thread = threading.Thread(target=server.serve_forever)
main_thread.daemon = True
main_thread.start()
server.transitionState()
server.initializeData()
start_time = time.monotonic()
print("Starting to serve data.")
# We will actually use the generator here
while server.state != GWGServerState.FINALIZING:
pass
end_time = time.monotonic()
print("Finished serving data. It took", end_time - start_time, "seconds.")
print("Resting for 35 seconds for any last connections.")
time.sleep(35)
end_time = time.monotonic()
server.shutdown()