Newsgroup: it.comp.programmare.win32
Titolo: [?] Gestione degli accessi: se il programma si pianta?

Ho scritto un programma che tra le altre cose gestisce gli accessi per
il suo utilizzo.
Praticamente ho un server con SQLServer e il mio programma che gira sui
vari client. Quando un utente lancia il programma, questo chiede nome e
password, controlla in una tabella del db se corrispondono e in caso
affermativo registra in un'altra tabella l'avvenuto accesso.
Quando il programma viene chiuso nella stessa tabella registro l'uscita.
Questa la struttura delle due tabelle che interessano
(i dati sono inventati)
operatori
+----------+----------+-----------------+
| login    | password | livello_accesso |
+----------+----------+-----------------+
| marcopaf | filino   | 0               |
| gingomuf | gargiano | 1               |
| birobiro | barufala | 1               |
| test     | test     | 1               |
| admin    | 3jr23mj4 | 2               |
+----------+----------+-----------------+
accessi
+----------+----------+------------------+
| in/out   | login    | data_ora         |
+----------+----------+------------------+
| 1        | admin    | 03/05/2002 15:23 |
| 1        | birobiro | 03/05/2002 15:34 |
| 0        | birobiro | 03/05/2002 16:13 |
| 0        | admin    | 03/05/2002 17:26 |
| 1        | test     | 03/05/2002 19:19 |
+----------+----------+------------------+
Ora per impedire che l'utente usi più copie del programma
contemporaneamente, o che si colleghi da un'altra postazione
dimenticandosi prima di chiudere il programma in quella precedente,
all'avvio controllo anche che lo stesso non risulti già collegato.
Tutto funziona bene finchè il programma funziona bene.
Purtroppo il programma non è esente da bug e la sfiga è molto brava
a trovarli prima di me!
Ora nel caso che il programma si pianti, l'utente non riesce più a
loggarsi, perchè secondo quanto registrato nelle tabelle sta già
usando il programma. Il problema l'ho risolto temporaneamente con un
altro programma, denominato sblocco, che, dietro richiesta di username e
password, inserisce nella tabella accessi la voce di uscita che avrebbe
dovuto inserire il programma stesso se fosse riuscito ad arrivare alla
fine.
L'unico difetto di questa soluzione e che se un utente lancia lo sblocco
quando sta usando il programma, alla fine nella tabella accessi
risulterà un uscita extra, ma questo fino a ieri non mi dava problemi.
Questa invece la situazione a oggi.
Il programma si è evoluto, e fa molte cose. Tra queste durante la sua
attività marchia alcuni record di alcune tabelle come "in uso da parte
dell'utente", questo mediante un apposito campo "usato_da" del record
stesso. Ora in caso di blocco del programma tali record continuano ad
essere considerati in uso, per cui avrei bisogno di ampliare il
programma di sblocco in modo che, oltre a registrare un'uscita, sblocchi
i record utilizzati dall'utente.
Ampliando lo sblocco in tal modo però il difetto descritto sopra diventa
un vero e proprio errore, infatti se un utente facesse lo sblocco con il
programma attivo, i record da lui usati risulterebbero liberi, quindi
un altro utente potrebbe modificarglieli sotto il naso.
Come risolvere il problema?
Io ho pensato ad alcuni modi, entrambi basati sul tentativo di
tenere monitorato lo stato di attività del programma principale, ma non
riescono a garantirmi al 100% da eventuali problemi.
Soluzione A
Un terzo programma detto "controllo" che viene avviato insieme al
principale sulla stessa macchina e che periodicamente controlla la lista
dei processi.
Se da questa vede sparire il programma senza che questo (ad esempio
tramite una connessione TCP) gli abbia comunicato la normale chiusura,
avvia automaticamente lo sblocco.
Problemi
Se il blocco del programma avviene per un problema sulla rete o per un
problema hardware sulla macchina (esempio banale, qualche idiota la
spegne) "controllo" non è in grado di collegarsi a SQLserver per
effettuare le registrazioni.
Soluzione B
Un terzo programma come nella soluzione A, solo che in caso di problemi
non effettua lui le operazioni, ma ordina di farle ad un quarto
programma detto "controllo_server" sempre in ascolto sul server.
In questo caso se cade la rete è "controllo_server" ad effettuare lo
sblocco quando rileva la caduta della connessione.
Problema
Se cade la connessione, non è detto che il programma dall'altra parte si
sia piantato, anzi normalmente se stacco il cavo di rete mentre l'utente
sta inserendo dei dati e lo riattacco prima che questo salvi, il
programma non se ne accorge nemmeno.
Soluzione C
Ampliamento della soluzione B.
Potrei, nel caso che "controllo_server" rilevi la caduta della rete,
iniziare a fargli fare dei ping alla macchina finchè non riprende a
rispondere, quando riprende riprovo a collegarmi a "controllo", se
questo riponde tutto ok, è stata solo un'interruzione temporanea,
altrimenti avvio lo sblocco.
Problemi
Non so come si fanno dei ping da VB.
Ci può essere la seguente situazione patologica.
Il computer è spento, "controllo_server" sta facendo dei ping in attesa
che il pc riparta... ma l'inconveniente è avvenuto poco prima del
termine del turno di lavoro dell'operatore e costui è già con le chiavi
infilate nel cruscotto e il piede sull'acceleratore.
Potranno passare ore prima che quel pc riparta, non posso permettermi
che i record rimangano bloccati così a lungo.
Soluzione D
Quando registro l'ingresso e l'uscita dal programma, registro anche l'IP
della macchina da cui il programma viene lanciato.
Quando si lancia lo sblocco, se la macchina è diversa da quella su cui
risulta in esecuzione il programma, lo sblocco avverte che va eseguito
da quell'altro pc. Se è la stessa, si può controllare nella lista dei
processi se effettivamente il programma è ancora in esecuzione.
Problema
Lo stesso della soluzione C, se il programma si blocca quando
l'operatore sta per terminare il turno, questo non sta a lanciare lo
sblocco, ma prende e se ne va a casa.
Ulteriore problema comune a tutte le soluzioni:
il programma è scritto in VB; andare a vedere se nella lista dei
processi c'è ancora il programma interessato non mi pare una cosa tanto
semplice da farsi in VB.
Grazie in anticipo per le eventuali risposte.
-- 
Samuele Battarra
prova il mio newsreader:
http://digilander.iol.it/battarsa/programmi/news/

 riescono a garantirmi al 100% da eventuali problemi.
Io lo farei in un altro modo, tipo "watchdog": ogni 'X' minuti fai
aggiornare il record della tabella degli utenti loggati, aggiornando
cosi` l'orario. Poi ogni 'Y' minuti fai eseguire sul server una query
che verifica i record che non sono stati aggiornati da piu` di 'X+Z'
minuti, e se ci sono assumi che l'utente non sia piu` loggato.
Ovviamente nella tabella degli accessi dovrai anche aggiungere un campo
di ID univoco (ad esempio l'indirizzo IP), in modo da riconoscere gli
aggiornamenti del record dai collegamenti da un'altra macchina.
--
Lorenzo