-
Notifications
You must be signed in to change notification settings - Fork 1
/
gestore_segnali.py
340 lines (317 loc) · 15.6 KB
/
gestore_segnali.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
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
"""
Autore: Francesco Antonetti Lamorgese Passeri
This work is licensed under the Creative Commons Attribution 4.0 International
License. To view a copy of this license, visit
http://creativecommons.org/licenses/by/4.0/ or send a letter to Creative
Commons, PO Box 1866, Mountain View, CA 94042, USA.
"""
from multiprocessing import Process
from time import sleep,time
import logging
ATTESA_CICLO_PRINCIPALE = 0.001
class gestore_segnali(Process):
"""Gestore Segnali
È progettato per essere posto come componente di un processo.
È il componente addetto alla gestione delle comunicazioni del processo
padre con altri processi.
Formato segnale: segnale:timestamp:[estensioni]
Estensioni implementate: mittente:destinatario
Formato segnale completo: segnale:timestamp:mittente:destinatario
Fondamentalmente fa da "cuscinetto" tra il canale di comunicazione tra gli
altri oggetti e l'oggetto stesso. La struttura di base è: canale di
comunicazione con l'esterno (la coda IPC in entrata ed IPC in uscita) e il
canale di comunicazione interno, tra l'oggetto e il Gestore Segnali (le code
Segnali in Entrata e Segnali in Uscita). Se c'è un segnale in arrivo
nella coda IPC in Entrata, il Gestore Segnali fa i vari controlli e lo mette
nella coda in entrata per l'oggetto. Se c'è un segnale nella Coda Segnali in
Uscita, il Gestore Segnali fa i vari controlli e lo mette nella coda IPC in
uscita.
"""
def __init__(self,
padre,
coda_ipc_entrata,
lock_ipc_entrata,
coda_ipc_uscita,
lock_ipc_uscita,
coda_segnali_entrata,
lock_segnali_entrata,
coda_segnali_uscita,
lock_segnali_uscita,
controlla_destinatario = True,
inoltra = False):
"""Inizializza
Inizializza le code per la comunicazione
"""
super().__init__()
logging.info(type(self).__name__ + " inizializzazione")
################# Inizializzazione Gestore Segnali ####################
# Interfaccia con i processi esterni
self.coda_ipc_entrata = coda_ipc_entrata
self.lock_ipc_entrata = lock_ipc_entrata
self.coda_ipc_uscita = coda_ipc_uscita
self.lock_ipc_uscita = lock_ipc_uscita
# Interfaccia con l'oggetto
self.coda_segnali_entrata = coda_segnali_entrata
self.lock_segnali_entrata = lock_segnali_entrata
self.coda_segnali_uscita = coda_segnali_uscita
self.lock_segnali_uscita = lock_segnali_uscita
# Nome dell'oggetto padre
self.padre = str(padre)
# Segnale in uscita attualmente gestito
self.segnale_uscita = {
"segnale": "",
"mittente": "",
"destinatario": ""
}
# Segnale in entrata attualmente gestito
self.segnale_entrata = {
"segnale": "",
"mittente": "",
"destinatario": "",
"timestamp": 0
}
# Effettivamente un workaround: serve per dire al gestore segnali se
# deve inoltrare o meno i segnali che riceve ma non sono indirizzati
# all'oggetto
self.controlla_destinatario = controlla_destinatario
self.inoltra = inoltra
# Stato iniziale
self.stato = "idle"
logging.info(type(self).__name__ + " " + self.padre + " inizializzato")
############## Fine Inizializzazione Gestore Segnali ##################
def run(self):
"""Punto d'entrata del processo/thread"""
# Entra nello stato richiesto
while True:
logging.info(type(self).__name__ + " " + self.padre + \
" entrando in " + self.stato)
s = getattr(self,self.stato)()
if isinstance(s,int):
if s != 0:
break
return int(s)
def idle(self):
"""Idle
Una volta inizializzato, il Gestore Segnale entra nello stato di idle
in attesa di essere avviato.
"""
logging.info(type(self).__name__ + " " + self.padre + " idle")
segnale_spacchettato = []
# Semplicemente due variabili per "facilitare" la gestione del segnale
self.segnale_uscita["segnale"] = ""
self.segnale_uscita["destinatario"] = ""
with self.lock_ipc_uscita:
self.coda_ipc_uscita.put_nowait("idle:" + str(time()) + ":" + \
str(type(self).__name__) + ":")
while True:
# Ripulisci il Segnale Spacchettato e le variabili
# d'appoggio
segnale_spacchettato[:] = ""
self.segnale_uscita["segnale"] = ""
self.segnale_uscita["destinatario"] = ""
# Controlla se ci sono segnali in arrivo
with self.lock_segnali_uscita:
if not self.coda_segnali_uscita.empty():
segnale_spacchettato[:] = \
self.coda_segnali_uscita.get_nowait()
logging.info(segnale_spacchettato)
logging.info("Lunghezza: " + \
str(len(segnale_spacchettato)))
if len(segnale_spacchettato) == 0:
# Se non è arrivato nessun segnale, salta al prossimo ciclo
sleep(ATTESA_CICLO_PRINCIPALE)
continue
if len(segnale_spacchettato) == 2:
# Se il segnale è formato da due parti, allora a posto
self.segnale_uscita["segnale"] = segnale_spacchettato[0]
self.segnale_uscita["destinatario"] = segnale_spacchettato[1]
else:
# Altrimenti il segnale è mal formato. Scartalo e passa al
# ciclo successivo
continue
# Se la "parte segnale" del segnale è stata definita
if self.segnale_uscita["segnale"] != "":
# Se il segnale è indirizzato al Gestore Segnale
if self.segnale_uscita["destinatario"] == type(self).__name__:
# Esegui il segnale se è tra i segnali che il
# Gestore Segnali può interpretare
if self.segnale_uscita["segnale"] in dir(self):
# Esegui l'operazione
self.stato = self.segnale_uscita["segnale"]
return 0
elif self.segnale_uscita["segnale"] == "stop":
# Se il segnale è la richiesta di stop
with self.lock_ipc_uscita:
self.coda_ipc_uscita.put_nowait("terminato:" + \
str(time()) + ":" + \
type(self).__name__ \
+ ":")
self.stato = "termina"
def avvia(self):
"""Avvia
Ciclo principale del Gestore Segnali, una volta avviato.
Controlla continuamente la Coda IPC per i segnali in entrata e la Coda
Segnali Uscita per i segnali pronti ad essere inviati
"""
logging.info(type(self).__name__ + " " + self.padre + " " + "avviato")
i = r = 0
while True:
# Controlla segnali in arrivo
with self.lock_ipc_entrata:
if not self.coda_ipc_entrata.empty():
r = self.ricevi_segnale()
sleep(ATTESA_CICLO_PRINCIPALE)
# Controlla segnali in entrata
with self.lock_segnali_uscita:
if not self.coda_segnali_uscita.empty():
i = self.invia_segnale()
if (i == int(-1)) or (r == int(-1)):
return int(-1)
sleep(ATTESA_CICLO_PRINCIPALE)
def invia_segnale(self):
logging.info(self.padre + " Invia segnale")
self.segnale_uscita["segnale"] = \
self.segnale_uscita["destinatario"] = \
self.segnale_uscita["mittente"] = ""
pacchetto_segnale = ""
segnale_spacchettato = []
# Preleva il segnale da inviare dalla Coda Segnali in Uscita
segnale_spacchettato[:] = self.coda_segnali_uscita.get_nowait()
logging.info(segnale_spacchettato)
# Controlla che il segnale sia ben formato
if self.inoltra:
if len(segnale_spacchettato) == 3:
self.segnale_uscita["segnale"] = segnale_spacchettato[0]
self.segnale_uscita["destinatario"] = segnale_spacchettato[1]
self.segnale_uscita["mittente"] = segnale_spacchettato[2]
if self.segnale_uscita["segnale"] == "" or \
self.segnale_uscita["destinatario"] == self.padre:
pacchetto_segnale = ""
segnale_spacchettato[:] = []
return 1
elif self.segnale_uscita["destinatario"] == \
str(type(self).__name__):
if self.segnale_uscita["segnale"] == "stop":
return int(-1)
else:
pacchetto_segnale = ""
segnale_spacchettato[:] = []
return 1
else:
pacchetto_segnale = \
str(self.segnale_uscita["segnale"]) + ":" + \
str(time()) + ":" + \
str(self.segnale_uscita["mittente"]) + ":" + \
str(self.segnale_uscita["destinatario"])
logging.info(pacchetto_segnale)
self.coda_ipc_uscita.put_nowait(pacchetto_segnale)
return 0
else:
self.segnale_uscita["segnale"] = \
self.segnale_uscita["destinatario"] = \
self.segnale_uscita["mittente"] = ""
pacchetto_segnale = ""
segnale_spacchettato[:] = []
return 0
else:
if len(segnale_spacchettato) == 2:
self.segnale_uscita["segnale"] = segnale_spacchettato[0]
self.segnale_uscita["destinatario"] = segnale_spacchettato[1]
if self.segnale_uscita["segnale"] == "" and \
self.segnale_uscita["destinatario"] == "":
segnale_spacchettato[:] = []
return 1
elif self.segnale_uscita["destinatario"] == \
str(type(self).__name__):
if self.segnale_uscita["segnale"] == "stop":
return int(-1)
else:
pacchetto_segnale = ""
segnale_spacchettato[:] = []
return 1
elif self.segnale_uscita["destinatario"] == self.padre:
pacchetto_segnale = ""
segnale_spacchettato[:] = []
return 1
else:
pacchetto_segnale = \
str(self.segnale_uscita["segnale"]) + ":" + \
str(time()) + ":" + \
str(self.padre) + ":" + \
str(self.segnale_uscita["destinatario"])
logging.info(pacchetto_segnale)
self.coda_ipc_uscita.put_nowait(pacchetto_segnale)
return 0
else:
self.segnale_uscita["segnale"] = \
self.segnale_uscita["destinatario"] = \
self.segnale_uscita["mittente"] = ""
pacchetto_segnale = ""
segnale_spacchettato[:] = []
return 0
def ricevi_segnale(self):
logging.info(self.padre + " Ricevi segnale")
pacchetto_segnale = ""
segnale_spacchettato = []
self.mittente = ""
self.segnale_entrata["segnale"] = ""
self.segnale_entrata["mittente"] = ""
self.segnale_entrata["destinatario"] = ""
self.segnale_entrata["timestamp"] = 0
# Inizia ricezione segnale
pacchetto_segnale = self.coda_ipc_entrata.get_nowait()
logging.info(self.padre)
logging.info(pacchetto_segnale)
segnale_spacchettato[:] = pacchetto_segnale.split(":")
logging.info(self.padre)
logging.info(segnale_spacchettato)
if len(segnale_spacchettato) == 4:
self.segnale_entrata["segnale"] = segnale_spacchettato[0]
self.segnale_entrata["timestamp"] = segnale_spacchettato[1]
self.segnale_entrata["mittente"] = segnale_spacchettato[2]
self.segnale_entrata["destinatario"] = segnale_spacchettato[3]
logging.info("Gestore Segnali " + self.padre)
logging.info(self.segnale_entrata["segnale"])
logging.info(self.segnale_entrata["mittente"])
logging.info(self.segnale_entrata["destinatario"])
logging.info(self.segnale_entrata["timestamp"])
elif len(segnale_spacchettato) == 3:
self.segnale_entrata["segnale"] = segnale_spacchettato[0]
self.segnale_entrata["timestamp"] = segnale_spacchettato[1]
self.segnale_entrata["mittente"] = segnale_spacchettato[2]
logging.info("Gestore Segnali " + self.padre)
logging.info(self.segnale_entrata["segnale"])
logging.info(self.segnale_entrata["mittente"])
logging.info(self.segnale_entrata["timestamp"])
else:
return 1
if self.controlla_destinatario:
if self.segnale_entrata["destinatario"] == self.padre or \
self.segnale_entrata["destinatario"] == "":
logging.info("Gestore Segnali " + self.padre)
logging.info([self.segnale_entrata["segnale"],
self.segnale_entrata["mittente"],
self.segnale_entrata["destinatario"],
self.segnale_entrata["timestamp"]])
if not self.coda_segnali_entrata.full():
self.coda_segnali_entrata.put_nowait(
[self.segnale_entrata["segnale"],
self.segnale_entrata["mittente"],
self.segnale_entrata["destinatario"],
self.segnale_entrata["timestamp"]])
return 1
else:
return 0
else:
logging.info("Gestore Segnali " + self.padre)
logging.info([self.segnale_entrata["segnale"],
self.segnale_entrata["mittente"],
self.segnale_entrata["destinatario"],
self.segnale_entrata["timestamp"]])
if not self.coda_segnali_entrata.full():
self.coda_segnali_entrata.put_nowait( \
[self.segnale_entrata["segnale"],
self.segnale_entrata["mittente"],
self.segnale_entrata["destinatario"],
self.segnale_entrata["timestamp"]])
return 1