Your SlideShare is downloading. ×
Università Degli Studi di Trieste
                 Facoltà di Ingegneria
  Corso di Laurea Specialistica in Ingegneria Inf...
Talk is cheap. Show me the code!
                (Linus Torvalds)
Indice



1 Introduzione                                                                      1

2 Il caso di studio      ...
ii                                                                          INDICE

     4 GEC_Scan                       ...
Capitolo      1
Introduzione

La gestione di un documento cartaceo per via informatica inizia con le
operazioni di acquisi...
2                                                                1. Introduzione

        Dall’osservazione della situazio...
Capitolo      2
Il caso di studio

2.1     Situazione iniziale e requisiti
La software house MIDA4 ha prodotto e mantiene ...
4                                                             2. Il caso di studio

    Il software necessario ad aggiunge...
Architettura generale e definizioni                                             5

   • esso deve consentire di proporre al...
6                                                                                                                         ...
Architettura generale e definizioni                                                7

un solo utente utilizzi più istanze d...
8                                                              2. Il caso di studio

    Documento un insieme di più immag...
Architettura generale e definizioni                                                                                        ...
10                                                                      2. Il caso di studio

     Un tipico caso di utili...
Cenni di implementazione e tecnologie utilizzate                               11

   5. GEC_Scan cerca tra i plug in cari...
12                                                                  2. Il caso di studio

     software GEC_Scan che trami...
Capitolo       3
SyncUtils

3.1     Requisiti e scopi di SyncUtils
La parte del progetto che deve interagire più intimamen...
14                                                                  3. SyncUtils

        Siamo perciò interessati ad un t...
Architettura                                                              15

XML ( 3.3.6 nella pagina 28); le risposte al...
16                                                                  3. SyncUtils

     Un attore che voglia prendere posse...
Architettura                                                                   17



                            Response
...
18                                                                    3. SyncUtils

           Per quanto riguarda Respons...
Architettura                                                                  19

   • SendToMyArchiveActionRequest;

   •...
20                                                                    3. SyncUtils

         Tutti i tipi specializzati, fi...
Dettagli implementativi e tecnologie                                                     21

firewall e da un sistema NAT/N...
22                                                                   3. SyncUtils

     ne di inconsistenza come quella ri...
Dettagli implementativi e tecnologie                                              23

    Per impedire che altri processi ...
24                                                                          3. SyncUtils

            • se tale nome file e...
Dettagli implementativi e tecnologie                                       25

Algorithm 3.1 Lock-CleanUp: Da eseguire all...
26                                                                   3. SyncUtils

     Algorithm 3.5 SCAN-Abort: Da esegu...
Dettagli implementativi e tecnologie                                          27

         acquisire il lock;
         leg...
28                                                                           3. SyncUtils

     Le due funzioni utilizzava...
Dettagli implementativi e tecnologie                                            29


     Listing 3.1: Esempio di XML gene...
30                                                             3. SyncUtils

     Listing 3.2: Esempio di XML generato da ...
Dettagli implementativi e tecnologie                                           31

     da identificatori univoci per l’ent...
32                                                                   3. SyncUtils

14       int _count = 0;
15       ...
1...
Dettagli implementativi e tecnologie                                            33

   • nella modalità esplicita, gli ogg...
34                                                                    3. SyncUtils

     l’algoritmo itera finché non è sta...
Dettagli implementativi e tecnologie                                           35

    3.3.8    COM

    COM è acronimo di...
36                                                                            3. SyncUtils

     QueryInterface permette d...
Dettagli implementativi e tecnologie                                                        37

   codice di contorno aggi...
38                                                                 3. SyncUtils


     Listing 3.5: Esempio della decorazi...
Dettagli implementativi e tecnologie                                            39


1   [InterfaceTypeAttribute(ComInterf...
40                                                                     3. SyncUtils

     e classi da queste derivate. Lo ...
Installazione e preparazione dell’ambiente di esecuzione                        41


1   RegAsm.exe nomeDll

        resid...
42   3. SyncUtils
Capitolo       4
GEC_Scan

4.1     Requisiti e progetto dell’interfaccia utente
Il software di acquisizione GEC_Scan dev’e...
44                                                                 4. GEC_Scan

     coda di tipo First In First Out, e va...
Requisiti e progetto dell’interfaccia utente                                  45




       Figura 4.1: Finestra di opzion...
46                                                                    4. GEC_Scan

        • utilizzo del rilevamento auto...
Requisiti e progetto dell’interfaccia utente                                      47

un trascinatore automatico, oppure n...
48                                                                    4. GEC_Scan

        • ruota in senso orario;

     ...
Composizione di GEC_Scan                                                    49

    Infine, chiudendo semplicemente la fines...
Tesi Todone
Tesi Todone
Tesi Todone
Tesi Todone
Tesi Todone
Tesi Todone
Tesi Todone
Tesi Todone
Tesi Todone
Tesi Todone
Tesi Todone
Tesi Todone
Tesi Todone
Tesi Todone
Tesi Todone
Tesi Todone
Tesi Todone
Tesi Todone
Tesi Todone
Tesi Todone
Tesi Todone
Tesi Todone
Tesi Todone
Tesi Todone
Tesi Todone
Tesi Todone
Tesi Todone
Tesi Todone
Tesi Todone
Tesi Todone
Tesi Todone
Tesi Todone
Tesi Todone
Tesi Todone
Tesi Todone
Tesi Todone
Tesi Todone
Tesi Todone
Tesi Todone
Tesi Todone
Tesi Todone
Tesi Todone
Tesi Todone
Tesi Todone
Tesi Todone
Tesi Todone
Tesi Todone
Tesi Todone
Tesi Todone
Tesi Todone
Tesi Todone
Tesi Todone
Tesi Todone
Tesi Todone
Tesi Todone
Tesi Todone
Tesi Todone
Upcoming SlideShare
Loading in...5
×

Tesi Todone

1,926

Published on

Tesi di laurea di Giancarlo Todone dal titolo
"Progetto e realizzazione di una infrastruttura modulare per acquisizione ed archiviazione remota di documenti"

Published in: Technology, Education
0 Comments
0 Likes
Statistics
Notes
  • Be the first to comment

  • Be the first to like this

No Downloads
Views
Total Views
1,926
On Slideshare
0
From Embeds
0
Number of Embeds
0
Actions
Shares
0
Downloads
38
Comments
0
Likes
0
Embeds 0
No embeds

No notes for slide

Transcript of "Tesi Todone"

  1. 1. Università Degli Studi di Trieste Facoltà di Ingegneria Corso di Laurea Specialistica in Ingegneria Informatica Tesi di laurea in reti di calcolatori Progetto e realizzazione di una infrastruttura modulare per acquisizione ed archiviazione remota di documenti LAUREANDO RELATORE Giancarlo Todone Prof. Alberto Bartoli CORRELATORE Ing. Giorgio Davanzo Anno Accademico 2008/2009
  2. 2. Talk is cheap. Show me the code! (Linus Torvalds)
  3. 3. Indice 1 Introduzione 1 2 Il caso di studio 3 2.1 Situazione iniziale e requisiti . . . . . . . . . . . . . . . . . 3 2.2 Architettura generale e definizioni . . . . . . . . . . . . . . 5 2.2.1 Flusso di un tipico caso di utilizzo . . . . . . . . . 9 2.3 Cenni di implementazione e tecnologie utilizzate . . . . . . 11 3 SyncUtils 13 3.1 Requisiti e scopi di SyncUtils . . . . . . . . . . . . . . . . 13 3.2 Architettura . . . . . . . . . . . . . . . . . . . . . . . . . . 14 3.3 Dettagli implementativi e tecnologie . . . . . . . . . . . . 20 3.3.1 Perché il file system? . . . . . . . . . . . . . . . . . 20 3.3.2 Meccanismo di sincronizzazione . . . . . . . . . . . 21 3.3.3 Identificativi di richieste e risposte . . . . . . . . . 23 3.3.4 Protocollo . . . . . . . . . . . . . . . . . . . . . . . 24 3.3.5 Problematiche delle notifiche . . . . . . . . . . . . 27 3.3.6 Formati dei file di comunicazione . . . . . . . . . . 28 3.3.7 Serializzazione XML . . . . . . . . . . . . . . . . . 32 3.3.8 COM . . . . . . . . . . . . . . . . . . . . . . . . . 35 3.4 Installazione e preparazione dell’ambiente di esecuzione . . 40 i
  4. 4. ii INDICE 4 GEC_Scan 43 4.1 Requisiti e progetto dell’interfaccia utente . . . . . . . . . 43 4.1.1 Interfaccia grafica e usabilità . . . . . . . . . . . . 44 4.2 Composizione di GEC_Scan . . . . . . . . . . . . . . . . . 49 4.2.1 TWAIN . . . . . . . . . . . . . . . . . . . . . . . . 50 4.2.2 VisualSlideShow e design delle classi coinvolte . . . 55 4.3 Tecnologie e tecniche implementative . . . . . . . . . . . . 58 4.3.1 dotNetTwain . . . . . . . . . . . . . . . . . . . . . 59 4.3.2 Grafica . . . . . . . . . . . . . . . . . . . . . . . . 68 4.4 Installazione e preparazione dell’ambiente di esecuzione . . 70 5 Sottosistema di archiviazione e plug in 73 5.1 Caratteristiche del sottosistema di archiviazione . . . . . . 73 5.1.1 Funzionalità di manipolazione file . . . . . . . . . . 75 5.2 Design del sottosistema di archiviazione . . . . . . . . . . 76 5.3 Specifiche e tecnologie . . . . . . . . . . . . . . . . . . . . 80 5.3.1 Archiviazione locale e debug . . . . . . . . . . . . . 84 5.3.2 Funzionalità estese ed archiviazione Remota . . . . 85 5.3.2.1 Sharepoint . . . . . . . . . . . . . . . . . 86 5.3.2.2 Google Documents . . . . . . . . . . . . . 92 5.4 Setup dei sistemi di archiviazione . . . . . . . . . . . . . . 97 6 Conclusioni 99 Bibliografia 103
  5. 5. Capitolo 1 Introduzione La gestione di un documento cartaceo per via informatica inizia con le operazioni di acquisizione ed archiviazione. Per “acquisizione” si intende l’operazione di traduzione e codifica di un documento cartaceo in una forma comprensibile e fruibile da un elaboratore. Per “archiviazione” si può distinguere tra la mera operazione di immagazzinamento dati e la “conservazione sostitutiva”—con la quale si intende tutto il complesso di azioni che permettono di conservare elettronicamente dati di valore legale o tributario senza per questo conservare anche i documenti cartacei originali. A seguito e come proseguimento del tirocinio svolto presso la soft- ware house MIDA4, lo scrivente ha realizzato un pacchetto software per consentire di aggiungere le funzionalità di archiviazione al software di contabilità preesistente GEC. Tale pacchetto fornisce una infrastruttura per interfacciare GEC con altri sistemi di archiviazione (già esistenti o futuri) grazie ad un sistema estendibile con plug in, e si inserisce in un più ampio contesto di gestione documentale in sviluppo nel “Laborato- rio Reti” del DEEI, Università Degli Studi di Trieste. Un tema trattato con particolare riguardo è quello dell’archiviazione remota, cioè l’inte- grazione con servizi di terze parti—come Google Documents o Microsoft Sharepoint—per la memorizzazione dei dati su un server connesso ad Internet. 1
  6. 6. 2 1. Introduzione Dall’osservazione della situazione di partenza, dopo lo studio del pro- blema nella sua accezione più generale, sono stati definiti dei requisiti che hanno portato alla suddivisione del lavoro nei tre moduli software responsabili di comunicazione, acquisizione e archiviazione; per ognuno dei tre moduli sono stati definiti ulteriori requisiti in base ai quali sono state poi concepite l’architettura e le specifiche tecnologiche di ogni sin- gola parte. Ogni classe o componente sviluppato è stato verificato con metodologie di unit-test ed in alcuni casi anche con test automatici di carico. L’intero progetto ha subito anche diversi test funzionali condotti da operatori umani. I requisiti tecnologici del committente hanno portato alla scelta del linguaggio C# e del framework dotNet all’interno dell’ambiente di svi- luppo integrato Visual Studio 2008, su un sistema operativo Windows XP/Vista. L’interfacciamento con le periferiche di acquisizione è gestito con lo standard TWAIN mentre l’interfacciamento con il software GEC è gestito con le tecnologie COM e XML. Nel capitolo 2 si affrontano tematiche di carattere generale inerenti l’insieme del software sviluppato. Nei tre capitoli successivi ( 3 nella pa- gina 13, 4 nella pagina 43, 5 nella pagina 73) si affrontano separatamente i tre moduli software, esponendo di ognuno: • situazione pregressa e/o requisiti; • architettura e definizioni; • tecniche implementative e tecnologie utilizzate; aggiungendo—ove pertinente—un breve riassunto delle operazioni necessarie all’installazione e alla manutenzione del modulo.
  7. 7. Capitolo 2 Il caso di studio 2.1 Situazione iniziale e requisiti La software house MIDA4 ha prodotto e mantiene il software di con- tabilità chiamato GEC. La necessità dei clienti di MIDA4 di archiviare documenti per via informatica contestualizzandoli con le loro situazioni amministrative e altri dati, ha spinto la software house a ricercare un modo per ampliare in tal senso le capacità del suo prodotto. La richiesta era quella di aggiungere le funzionalità desiderate in un modo che permettesse di iniziare a servirsi di tecnologie più recenti e promettenti senza per questo dover riscrivere da capo un programma già rodato e funzionante come GEC. GEC viene attualmente fornito in due versioni: installabile e ASP (2.2): • la versione installabile è un normale programma che risiede ed ope- ra sul personal computer dell’utente finale, ed eventualmente co- munica con un server centralizzato per recuperare informazioni di licenza ed aggiornamenti; • la versione ASP consiste nella versione installabile montata però su un server accessibile da molti fruitori contemporaneamente tramite Internet ed un software di remote desktop. 3
  8. 8. 4 2. Il caso di studio Il software necessario ad aggiungere le funzionalità di archiviazione de- siderate, deve necessariamente interagire con GEC—qualsiasi sia la sua ubicazione—ma deve anche interagire con l’hardware dell’utente fina- le (es: scanner e fotocamere) e deve essere in grado di comunicare autonomamente con eventuali servizi di archiviazione di terze parti. Il modo in cui il nuovo software si integra con GEC deve 1. richiedere il minimo sforzo in termini di modifiche al codice sorgente di GEC; 2. essere facilmente utilizzabile dagli sviluppatori di GEC; 3. permettere l’integrazione futura con nuovi servizi di terze parti senza riscrivere il codice sorgente; per poter permettere rispettivamente: 1. di rendere il più possibile indipendenti lo sviluppo e il manteni- mento di GEC da quelli del nuovo software di archiviazione; 2. di consentire una rapida integrazione al momento del rilascio; 3. di poter essere rapidamente espandibile con nuove funzionalità. Dal punto di vista dell’utente, il software sviluppato dev’essere: • facilmente integrabile con il proprio sistema di produzione; • di utilizzo semplice ed immediato. In quest’ottica, un sistema di astrazione delle periferiche di acquisi- zione immagini dell’utente è stato posto come requisito; fondamentale è anche la trasparenza di tale meccanismo, necessaria al fine di ottenere un’interfaccia grafica consistente per tutti gli utenti, a prescindere da marca e modello dei loro hardware. Infine, la scelta dell’ambiente di sviluppo ha dovuto tenere conto di varie richieste: • GEC opera in ambiente Microsoft Windows, e quindi anche il nuovo software di archiviazione deve funzionare almeno in tale sistema;
  9. 9. Architettura generale e definizioni 5 • esso deve consentire di proporre all’utente finale un’interfaccia piacevole, immediata e consistente; • metodologie, linguaggi, librerie, framework utilizzati (a parte quelli finora citati che hanno diverse motivazioni) devono essere allo stato dell’arte, o quantomeno ancora vivamente supportati da produttori e da una nutrita schiera di sviluppatori; essi devono però permet- tere allo sviluppatore di interfacciarsi anche con moduli software utilizzanti tecnologie meno recenti, come TWAIN o Visual Basic 6 (di cui—come vedremo—fanno uso alcune parti del sistema). Da ciò si evince come la capacità di interoperabilità tra diverse tecnolo- gie sia essa stessa un requisito; viste queste necessità, in fase di analisi preliminare è stato posto l’utilizzo del dotNet framework di Microsoft come requisito. 2.2 Architettura generale e definizioni Per motivi di natura tecnica e per questioni di manutenibilità del codice che vedremo in seguito, il modulo che dovrà svolgere le operazioni di acquisizione e archiviazione dev’essere indipendente, cioè non fare parte di GEC, ma essere compilato in un eseguibile autonomo: questo significa che GEC e il nuovo software di acquisizione sono due entità distinte che necessitano di comunicare. Si considerino quindi i seguenti attori: GEC è il programma di contabilità già esistente, che dovrà subire delle modifiche per poter utilizzare SyncUtils e comunicare con il soft- ware di nuova creazione dedicato all’acquisizione e archiviazione; in seguito, se non esplicitamente specificato, col nome di GEC ci si riferirà indistintamente al programma in versione tradizionale o ASP; GEC_Scan è il software di acquisizione e archiviazione: esso è un soft- ware a se stante, ma può dialogare con GEC—tramite un mec- canismo descritto in 3.3 nella pagina 20—e con servizi di terze parti—mediante dei moduli aggiuntivi chiamati plug in ( 5.3 nella pagina 80).
  10. 10. 6 2. Il caso di studio ASP Remote desktop Internet (A) User 1 GEC_Scan ASP Remote desktop GEC-2 (B) User 2 ASP GEC-1 GEC_Scan GEC-3 (C) User 3 GEC_Scan Figura 2.1: Tre casi di utilizzo del sistema di archiviazione: nel caso (A) l’utente 1 utilizza solo l’istanza 1 di GEC tramite ASP e il suo sistema di remote desktop; nel caso (C) l’utente 3 utilizza solo GEC-3 in esecuzione sul suo computer locale; nel caso (B), l’utente 2 utilizza sia la locale istanza 2 di GEC, sia GEC-1 tramite sistema ASP. Queste due entità devono poter comunicare tra loro in vario modo. Nel caso più semplice GEC e GEC_Scan vengono eseguiti sullo stesso calcolatore e comunicano senza interferenze esterne; in figura 2.1 si os- servano anche i casi in cui GEC sia remoto e quello più complesso in cui
  11. 11. Architettura generale e definizioni 7 un solo utente utilizzi più istanze di GEC, eventualmente miste tra locali e remote. plug in SyncUtils GEC GEC_Scan plug in plug in                         acquisizione archiviazione                                             comunicazioni funzionalità                                                                 software software preesistente nuovo Figura 2.2: Descrizione dei software coinvolti; GEC è preesistente e viene modificato solo per poter usare SyncUtils; il resto del software è sviluppato ex novo; di questo è visibile la suddivisione in comunicazioni, acquisizione ed archiviazione: solo le ultime due implementano funzionalità richieste, mentre la prima serve a rendere interoperabili nuovo e vecchio software. Come illustrato in figura 2.2, tutte le funzionalità aggiunte risiedono in GEC_Scan e nei suoi plug in, mentre la libreria SyncUtils consente a GEC di comunicare con GEC_Scan e di utilizzare tali funzionalità. Si consideri inoltre la seguente nomenclatura: Utente è l’utente finale di GEC e di GEC_Scan, colui che opera i pro- grammi per archiviare documenti; si faccia attenzione alla differen- za tra “utente finale” e l’utente di una libreria (sviluppatore) o di un servizio (potrebbe essere un modulo software);
  12. 12. 8 2. Il caso di studio Documento un insieme di più immagini corredate da meta dati; ASP acronimo di Application Service Provider, è il sistema che permet- te tramite un remote desktop di utilizzare dal PC dell’utente finale un’istanza di GEC in esecuzione su un server remoto; da non con- fondersi con Active Server Pages di Microsoft (di cui non si parla mai in questo testo); Plug in è un modulo software che consente di aggiungere funzionalità a GEC_Scan senza la necessità di modificare o ricompilare il suo codice sorgente; Servizio esterno un qualsiasi servizio di archiviazione di documenti estraneo sia a GEC che a GEC_Scan, probabilmente pubblicato tramite un servizio web. Sessione di acquisizione l’insieme di operazioni iniziate dall’utente che portano all’acquisizione, riorganizzazione in documenti e archi- viazione di un insieme di immagini con i loro meta dati associati (punti da 2 a 9 in 2.2.1 nella pagina 10 e figura 2.3; si noti che tra il punto 3 e il punto 4 il sistema rimane indefinitamente in attesa di istruzioni dall’utente; quindi può essere un operazione che richiede molto tempo). In aggiunta—se non per esigenze particolari—si eviterà di seguito l’uti- lizzo di termini come “server” e “client” per riferirsi a GEC o GEC_Scan, poiché potrebbero essere causa di fraintendimenti; infatti nella sua ver- sione ASP, il software GEC viene eseguito su una macchina che interpreta il ruolo di server, ma per correttezza dovrebbe essere considerato client del software di acquisizione che gli offre per l’appunto un servizio.
  13. 13. Architettura generale e definizioni 9 2.2.1 Flusso di un tipico caso di utilizzo 1.richiede inizio sessione di acquisizione Utente 2.Request 3.mostra form principale Acquisizione (tempo indefinito) 4.accetta o annulla (C): GEC_SCAN (B): SyncUtils (A): GEC tempo 5.esegue il plug in adeguato 6.sottomette (E): Servizio esterno documenti (D): Plug in 7.fine del job 8.fine del job 9.Response Figura 2.3: Flusso di esecuzione di una richiesta e relativa risposta; vede- re 2.2.1 nella pagina successiva per una descrizione puntuale dei passi nume- rati; la progettazione e creazione delle entità marcate come (B), (C) e (D) costituiscono il caso di studio; le linee ondulate indicano il punto in cui l’utente può causare un’attesa a tempo indeterminato del sistema; (B) risolve i proble- mi di comunicazione tra (A) e (C) siano essi sulla stessa macchina oppure su macchine diverse comunicanti tramite Internet.
  14. 14. 10 2. Il caso di studio Un tipico caso di utilizzo del sistema—nel quale una singola istanza di GEC comunica con una singola istanza di GEC_Scan—si svolge co- me di seguito (i punti numerati si riferiscono a figura 2.3 nella pagina precedente): • il sistema dell’utente si avvia; parte automaticamente anche il soft- ware di acquisizione e carica dalla cartella plugins le estensioni di cui è stato dotato; • l’utente carica e opera GEC (versione installabile o ASP), mentre il programma di acquisizione (eseguito allo start up sul sistema dell’utente) resta in attesa nascosto; 1. l’utente esegue un’operazione su GEC per la quale è prevista l’acquisizione di un certo numero di documenti; 2. GEC—tramite una chiamata all’apposita libreria di comunicazione SyncUtils—effettua una richiesta a GEC_Scan; ad esso (sia que- sto in esecuzione sulla medesima macchina o su di una diversa) viene segnalato di mostrare la sua finestra principale, inviandogli nel contempo i meta dati da associare ai documenti che si andrà ad acquisire ed una lista di azioni desiderate da intraprendere su di essi; se la finestra era già aperta a seguito di una precedente richiesta non ancora soddisfatta, il lavoro viene messo in coda; 3. GEC_Scan accetta la richiesta e la accoda ad una lista o la scarta rispondendo con una lista di errori (ad esempio quando non è in grado di gestire la richiesta); 4. l’utente usa le funzionalità del programma di acquisizione per scan- sionare1 ed ordinare un certo numero di pagine inerenti la richiesta accettata; l’utente può inserire dei separatori tra gruppi di immagi- ni per organizzare il materiale acquisito in documenti: ad ogni do- cumento vengono associati tutti i meta dati ricevuti; alla fine della riorganizzazione e separazione dei documenti, l’utente sottomette i dati o annulla la sessione con appositi comandi; 1 Sulla scelta tra gli equivalenti italiani dell’inglese “to scan” l’Accademia della Crusca si è espressa nelle “Risposte ai quesiti” concludendo che sono accettabili tutte le soluzioni (scandire, scannare, scannerare, scannerizzare, scansionare) [3].
  15. 15. Cenni di implementazione e tecnologie utilizzate 11 5. GEC_Scan cerca tra i plug in caricati quelli in grado di soddisfare le richieste effettuate da GEC tramite la libreria di comunicazione ed esegue ogni operazione ritenuta pertinente su ogni documento; 6. questo può comportare il dialogo con un ulteriore software di ar- chiviazione, anche residente su una macchina diversa da quella su cui è in esecuzione GEC e da quella su cui esegue il programma di acquisizione (esempio: inviare tutti i documenti ad un servizio web); 7. il software di acquisizione completa ogni elaborazione e compila un rapporto con il dettaglio delle operazioni effettuate e un’eventuale lista di errori; 8. il software di acquisizione invia la risposta così costruita a GEC sempre tramite libreria di comunicazione; 9. GEC riceve la notifica che i suoi lavori richiesti sono stati completati (o annullati); • nel caso la coda di lavori del software di acquisizione non sia vuo- ta, l’utente viene invitato a continuare il suo lavoro con un’altra sessione di sottomissione documenti. 2.3 Cenni di implementazione e tecnologie utilizzate Il programma preesistente GEC è stato sviluppato in Visual Basic 6, kit di sviluppo capace di generare file di codice eseguibile nativo; esso permette anche una buona interazione con componenti COM. Nei seguenti tre capitoli, viene trattato il software sviluppato ex novo per aggiungere a GEC le funzionalità di acquisizione e archiviazione: libreria di comunicazione (progetto di nome “SyncUtils”) che per- mette ad un’istanza di GEC di effettuare richieste ad un’istanza di GEC_Scan e riceverne risposta, in 3 nella pagina 13;
  16. 16. 12 2. Il caso di studio software GEC_Scan che tramite interfaccia grafica permette l’acqui- sizione di documenti, in 4 nella pagina 43; plug in che permettono a GEC_Scan di accedere a servizi di archiviazione di terze parti, in 5 nella pagina 73. Tutti questi moduli software sono stati sviluppati nel linguaggio C# e utilizzano quindi il dotNet framework (versione 2.0 o successive). Con riguardo alla libreria di comunicazione, in 3.3.8 nella pagina 35 si parla della necessaria metodologia di interazione tra codice mana- ged e codice nativo: l’utilizzo di oggetti dotNet come componenti COM tramite software wrapper. Quest’ultimo sistema è stato adottato per permettere a GEC di chia- mare delle funzioni sviluppate con tecnologia dotNet; in questo modo la libreria SyncUtils è richiamabile sia da codice nativo (come avviene per GEC) sia da codice dotNet. Le funzioni di comunicazione utilizzano un meccanismo di sincronia e comunicazione basato sulla condivisione di un file system ( 3.2 nella pa- gina 14) per scambiarsi messaggi XML (formato descritto in 3.3.6 nella pagina 28) secondo il protocollo descritto in 3.3.4 nella pagina 24. La ge- nerazione del codice XML avviene tramite meccanismo semi automatico per serializzazione di oggetti ( 3.3.7 nella pagina 32). Per l’interfacciamento di GEC_Scan con le periferiche di acquisizio- ne immagini è stato usato TWAIN ( 4.2.1 nella pagina 50)—secondo le specifiche versione 1.9 [5]—tramite l’apposito sviluppo della libreria dotNetTwain. TWAIN si presenta come una DLL contenente codice nativo a 32 bit; per l’utilizzo da parte di dotNet, è quindi necessa- rio adottare ulteriori tecniche di interoperabilità con l’aiuto del package System.Runtime.InteropServices ( 4.3.1 nella pagina 59). Ogni plug in è stato sviluppato come una classe dotNet residente in un assembly dotNet2 . Per permettere il rapido sviluppo di plug in sono state sfruttate alcune caratteristiche del framework dotNet come reflection e caricamento dinamico di classi. 2 Un assembly dotNet è una DLL contenente bytecode dotNet nella forma di una o più classi appartenenti anche a diversi namespace, con i rispettivi meta dati di contorno.
  17. 17. Capitolo 3 SyncUtils 3.1 Requisiti e scopi di SyncUtils La parte del progetto che deve interagire più intimamente con GEC è la libreria di comunicazione chiamata SyncUtils. Mentre le funzionalità di archiviazione aggiuntive risiedono principalmente in GEC_Scan e nel- l’insieme dei suoi plug in, esse non potrebbero essere utilizzate da GEC senza l’ausilio di questa libreria: il suo scopo è quello di astrarre il meto- do di comunicazione dalle modalità tecniche con le quali le comunicazioni effettivamente avvengono. L’ambiente nel quale il sistema progettato deve operare prevede: • molti software di scansione (GEC_Scan) che hanno a disposizione varie sorgenti di dati e vengono manovrati da operatori umani; • uno o più software di controllo (GEC) che possano richiedere ad uno dei software di scansione di cominciare una sessione di acquisizione. GEC_Scan deve essere in grado di accettare una richiesta di inizio proce- dura di acquisizione, gestirla autonomamente e inviare alla fine la notifica dell’avvenuto lavoro senza tenere GEC in sospeso, permettendogli così di gestire nel frattempo eventuali altre comunicazioni. 13
  18. 18. 14 3. SyncUtils Siamo perciò interessati ad un tipo di comunicazione nella quale—nel caso peggiore (facendo riferimento alle figure 2.1 nella pagina 6 e 3.1): • come attori, sono coinvolte m istanze di GEC in versione installa- bile (al massimo una per macchina), n istanze remote di GEC in versione ASP, i istanze di GEC_Scan (al massimo una per macchi- na), con i, m ed n numeri imprecisati non necessariamente uguali, maggiori di 1; • ogni attore può prendere l’iniziativa di parola; • ogni GEC in versione installata può parlare col GEC_Scan presente sulla sua stessa macchina (se presente); • ogni GEC in versione ASP può parlare con qualsiasi GEC_Scan; • ogni GEC_Scan può parlare con GEC installato sulla sua stessa macchina e con qualsiasi altro GEC in versione ASP. Cioè: ogni utente col suo calcolatore deve poter usare la sua unica copia di GEC_Scan facendola interagire con un GEC installato sulla sua stessa macchina e/o con un certo numero di altri GEC remoti. 3.2 Architettura Si assuma che ogni copia di GEC_Scan abbia accesso in lettura e scrit- tura ad una porzione privata del file system dell’elaboratore sul quale è installato; chiunque voglia dialogare con esso (ad es. GEC installato o GEC versione ASP) dovrà poter avere accesso in lettura e scrittura alla stessa porzione del file system (per brevità di seguito “file system” o “FS”). La comunicazione è dunque a mezzo condiviso, nel senso che gli attori che dialogano tra loro di volta in volta devono condividere un file system cui hanno accesso; per analizzare il caso più generale continueremo a dire che ogni GEC condivide con l’i-esimo GEC_Scan il file system i (o FS-i). Le richieste vengono effettuate da un GEC scrivendo nel FS-i dei file con estensione .IN contenenti i dettagli delle richieste in formato
  19. 19. Architettura 15 XML ( 3.3.6 nella pagina 28); le risposte al termine di una sessione di acquisizione vengono fornite da GEC_Scan scrivendo nel FS-i dei file con estensione .OUT e nome file uguale alla corrispondente richiesta. GEC ASP ASP GEC GEC FS-i GEC_Scan-i Figura 3.1: Schema dell’utilizzo concorrente da più istanze di GEC del file system i, associato alla i-esima istanza di GEC_Scan. Naturalmente, più processi potrebbero accedere contemporaneamen- te ad uno stesso file system; è tuttavia stato approntato un meccanismo di mutua esclusione (descritto in 3.3.2 nella pagina 21): • per fare in modo che ogni richiesta abbia un nome univoco sul file system i; • per garantire che più GEC concorrenti nell’effettuare una richiesta allo stesso GEC_Scan non si intralcino a vicenda; • per fare in modo che le richieste siano ordinabili—per istante di arrivo—in una coda.
  20. 20. 16 3. SyncUtils Un attore che voglia prendere possesso del mezzo comunicativo costitui- to dal FS-i, per prima cosa utilizzerà detto meccanismo impedendo a qualunque altro attore di impadronirsi a sua volta del file system. Ovviamente non sempre un attore riesce a prenotare l’uso esclusivo del file system, ad esempio quando questo è già in uso da un altro attore; in seguito ( 3.3.2 nella pagina 21) si darà spiegazione dei dettagli del meccanismo: si dica “tentativo di acquisizione del lock ” il tentativo di impadronirsi del mezzo di comunicazione, e “acquisizione del lock ” il provare reiteratamente ad acquisire il lock finché non si abbia successo. La generazione di un nome file univoco nel FS-i, necessaria per la scrittura dei file .IN dipende da una stringa originata a partire dalla da- ta/ora della sua creazione: questa stringa e l’entità che essa rappresenta assumono il nome di JobId. Definiamo quindi un JobId come l’iden- tificativo univoco all’interno di un file system, utilizzato per identificare esattamente richieste e relative risposte. Ogni file di nome {JobId}.IN contiene delle informazioni organiz- zate in un’entità chiamata Request; ogni file di nome {JobId}.OUT contiene dati relativi ad un’entità di tipo Response. Come si può osservare in figura 3.2 nella pagina successiva, ogni Request contiene: • una o più ActionRequest; • uno e un solo AdditionalData; • un Timestamp. In ottica di programmazione ad oggetti, ActionRequest e AdditionalData sono solo delle classi base astratte, atte a definire l’archetipo dei campi contenuti in ogni richiesta: una Request ben for- mata non conterrà mai direttamente una ActionRequest, bensì una classe derivata da essa (similmente per AdditionalData ed altre clas- si simili); d’ora in avanti per “una ActionRequest” ad esempio, si intenderà una qualsiasi entità che derivi da ActionRequest e non un oggetto di tipo ActionRequest, se non diversamente specificato.
  21. 21. Architettura 17 Response Request Document Page ActionRequest ActionResponse ResponsePage Page ActionRequest ResponsePage Page ActionResponse ResponsePage Page AdditionalData ResponsePage Document ActionResponse Page ResponsePage ActionResponse ResponsePage Figura 3.2: Esposizione grafica della struttura di Request e Response; le frecce indicano che l’oggetto d’origine mantiene internamente un riferimento all’oggetto puntato. Le azioni intraprese da GEC_Scan alla ricezione di una Request dipendono dal tipo specializzato di ogni ActionRequest contenuta; AdditionalData contiene dei meta dati che devono essere interpreta- ti da GEC_Scan per soddisfare correttamente ogni richiesta e possono essere associati ai documenti acquisiti.
  22. 22. 18 3. SyncUtils Per quanto riguarda Response essa contiene sempre: • la sezione Documents; • la sezione Errors, relativa agli errori generici di comunicazione. Si ponga attenzione sul fatto che un documento è stato definito come un’insieme di una o più immagini: finora non si è parlato di alcun limite al numero di immagini acquisibili dall’utente, o di vincoli sul modo di raggrupparle in documenti; quindi nè il numero di documenti che ver- ranno elaborati nè il numero di pagine di ognuno di questi è predicibile salvo casi particolari1 . Per questi motivi, in una Response • Documents contiene uno o più oggetti Document, entità rappresentante un gruppo di immagini; • ogni Document contiene una lista di oggetti Page, entità rappresentanti le singole immagini scansionate dall’utente; • ogni Document contiene una o più ActionResponse (con considerazioni simili al caso di ActionRequest); • ogni ActionResponse rappresenta il rapporto su una sola azione intrapresa per il Document che la contiene in seguito all’elaborazione di una ActionRequest; • ogni ActionResponse contiene una lista di ResponsePage, enumerazione delle azioni intraprese sulle singole Page del Document. Anche in questo caso l’esatto contenuto di una ActionResponse dipen- de dalla classe specializzata che la estende. Si pensi al seguente esempio pratico: si ha la necessità di archiviare una fattura del signor Mario Ros- si presso un servizio di archiviazione remota chiamato “MyArchive”; a tale scopo saranno stati precedentemente definiti alcuni tipi specializzati come 1 In realtà GEC può richiedere un numerno minimo ed uno massimo di gruppi di immagini (vedi 4.1.1 nella pagina 47).
  23. 23. Architettura 19 • SendToMyArchiveActionRequest; • SendToMyArchiveActionResponse; • SendToMyArchiveActionPerformer; • SendToMyArchiveResponsePage; derivanti rispettivamente da • ActionRequest; • ActionResponse; • ActionPerformer; • ResponsePage. In più, per veicolare correttamente i dati relativi ad una fat- tura, InvoiceAdditionalData è stato derivato—con l’ag- giunta di appositi campi—da AdditionalData. A que- sto punto è possibile costruire una Request contenente ad esempio una sola SendToMyArchiveActionRequest ed un InvoiceAdditionalData. SendToMyArchiveActionRequest conterrà informazioni relative l’indirizzo al quale raggiungere il servizio MyArchive ed impostazioni simili; InvoiceAdditionalData potrebbe contenere l’anagrafica del signor Mario Rossi e ogni altro dato utile ai fini della compilazione dei meta dati associati ai documenti veri e propri. Se l’utente ha acquisito due documenti da tre pagine ciascuno, con tale ri- chiesta è lecito aspettarsi una risposta per cui vi saranno due Document contenenti tre Page e una SendToMyArchiveActionResponse cia- scuno; ogni SendToMyArchiveActionResponse conterrà a sua volta tre SendToMyArchiveResponsePage, ognuna delle quali—facendo riferimento ad una singola Page—fornirà ad esempio informazioni sul successo o meno dell’archiviazione, un link per recuperare l’immagine corrispondente ecc. . .
  24. 24. 20 3. SyncUtils Tutti i tipi specializzati, finalizzati a specifiche richieste, sono defi- niti nei moduli aggiuntivi chiamati plug in, caricati in modo dinamico all’avvio di GEC_Scan. 3.3 Dettagli implementativi e tecnologie Posto che GEC_Scan è un modulo software a se stante, anche il solo aggiungere a GEC le funzionalità di comunicazione con quest’ultimo ri- chiede necessariamente la modifica del programma e l’aggiunta di molto codice. Integrare direttamente in GEC queste capacità sviluppandole in Vi- sual Basic 6—lo stesso linguaggio in cui è stato scritto—sarebbe potuta sembrare una buona idea: al contrario, aggiungere a del codice già ma- turo una ulteriore complessità per quanto lieve, potrebbe portare a dei problemi di manutenibilità. Se si aggiunge il fatto che il kit di sviluppo di Visual Basic 6 è alla fine del suo ciclo di vita, si capisce come sia stato preferibile comporre il sistema di comunicazione con una tecnologia più moderna: si è scelto di sviluppare con dotNet e la tecnologia COM del codice che—proprio dal punto di vista del ciclo di vita—è autonomo e interfacciabile con GEC con un ridotto numero di modifiche a quest’ultimo. La libreria SyncUtils è utilizzabile da codice dotNet come un qualsiasi altro assembly e (previa registrazione di alcuni tipi, 3.4 nella pagina 40) come componente COM. 3.3.1 Perché il file system? La comunicazione tra sistemi informatici è sempre un ambito insidioso e ricco di difficoltà, spesso nemmeno troppo palesi; anche per questo motivo, nell’affrontarlo si tenta quasi sempre di evitare di reinventare la ruota: come in molte altre situazioni ci si affida più il possibile a soluzioni già note ed affermate, almeno per i problemi più comuni. Nel caso in esame, ci si trova nella situazione abbastanza tipica di un software (GEC_Scan) che pur eseguendo sull’elaboratore di un utente finale (ed essendo perciò molto probabilmente isolato dalla rete da un
  25. 25. Dettagli implementativi e tecnologie 21 firewall e da un sistema NAT/NAPT) deve comportarsi come server, attendendo richieste e non iniziandole. Le possibili soluzioni note che usino protocolli consueti come TCP/IP, sarebbero comunque state tutte piuttosto complesse da mettere in pratica: fortunatamente il sistema ASP—come già accennato—mette a disposizione un file system condiviso tra i suoi utilizzatori. L’utilizzo di un file system condiviso per la sincronia tra processi, la regolamentazione di accesso esclusivo a risorse e lo scambio di informazio- ni, è una pratica da tempo largamente diffusa e di dimostrata efficacia2 : lo studio di alcune specifiche Microsoft [8] ed alcuni esperimenti condotti, hanno consentito di giudicare tali metodologie idonee anche all’utilizzo su un file system condiviso con una macchina remota tramite il sistema ASP. Ciò permette di delegare al gestore del file system alcune problemati- che descritte in seguito come l’atomicità della creazione di un oggetto di sincronia, la sicurezza del canale trasmissivo, la capacità di comunicare in determinate condizioni. 3.3.2 Meccanismo di sincronizzazione L’acquisizione del lock per il file system i, si effettua tramite la scrittura in esso di un file—vuoto—di nome concordato che non possa collidere con gli eventuali file .in e .out già presenti (attualmente esso si chiama lockfile.lck). Si dice che tale lock viene rilasciato quando il file viene cancellato. Un attore che volesse acquisire il lock dovrebbe per prima cosa veri- ficare che tale file non esista già e solo in tal caso provvedere a crearlo; una volta creato, altri attori desiderosi di acquisire il lock rileverebbero la presenza del file sopra citato e desisterebbero (o resterebbero in attesa che il file venga rimosso, a seconda dei casi). È di fondamentale importanza capire come l’operazione di verifica e creazione del file di lock debba necessariamente essere atomica per gestire le eventuali situazioni di concorrenza: non è accettabile alcuna situazio- 2 Basti pensare ai files di lock utilizzati da alcuni software di database o a quelli usati del popolare Microsoft Word per regolare l’accesso ai suoi documenti.
  26. 26. 22 3. SyncUtils ne di inconsistenza come quella riportata di seguito a titolo d’esempio: nell’ordine 1. l’attore A vuole acquisire il diritto di parola, pertanto tenta di segnalarlo, provando a creare il file di lock ; 2. in un istante di tempo ravvicinato ad (1) l’attore B vuole acquisire anch’esso il diritto di parola, pertanto tenta di creare a sua volta il file di lock ; 3. A verifica che il file di lock non esiste; 4. B verifica che il file di lock non esiste; 5. A crea fisicamente il file di lock ; 6. B—visto il punto 4—crede che il file di lock non esista e lo sovrascrive. Se il sistema di sincronia fosse prono ad un tale tipo di errore, due attori potrebbero ritenere di essere ognuno l’unico autorizzato ad accedere al file system in un dato istante di tempo, creando JobId non certamente univoci e sovrascrivendo potenzialmente l’uno i file dell’altro, portando così ad evoluzioni impredicibili nella comunicazione. Il problema della atomicità delle operazioni di verifica e creazione del file di lock viene risolto considerando che all’atto della creazione di un nuovo file, in ambiente Microsoft Windows si può indicare al sistema cosa fare nel caso in cui non sia possibile completare l’operazione (es: perché il file esiste già): sovrascrivere il file, accodare al contenuto o segnalare un’errore. Quando un attore desidera acquisire il lock, può semplicemente provare a creare il file, istruendo il sistema operativo a sollevare un’errore in caso di fallimento: se non si riceve alcun errore il lock è acquisito, altrimenti no. Al sistema operativo si delega la responsabilità della consistenza del suo file system; in caso di file system remoti, il sistema operativo che fornisce l’accesso remoto ad un file system da lui mantenuto si occupa di garantire la consistenza quando più processi tentino di creare lo stesso file [8].
  27. 27. Dettagli implementativi e tecnologie 23 Per impedire che altri processi come un antivirus o lo stesso uten- te possano inavvertitamente interferire col meccanismo di sincronia, il file viene mantenuto aperto in modalità esclusiva per tutto il tempo di detenzione del lock : in questo modo è impossibile per chiunque altro cancellarlo, rinominarlo o modificarlo. Nel caso il processo detentore del lock venga terminato, il file resta scritto sul file system, ma la modalità esclusiva viene a mancare: ogni eventuale altro processo in attesa di rilascio del lock non avrà speranze di acquisirlo fino al prossimo riavvio di GEC_Scan che causa la pulizia dei file residui di vecchie esecuzioni. 3.3.3 Identificativi di richieste e risposte Richieste e risposte vengono scambiate tramite dei file di estensione .IN e .OUT, diversi dal file di lock ma residenti nel suo stesso file system. Questi file hanno sempre il nome costituito da dodici cifre ed un trattino orizzontale, che rappresenta il JobId del lavoro in questione. Un JobId è stato definito come l’identificativo univoco all’interno di un file system, utilizzato per identificare univocamente richieste e ri- sposte. Esso viene generato a partire dalla data-ora della sua creazione; nell’implementazione C# è in realtà un oggetto che conserva come stato interno un timestamp, e permette di ricavare da questo una rappresenta- zione stringa nel formato yyyyMMdd-hhmmss dove “y” sono le quattro cifre corrispondenti all’anno, “M” quelle corrispondenti al mese, “d” al giorno, “h” all’ora, “m” ai minuti e “s” ai secondi. Per creare un JobId valido (avendo certezza della sua univocità per un determinato file system) ed associarlo ad una richiesta si effettua la seguente procedura: • si acquisisce il lock ; • si crea a partire da data e ora correnti la stringa yyyyMMdd-hhmmss; • si usa la stringa come nome file, considerando che l’estensione per una richiesta dev’essere .IN;
  28. 28. 24 3. SyncUtils • se tale nome file esiste già, si incrementa di uno il numero indi- viduato graficamente da yyyyMMddhhmmss e si torna al punto precedente (senza preoccuparsi del fatto che il numero corrisponda ancora ad una data-ora valida; es: 800419170261 non corrisponde ad una data-ora valida, ma è comunque valido come base per creare un JobId); • si crea il file; • si scrive una richiesta valida nel file; • si rilascia il lock. Una risposta ad una richiesta ha il suo stesso nome file ma con estensione .OUT; i file di richiesta e di risposta, contengono dati in formato che vedremo in seguito (vedi 3.3.6 nella pagina 28). Spesso una risposta fornisce anche un certo quantitativo di dati— nel nostro caso, ad esempio le immagini catturate: formato e ubicazione di questi dati sono indipendenti dal sistema di comunicazione, e deter- minati dai singoli plug in che gestiscono l’archiviazione (vedi 5.2 nella pagina 76), ma vengono comunque specificati in apposite sezioni nel file .OUT. 3.3.4 Protocollo Di seguito vengono riportate in pseudo codice alcune delle procedure che costituiscono il protocollo di comunicazione3 . Le procedure con prefisso GEC sono eseguite su iniziativa di GEC sulla macchina ove questo è in esecuzione, mentre quelle con prefisso SCAN si riferiscono al software di scansione GEC_Scan. FS sta per file system. L’indice i riferisce il prefisso al file system i-esimo. “Lavoro” o “Job” è il termine generico per indicare una richiesta, solitamente coincidente con la richiesta di inizio sessione di acquisizione. 3 Protocollo studiato dal prof. Alberto Bartoli con l’aiuto della documentazione prodotta dall’ing. Giorgio Davanzo; implementazione pratica in C#, sostituzione dell’active poll con sistemi di notifica e cura di dettagli tecnici pratici a cura di Giancarlo Todone.
  29. 29. Dettagli implementativi e tecnologie 25 Algorithm 3.1 Lock-CleanUp: Da eseguire all’avvio di GEC_Scan. 1: if EXISTS(lockfile-i) then 2: TIMEOUT = 10sec 3: BeginWait = now() 4: while now() BeginWait + TIMEOUT do 5: if NOT EXISTS(lockfile-i) then 6: break; 7: end if 8: end while 9: DELETE lockfile-i 10: end if Algorithm 3.2 GEC-RequestJob: Da eseguire per richiedere un lavoro. 1: GET lock-i 2: GET NEW JobId-i 3: RELEASE lock-i Algorithm 3.3 GEC-Abort: Da eseguire per annullare una richiesta di lavoro pendente su iniziativa di GEC, dato il suo JobId. 1: GET lock-i 2: DELETE request-file (filename = JobId.IN) in FS-i 3: RELEASE lock-i Algorithm 3.4 SCAN-CleanUp: Da eseguire all’avvio del programma di scansione; FS-i viene riportato nello stato iniziale. Per semplicità, non si cerca di recuperare eventuali lavori effettuati nella incarnazione precedente ma non completati. 1: EXEC Lock-CleanUp 2: GET lock-i 3: DELETE ALL response, data, request files (in quest’ordine) 4: RELEASE lock-i
  30. 30. 26 3. SyncUtils Algorithm 3.5 SCAN-Abort: Da eseguire per annullare (su iniziativa del software di acquisizione) una richiesta di lavoro pendente, dato il suo JobId. 1: GET lock-i 2: GENERATE EMPTY response-file (name = JobId.OUT) in FS-i 3: RELEASE lock-i Algorithm 3.6 SCAN-CompleteJob Da usarsi per segnalare il completamento (andato a buon fine o meno) di una richiesta di lavoro. 1: GET lock-i 2: if EXISTS(Input) then 3: CREATE data-files in FS-i 4: CREATE Output-file in FS-i 5: else 6: DISMISS data 7: end if 8: RELEASE lock-i In pratica: • Per effettuare una richiesta, il GEC deve: acquisire il lock; calcolare un JobId valido; scrivere un file {JobId}.IN contenente la richiesta nel corretto formato; rilasciare il lock; restare in attesa che venga scritto nella stessa posizione un file con lo stesso nome ma estensione .OUT. • Per recepire la richiesta ed effettuare una risposta, il GEC_Scan deve: restare in attesa finché sul file system predefinito non viene creato un file con nome corrispondente ad un JobId valido ed estensione .IN;
  31. 31. Dettagli implementativi e tecnologie 27 acquisire il lock; leggere il contenuto del file di richiesta; rilasciare il lock ; elaborare la richiesta; acquisire il lock ; scrivere il file .OUT; rilasciare il lock. Come si può notare dall’ultima esemplificazione, l’elaborazione viene fatta da GEC_Scan mentre il lock non è mantenuto, per permette- re che altre comunicazioni avvengano mentre è in atto un processo di archiviazione molto lungo. Inoltre è visibile che se GEC_Scan notasse la presenza del file di richiesta e tentasse di leggerlo prima che il GEC abbia finito di scriverlo, non vi riuscirebbe semplicemente perché prima dovrebbe acquisire il lock ancora detenuto dalla controparte. Un analogo ragionamento si può fare per il file di risposta. Se questo tipo di meccanismo da un lato permette una corretta evolu- zione delle dinamiche di comunicazione, dall’altro introduce anche delle situazioni in cui i processi comunicanti si intralciano a vicenda, spre- cando delle risorse; per questo motivo nell’implementazione reale degli algoritmi di comunicazione si sono previsti dei piccoli ritardi program- mabili, impostati poi a valori dedotti in modo sperimentale. Questi non alterano in alcun modo la logica della comunicazione, ma minimizzano i tempi di attesa attiva di ciascuna parte. 3.3.5 Problematiche delle notifiche Inizialmente si erano concepite ulteriori due procedure: SCAN-CheckForRequests con la quale il software di acquisizione controllava l’eventuale arrivo di nuove richieste; GEC-CheckJobCompleted che si occupava di controllare—dal lato di GEC—se una richiesta fatta in precedenza non fosse stata soddisfatta.
  32. 32. 28 3. SyncUtils Le due funzioni utilizzavano la tecnica dell’active poll, interrogando di continuo il file system sulla presenza o meno di determinati file. Consi- derato che questo caricava notevolmente i file system (e in minor parte anche la rete, in caso di sistema acceduto da remoto) si è provveduto a modificare il meccanismo in modo da utilizzare strumenti chiamati FileSystemWatcher [9]. Questi consistono fondamentalmente in hook 4 di sistema alle funzioni di base di accesso al disco, che sollevano un evento quando si presentano determinate condizioni, come il tentativo da parte di un programma di scrivere un nuovo file in una cartella. Purtroppo, come rilevato anche da una nutrita schiera di utenti5 , il codice che implementa questa tecnica a volte ha dei comportamenti inattesi quando eseguito in ambiente Microsoft Windows 2003 Server. All’epoca della prima stesura del programma non erano disponibili dei work around efficaci o soluzioni pubbliche: si è stati costretti a svi- luppare una soluzione alternativa poi segnalata sulla pagina ufficiale di bug report6 . La soluzione consiste nel sopperire ai comportamenti inattesi con de- gli snapshot della cartella ove avvengono gli scambi dei file: se tutto funziona come da specifiche Microsoft, l’esecuzione procede normalmen- te e le operazioni sul file system generano le notifiche attese; se invece qualcosa dovesse andare male, viene richiamato un gestore d’errore con del codice d’emergenza che confrontando il sotto albero della cartella al momento dell’errore con quello stimato durante le esecuzioni corrette, lo aggiorna e genera le notifiche di conseguenza. 3.3.6 Formati dei file di comunicazione Il formato interno dei file di comunicazione si basa su XML. Una richiesta tipo, contenuto di un file .IN si presenta come nel listato 3.1. 4 Tecnica di intercettazione e modifica al volo di dati comunicati tra funzioni di sistema; può essere “installato” in una catena di messaggi o in mezzo ad una serie di chiamate a routine [10, 13]. 5 https://connect.microsoft.com/VisualStudio/feedback/ ViewFeedback.aspx?FeedbackID=337917 6 https://connect.microsoft.com/VisualStudio/feedback/ Workaround.aspx?FeedbackID=337917
  33. 33. Dettagli implementativi e tecnologie 29 Listing 3.1: Esempio di XML generato da SyncUtils per effettuare una richiesta. 1 Request 2 ActionRequest xmlns:xsi=http://www.w3.org/2001/ XMLSchema-instance xmlns:xsd=http://www.w3.org /2001/XMLSchema xsi:type=SaveToFileActionRequest ARQID=0 3 Performer name=SaveToFileActionPerformer / 4 RequiredFileFormatpng/RequiredFileFormat 5 Pathc:lockpath/Path 6 /ActionRequest 7 AdditionalData xmlns:xsi=http://www.w3.org/2001/ XMLSchema-instance xmlns:xsd=http://www.w3.org /2001/XMLSchema 8 OwnerID64/OwnerID 9 CustomerIDmyCustomerID/CustomerID 10 /AdditionalData 11 Timestamp2009-02-25T16:59:48.375+01:00/Timestamp 12 /Request Il codice XML viene generato semi automaticamente per serializza- zione di oggetti (vedi 3.3.7 nella pagina 32), quindi in questo frangente, con un nome ci si potrà riferire indistintamente al tag o alla classe che lo ha generato. In 3.2 nella pagina 16 parlando della struttura del sistema di comu- nicazione, è stato detto che Request e Response reali contengono solo tipi specializzati di ActionRequest, ActionResponse ecc. . . Nel listato di esempio è immediato però notare che i nomi dei tag di alcune entità derivabili sono dati da quelli delle loro classi base; questo fa parte del meccanismo di serializzazione: il nome della classe specializzata è contenuto in questi casi dall’attributo xsi:type. Non si fa affidamen- to a xsi:type per la corretta serializzazione del campo Performer che contiene semplicemente il nome della classe preposta a gestire la ActionRequest che lo contiene. In 3.2 nella pagina seguente si può osservare un esempio di risposta, contenuto nel file .OUT corrispondente ad un file .IN di richiesta.
  34. 34. 30 3. SyncUtils Listing 3.2: Esempio di XML generato da SyncUtils per effettuare una risposta. 1 Response xmlns:xsi=http://www.w3.org/2001/XMLSchema- instance xmlns:xsd=http://www.w3.org/2001/XMLSchema 2 Documents 3 Document GID=0 4 Pages 5 Page PID=0 / 6 Page PID=1 / 7 Page PID=2 / 8 /Pages 9 ActionResponses 10 ActionResponse xsi:type= SaveToFileActionResponse ARSID=0 Request= 0 11 Errors / 12 Pages 13 ResponsePage xsi:type=FSPage Page=0 Format=png FileName=fileName1 / 14 ResponsePage xsi:type=FSPage Page=1 Format=png FileName=fileName2 / 15 ResponsePage xsi:type=FSPage Page=2 Format=png FileName=fileName3 / 16 /Pages 17 Pathc:lockpath/Path 18 /ActionResponse 19 /ActionResponses 20 /Document 21 /Documents 22 Errors 23 Error IsCrytical=true EID=0 24 Test error message 2 ! 25 /Error 26 /Errors 27 Timestamp2009-02-27T23:14:52.640625+01:00/Timestamp 28 /Response Si possono notare gli attributi PID, GID, EID ecc. . . che fungono
  35. 35. Dettagli implementativi e tecnologie 31 da identificatori univoci per l’entità cui appartengono all’interno del loro contenitore; in figura 3.2 nella pagina 17 le frecce indicano che l’oggetto da cui partono conserva un identificativo dell’oggetto punta- to, cui si riferiscono logicamente, come una ActionResponse indica l’ActionRequest da cui è originata. Il meccanismo di distribuzione degli identificativi è tale che un identificativo sia univoco tra quelli degli oggetti contenuti nello stes- so contenitore (ad esempio: non ci sono ripetizioni tra gli id del- le ActionResponse in un medesimo Document, ma due id di ActionResponse in due Document distinti possono essere uguali poiché non è comunque possibile equivocare tra loro). Dal punto di vista dell’implementazione, ogni oggetto che può funge- re da contenitore per altri oggetti mantiene internamente un oggetto di tipo IdFactory per la generazione consistente e la distribuzio- ne degli identificativi; tutti gli oggetti che possono venire identificati per qualche motivo implementano l’interfaccia IHasId; tutti gli oggetti che possono fare riferimento ad un altro oggetto implementante IHasId implementano a loro volta l’interfaccia IIdPointer. È forse doveroso ribadire che normalmente per individuare precisa- mente un oggetto manterremmo semplicemente una managed reference a quest’ultimo; ma questo tipo di riferimento, nella situazione proposta è di difficile espressione durante la serializzazione XML. Listing 3.3: Riassunto dei meccanismi di distribuzione consistente degli identificativi. 1 public interface IHasId 2 { 3 int Id { get; set; } 4 } 5 6 public interface IIdPointer 7 { 8 int PointedId { get; set; } 9 void PointTo(IHasId item); 10 } 11 12 public class IdFactory 13 {
  36. 36. 32 3. SyncUtils 14 int _count = 0; 15 ... 16 public virtual IHasId SetID(IHasId item) 17 { 18 item.Id = _count++; 19 return item; 20 } 21 ... 22 } 23 24 public class IdFactoryT : IdFactory where T : IHasId, new() 25 { 26 ... 27 public override IHasId SetID(IHasId item) 28 { 29 ... 30 return base.SetID(item); 31 } 32 } 3.3.7 Serializzazione XML Le tecniche di serializzazione XML in generale, e quelle utilizzate secon- do le usanze del framework dotNet in particolare, sono estremamente note in letteratura [12], ma è bene soffermarsi su certi loro aspetti per gli interessanti risvolti scaturiti durante lo sviluppo di alcune parti del software di interscambio dati. La serializzabilità di un tipo in ambito dotNet è cosa diversa dalla sua serializzabilità XML: ai nostri scopi tutti i tipi primitivi sono XM- L-serializzabili e in aggiunta—grazie all’uso della reflection—anche molti tipi complessi non espressamente pensati in ottica di serializzazione XML sono comunque XML-serializzabili. Nel package System.Xml.Serialization si trovano gli strumen- ti per effettuare serializzazione e deserializzazione di oggetti secondo due modalità che potremmo definire “esplicita” ed “implicita”:
  37. 37. Dettagli implementativi e tecnologie 33 • nella modalità esplicita, gli oggetti candidati alla serializ- zazione devono implementare esplicitamente l’interfaccia IXmlSerializable, che prescrive l’implementazione di tre metodi per la serializzazione, la deserializzazione e la definizione di uno schema; • nella modalità implicita, il framework ispeziona tramite reflection le classi degli oggetti da serializzare e considerando solo campi e proprietà pubbliche genera al volo un oggetto serializzatore adatto. Nella maggior parte dei casi la modalità implicita è più che sufficiente, se si considera che è possibile istruire in certa misura il serializzatore su alcuni dettagli come nomi dei tag, tipo dei nodi ecc. . . mentre con la mo- dalità esplicita—che pur permette di risolvere problemi più complessi—è necessario scrivere molto codice, introducendo problemi di leggibilità e manutenibilità del sorgente. Solitamente si fa uso di una sola tecnica per volta, ma accade anche che le due vengano combinate, ad esempio quando si serializza un ogget- to implicitamente serializzabile che però serba in alcuni dei suoi campi oggetti esplicitamente serializzabili; ciò che accade è esemplificato nel seguente algoritmo: • se l’oggetto da serializzare è un tipo primitivo, allora è ben conosciuto: si richiama una procedura standard per la sua serializzazione e si termina la procedura; • se l’oggetto da serializzare implementa IXmlSerializable, al- lora si chiama il metodo IXmlSerializable.WriteXml() e si termina la procedura; • se l’oggetto non appartiene alle precedenti due categorie ma è comunque XML-serializzabile, allora si itera l’algoritmo su ogni campo. Analogamente per la deserializzazione. È ovvio che nel caso di un og- getto complesso con campi complessi tutti implicitamente serializzabili,
  38. 38. 34 3. SyncUtils l’algoritmo itera finché non è stato analizzato l’intero albero7 ; è altresì visibile che qualora venga incontrato un oggetto IXmlSerializable, i suoi metodi WriteXml/ReadXml si occuperanno della sua intera serializzazione/deserializzazione, fermando la ricorsione dell’algoritmo summenzionato. Nello sviluppo del progetto si sono affrontati dei casi in cui ciò rappre- senta un problema: gli oggetti che gestiscono richieste e risposte utilizza- no meccanismi di serializzazione complessi, poichè gli oggetti scambiati durante una comunicazione non sempre sono ben conosciuti da entram- bi gli interlocutori; quindi questi oggetti implementano esplicitamente i meccanismi con IXmlSerializable. Nonostante ciò, per semplificare lo sviluppo futuro di ulteriori oggetti contenuti in richieste e risposte, si desidera che tali oggetti non debbano necessariamente implementare essi stessi le loro procedure di serializzazione in maniera esplicita. È stato quindi adottato un espediente: nel codice di serializzazione personalizzato di Request e Response, ogni loro campo viene serializ- zato/deserializzato istanziando di volta in volta un nuovo serializzatore, che inizia nuovamente per ogni loro campo l’algoritmo descritto in pre- cedenza; i flussi di codice XML prodotto nelle singole serializzazioni di questi oggetti vengono poi fusi col flusso principale dell’oggetto padre a posteriori (analogamente, durante la deserializzazione avviene l’estrazio- ne di porzioni di XML dal flusso principale che generano oggetti reinseriti negli appositi campi dell’oggetto padre a posteriori). Tutti i tipi conosciuti da un’esecuzione della libreria di comunicazio- ne, vengono mantenuti in un registro statico e pubblico, accessibile da ogni serializzatore; l’insieme di queste tecniche permette la serializzazio- ne/deserializzazione di tipi non noti a compile time, e la corretta gestio- ne della loro ereditarietà, mantenendo comunque semplice lo sviluppo di funzionalità aggiuntive. 7 Per semplicità e compattezza vengono taciute le problematiche di visita come ad esempio riferimenti incrociati e similari, pur esistenti ed affrontati dall’implementazione reale dell’algoritmo.
  39. 39. Dettagli implementativi e tecnologie 35 3.3.8 COM COM è acronimo di Component Object Model, un’architettura che permette l’interfaccia di componenti software di varie parti senza che queste siano ricompilate in un progetto, al fine di promuoverne l’interoperabilità. Esso non è dipendente da un particolare linguaggio—ogni linguaggio che sia in grado di chiamare funzioni tramite puntatori può accedere alle sue funzionalità—e si basa sui concetti di componente ed interfaccia. Tali componenti ed interfacce sono conservati in delle DLL struttu- rate secondo un metodo prestabilito, e riferiti durante il loro utilizzo secondo un peculiare meccanismo di doppia indirezione: si mantiene il riferimento ad un componente tramite l’indice di una tabella—chiamata “vtable”—che a sua volta conserva un’indirizzo reale alla struttura dati desiderata: in questo modo le vtable possono essere condivise da più istanze di un oggetto riducendo l’utilizzo di memoria. Un componente COM somiglia in struttura a ciò che è una classe per la programmazione ad oggetti. In una gerarchia di classi, in qualsiasi contesto di programmazione esiste un ancestor, ovvero il modello di un’entità di base con un insieme minimo di caratteristiche e funzionalità di base che qualsiasi altro oggetto deve possedere; in ambito COM, si dice che tale oggetto implementa almeno l’interfaccia IUnknown. Listing 3.4: Interfaccia IUnknown come appare in C++. 1 class IUnknown 2 { 3 virtual HRESULT QueryInterface(IID iid, void** ppvObj) = 0; 4 virtual ULONG AddRef() = 0; 5 virtual ULONG Release() = 0; 6 } Questa interfaccia prescrive l’implementazione di tre metodi:
  40. 40. 36 3. SyncUtils QueryInterface permette di interrogare il componente imple- mentante circa il supporto o meno di un’altra specifica interfaccia; AddRef viene chiamato per aumentare il conteggio interno degli uti- lizzatori (insieme a Release implementa un primitivo Garbage Collector); Release decrementa il conteggio interno degli utilizzatori e libera la memoria quando questo raggiunge lo 0. Un componente COM può supportare un numero qualsiasi di interfacce a partire da un minimo di una (IUnknown); le interfacce possono essere prese dal programmatore tra alcune predefinite, derivate da esse o create ex novo. Per permettere la risoluzione degli identificativi univoci che contrad- distinguono componenti ed interfacce COM a partire da nomi, tali ele- menti devono necessariamente essere registrati, cioè iscritti ad elenchi siti in determinate aree del registro di configurazione di Windows8 . La tecnologia dotNet, con il suo proprio concetto di riusabilità sta soppiantando di fatto il Component Object Model, nonostante que- st’ultimo sia stato forse una delle tecnologie più usate dal 1993 ad oggi9 . Il passaggio da una tecnologia all’altra viene reso più facile dalla prevista possibilità di interazione tra le due: questa opportunità si espli- cita con il Runtime Callable Wrapper (RCW) necessario per eseguire una chiamata a un server COM da un client dotNet, e il COM Callable Wrapper (CCW) per eseguire viceversa una chiamata a un server dotNet da client COM10 . Come suggerito dai nomi, queste due entità sono del 8 In realtà COM fu portato anche su sistemi operativi diversi da Windows e addi- rittura su macchine diverse dai PC compatibili; in questi sistemi la risoluzione degli identificativi avviene in modo analogo ma implementativamente diverso; l’uso più esteso di COM rimane quello su piattaforme Windows, dal 3.x fino alle più moderne XP, Vista e Seven. 9 Nata nel 1993, questa tecnologia è stata menzionata con enfasi da Microsoft solo a partire dal 1997. 10 Chiamiamo “client COM” una porzione di un programma in grado di utilizzare un servizio esposto da un oggetto COM; chiamiamo altresì “server COM” il componente che espone tale funzionalità.
  41. 41. Dettagli implementativi e tecnologie 37 codice di contorno aggiunto automaticamente ai componenti di una del- le due metodologie di sviluppo per essere interpretati ed utilizzati anche dalla controparte tecnologica. Component RCW Consumer Unmanaged Managed Consumer CCW Class Figura 3.3: Schema di funzionamento di RCW e CCW; nella prima riga un componente dotNet richiama funzionalità da un provider COM; nella seconda, del codice capace di richiamare funzionalità COM chiama codice dotNet tramite il CCW. Nonostante ogni CCW sia generato automaticamente dal runtime dotNet, le classi da esporre come componenti COM devono venire ade- guatamente preparate; l’ambiente integrato di sviluppo Visual Studio 2008 offre degli automatismi per assolvere a questo compito, ma resta preoccupazione del programmatore decorare le classi dotNet con attributi atti ad istruire il runtime nella creazione dei CCW ad esse dedicati. Fondamentali ComVisible che abilita il processo di wrapping e ProgId che assegna il nome al componente. Eventuali altri attributi da applicare possono essere Guid, che specifica un identificativo univoco altrimenti assegnato automaticamente e DispId che specifica in maniera esplicita l’ordine in cui i metodi devono comparire in un’interfaccia11 . 11 Per la corretta compilazione del codice, se almeno un metodo di una classe è stato decorato con DispId, allora lo devono essere tutti all’interno della stessa classe.
  42. 42. 38 3. SyncUtils Listing 3.5: Esempio della decorazione minima di un componente da esporre tramite COM. 1 [InterfaceTypeAttribute(ComInterfaceType. InterfaceIsIDispatch)] 2 public interface _JobId 3 { 4 string ToString(); 5 bool Equals(object value); 6 void Increment(); 7 JobId Clone(); 8 } 9 10 [ClassInterface(ClassInterfaceType.None)] 11 [ProgId(SyncUtils.JobID)] 12 [ComVisible(true)] 13 public class JobId : _JobId 14 { 15 ... 16 } Una particolare menzione meritano la gestione degli eventi e quella degli errori; mentre i secondi sono propagati automaticamente dal siste- ma semplicemente assegnando un codice d’errore ad ogni eccezione non gestita, l’utilizzo dei primi richiede del codice aggiuntivo. Proprietà di un’interfaccia C# come potrebbe essere 1 event JobCompletedDelegate OnJobCompleted; vengono viste in realtà dai client COM come una coppia di metodi per l’aggiunta e la rimozione di gestori d’evento 1 AddJobCompletedDelegate(); 2 RemoveJobCompleteDelegate(): ma per permettere ad un COM client di venire notificato da un componente, è necessario assegnare esplicitamente a quest’ultimo an- che un’interfaccia in cui si specifica il metodo da chiamare al verificarsi dell’evento; del tipo
  43. 43. Dettagli implementativi e tecnologie 39 1 [InterfaceTypeAttribute(ComInterfaceType. InterfaceIsIDispatch)] 2 public interface UserEvents 3 { 4 void OnJobCompleted(JobId job, Response response); 5 ... 6 } Dal punto di vista dell’utilizzo con Visual Basic 6, l’utilizzo di un oggetto COM richiede un file che ne specifichi le funzioni presenti: tale file—di estensione .tlb—viene chiamato “type library”, ed è generato automaticamente all’atto della registrazione di un componente. Impor- tando la type library, è poi possibile cominciare ad usare qualsiasi dei tipi ivi definiti, curandosi di dichiarare con la clausola WithEvents quelli dei quali si voglia usare la capacità di sollevare eventi. Nel progetto del sistema di archiviazione proposto, le classi ad essere predisposte per l’utilizzo come componenti COM sono essenzialmente quelle riguardanti la libreria della comunicazione, e in maggior dettaglio quelle che permettono a GEC di richiedere un servizio a GEC_Scan: ClientSideFileSync; Request; Response; ActionRequest; ActionResponse; Document; DocInfo; Page; ResponsePage; Error
  44. 44. 40 3. SyncUtils e classi da queste derivate. Lo sviluppatore che intendesse creare ulteriori plug in aggiuntivi dovrà curarsi che le sue classi siano accessibili a client COM per permetterne l’uso da parte di GEC. 3.4 Installazione e preparazione dell’ambiente di esecuzione Il software in tutte le sue parti è in fase di test, e non viene quindi ancora distribuito al di fuori del contesto di sviluppo. Per questo motivo non è fornito di un programma di installazione e di istruzioni user friendly, ma solo di note tecniche, la maggior parte delle quali messe insieme durante la soluzione di reali problematiche di set up, o collezione di alcuni brani rilevanti dalla documentazione e dai commenti al codice sorgente. I tre tipi di software prodotti eseguono in due ambienti eventualmente coincidenti: • il calcolatore che esegue GEC • il personal computer dove viene eseguito il software di acquisizione e i suoi plug in Per quanto riguarda il lato controllore, devono essere distribuiti assieme a GEC tutti gli assembly inerenti la libreria di comunicazione. Le seguenti DLL contenenti codice dotNet racchiuso in oggetti COM vanno copiate in una cartella apposita su un volume non rimovibile del PC e registrate nell’ordine: • CommonUtils.dll • SyncUtils.dll • SerializationSetupHelper.dll • BasicPlugins.dll • ClientSync.dll che in buona parte dipendono da (e quindi richiedono anche) SimpleLogger.dll Per la registrazione, è possibile utilizzare il comando
  45. 45. Installazione e preparazione dell’ambiente di esecuzione 41 1 RegAsm.exe nomeDll residente nella cartella %WINDIR%Microsoft.NETFrameworkv2.X Come si può notare, la cartella è parte integrante del framework dotNet 2.x (dove “x” sta per qualsiasi numero), palesando che l’installazione del runtime dotNet 2.0 o superiore è un prerequisito. Da osservare anche il fatto che gli assembly preparati per essere utiliz- zati come oggetti COM hanno bisogno di un trattamento particolare, uti- lizzando per la registrazione l’apposito regasm.exe al posto dell’usuale regsvr32.exe Molte di queste librerie sono utilizzate anche dal lato del software di acquisizione: anche se questo dovesse essere installato sulla stessa macchina di GEC, le librerie non possono essere condivise. Andranno quindi replicate nella cartella dedicata solo al programma di scansione.
  46. 46. 42 3. SyncUtils
  47. 47. Capitolo 4 GEC_Scan 4.1 Requisiti e progetto dell’interfaccia utente Il software di acquisizione GEC_Scan dev’essere funzionalmente inte- grato con GEC. L’utente, una volta installato il sistema, non deve avere coscienza che GEC_Scan è un programma diverso da GEC ma deve essere portato a considerarlo come una sua estensione: per ottenere que- sto risultato GEC_Scan deve essere eseguito all’avvio della macchina su cui è installato e rimanere nascosto finchè non si presenti un determinato evento (come l’arrivo di una comunicazione da GEC) nel qual caso dovrà essere mostrata una schermata adatta a gestire l’evento. In questo modo, la finestra di GEC_Scan si comporterà come se fos- se un form dell’applicazione principale, lasciando trasparente all’utente tutta la gestione delle comunicazioni tra un software e l’altro. GEC_Scan deve utilizzare SyncUtils o essere compatibile con il suo metodo di comunicazione a file system condiviso: deve quindi avere ac- cesso in lettura e scrittura alla porzione del file system sul suo elaboratore che viene acceduta da GEC tramite SyncUtils. GEC_Scan deve poter accettare da GEC un numero qualsiasi di richieste di inizio sessione di acquisizione a prescindere dal suo stato di occupazione: se arrivano ulteriori richieste mentre l’utente sta operando il programma per soddisfarne una, tali richieste vanno inserite in una 43
  48. 48. 44 4. GEC_Scan coda di tipo First In First Out, e vanno presentate all’utente in ordine una ogni volta che la precedente sia terminata. L’utente deve essere posto in grado di valutare la lunghezza della coda e di annullare una o tutte le richieste senza interrompere il suo lavoro corrente. A tale scopo deve essere presente un form separato da quello principale che permette di osservare in tempo reale l’occupazione della coda. GEC_Scan deve poter comunicare con il maggior numero possibile di periferiche di acquisizione come scanner, fotocamere e basi di dati; tale connettività deve però essere assolutamente trasparente, cioè: il com- portamento e l’apparenza grafica del programma devono essere sempre uguali e garantire un’esperienza di utilizzo consistente qualsiasi sia la sorgente di dati scelta. Le immagini acquisite singolarmente o in gruppi, devono essere presentate tramite piccole anteprime che permettano quantomeno di identificare in linea di massima ogni documento. Non ci deve essere un limite—se non quello fisico della macchina di esecuzione—al numero di immagini acquisibili e gestibili: allo sco- po di facilitare la gestione delle immagini (operazioni di ispezione, se- lezione, riordino, rotazione) il programma deve essere provvisto di un visualizzatore integrato, che permetta di ingrandire le piccole anteprime e presentare le immagini a più alta risoluzione a vari livelli di zoom. 4.1.1 Interfaccia grafica e usabilità Normalmente il programma di acquisizione documenti viene eseguito al- l’avvio del sistema dell’utente, ma la maggior parte delle sue funziona- lità è preclusa finché GEC—a seguito di un’operazione dell’utente—non inizia una sessione; per l’utente è tuttavia sempre possibile accedere tra- mite icona nella barra dell’orologio ad un menu di opzioni che permette di impostare: • il dispositivo da utilizzare tra una lista di scanner, fotocamere ed altre sorgenti TWAIN disponibili sul sistema;
  49. 49. Requisiti e progetto dell’interfaccia utente 45 Figura 4.1: Finestra di opzioni del programma di acquisizione. • la risoluzione (impostata alla prima esecuzione sulla risoluzio- ne disponibile più vicina—possibilmente per eccesso—a 300 dpi, risoluzione richiesta dalla maggior parte dei software OCR); • modalità di colore (impostata alla prima esecuzione sulla modalità più semplice che si avvicini a RGB); • orientamento pagine (impostato alla prima esecuzione a 0º); • utilizzo dell’alimentatore automatico fogli (se disponibile, imposta- to a vero alla prima esecuzione); • utilizzo della scansione automatica fronte e retro (inizialmente falso); • utilizzo dell’eliminazione automatica pagine vuote (inizialmente falso); • utilizzo della rotazione automatica pagine (inizialmente falso);
  50. 50. 46 4. GEC_Scan • utilizzo del rilevamento automatico delle dimensioni di una pagina (se disponibile inizialmente vero); Ogni controllo di impostazione risulta operabile se pertinente, e non presente o disegnato in grigio se non disponibile o non applicabile. Ogni impostazione si riferisce al dispositivo correntemente seleziona- to: scegliere un’altra periferica causerà l’adattamento dei parametri alle capacità della nuova sorgente scelta. Alla chiusura della finestra delle preferenze, queste vengono rese ufficiali e salvate su disco. Figura 4.2: Schermata principale del programma di acquisizione. Quando l’utente effettua in GEC un’operazione che causa l’inizio di una sessione di acquisizione, la schermata principale del programma di scansione compare in primo piano. Tramite il tasto “Acquisisci” si inizia la scansione dalla periferica sele- zionata di una o più pagine dipendentemente dalle preferenze impostate: eventuali operazioni lunghe comporteranno la comparsa di un indicato- re di avanzamento che consente anche di interrompere le operazioni in corso. Ad esempio, un’operazione di acquisizione molto lunga potrebbe pre- sentarsi nel caso in cui si sia scelto di scansionare molti documenti con
  51. 51. Requisiti e progetto dell’interfaccia utente 47 un trascinatore automatico, oppure nel caso si sia scelto di utilizzare una risoluzione molto alta. Una volta raccolte delle immagini, queste compaiono sotto forma di icone sullo sfondo grigio della finestra principale: passandoci sopra con il puntatore esse si ingrandiscono per permettere di comprendere meglio di che pagina si tratta e per consentire all’operatore di capire qual è il foglio correntemente puntato. Aumentando le dimensioni della finestra, aumentano anche quelle delle icone delle pagine. Facendo doppio click su un’immagine, questa viene mostrata in una finestra di anteprima, nella quale è possibile effettuare zoom (operando la rotella del mouse o i tasti + e -) sulle sue varie parti a fini di ispezione. Tenendo premuto il tasto sinistro del mouse e trascinando, l’imma- gine puntata viene rimossa dalla sua sede per consentire di posizionarla in altra locazione: rilasciando il tasto sinistro, essa verrà inserita su- bito prima dell’immagine correntemente sotto il puntatore (locazione evidenziata da una barra nera sfumata). Una barra di posizionamento compare al di sotto delle immagi- ni quando queste sono troppe per essere contenute in una sola scher- mata: sia quando si scorrono semplicemente le immagini, sia duran- te le operazioni di trascinamento, avvicinandosi al bordo sinistro o de- stro il programma effettua automaticamente una carrellata—tanto più velocemente quanto più si è vicini al bordo. Tenendo premuto il tasto sinistro del mouse sull’area recante la di- citura “inserisci separatore” e trascinando, viene creato un elemento se- paratore (delle sembianze di una barra nera verticale) che è possibile rilasciare tra due immagini secondo le modalità già viste: anche una volta rilasciato un separatore, è sempre possibile riprenderlo e spostarlo come una immagine qualsiasi. Verrà considerato “documento” o “gruppo” l’insieme delle pagine con- tenute fra due separatori (o tra un separatore e l’inizio/fine della lista): il programma può essere forzato da GEC a richiedere un numero mini- mo e un numero massimo di gruppi di pagine: è possibile sapere quali sono i vincoli lasciando il puntatore sull’area di inserzione separatore e aspettando la comparsa di un fumetto contenente tali informazioni. Facendo click destro su un’immagine o un separatore, appare un menu contestuale con diverse opzioni auto esplicative:
  52. 52. 48 4. GEC_Scan • ruota in senso orario; • ruota in senso antiorario; • elimina. La pressione del tasto “cancella immagini” causa la cancellazione di tutte le immagini acquisite. Una volta catturate, riordinate e divise le pagine è possibile annullare tutto il lavoro o proseguire con l’archiviazione dei dati; la differenza tra “cancella immagini” e “scarta” consiste proprio nel fatto che il primo co- mando lascia la finestra aperta per effettuare ulteriori operazioni, mentre il secondo chiude e manda contestualmente a GEC un messaggio di er- rore comunicandogli che non è stato possibile completare correttamente il lavoro per annullamento da parte dell’utente. Se nel frattempo erano pervenute altre richieste di inizio sessione (es: l’utente ha effettuato altre operazioni su GEC che hanno originato altre richieste), il programma lo palesa restando in attesa di istruzioni, altrimenti torna nel suo stato quiescente. In ogni momento è possibile controllare e gestire lo stato della coda di richieste tramite l’apposita finestra, richiamabile dalla tray icon. Figura 4.3: Finestra di gestione della coda in caso di richieste multiple.
  53. 53. Composizione di GEC_Scan 49 Infine, chiudendo semplicemente la finestra principale (con la classi- ca “x” in alto a destra) o tramite il tasto “Nascondi” senza scegliere di memorizzare o scartare il materiale raccolto, si sospende la sessione di lavoro nascondendo la finestra, recuperabile (senza perdere alcun dato) tramite icona nella barra dell’orologio. 4.2 Composizione di GEC_Scan Plug in Servizi Plug in manager esterni Plug in codice principale SyncUtils File System GEC dotNetTwain TWAIN Periferiche VisualSlideShow WinForms e interfaccia Utente GDI grafica GEC_Scan Figura 4.4: Composizione di GEC_Scan e sue relazioni con tecnologie ed altre parti del progetto. In figura 4.4, si può osservare l’architettura di GEC_Scan e le sue

×