GRIMD Queue Management - Digital Forensics @ UniSa

Transcript

GRIMD Queue Management - Digital Forensics @ UniSa
Università degli Studi di Salerno
Facoltà di Scienze Matematiche Fisiche e Naturali
Corso di Laurea Magistrale in Informatica
Tesina per il corso di
Sistemi Operativi II
GRIMD Queue Management
Gestione code utenti tramite interfaccia web e refactoring
architetturale di GRIMD
Prof.
Giuseppe Cattaneo
Gruppo
Antonio Balsamo
Salvatore Cascone
Anno Accademico 2011-2012
Indice
1 Introduzione
1.1 Grid Computing .
1.2 Motivazioni . . .
1.3 Caso di studio . .
1.3.1 Obiettivi .
1.4 Stato dell’arte . .
1.5 Risultati . . . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
2 Le tecnologie
2.1 .NET Framework . . . . . . . . . . . . . . .
2.1.1 Entity Framework . . . . . . . . . . .
2.1.2 Membership . . . . . . . . . . . . . .
2.1.3 Windows Communication Foundation
2.2 SQL Server . . . . . . . . . . . . . . . . . .
2.3 Windows Server 2003 . . . . . . . . . . . . .
2.3.1 Internet Information Services . . . .
2.4 Virtual Private Network . . . . . . . . . . .
3 Refactoring architettura
3.1 GRIMD 1.1 . . . . . .
3.2 Modifiche apportate .
3.2.1 Sicurezza . . .
3.3 Requisiti minimi . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
i
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
1
1
1
3
3
4
5
.
.
.
.
.
.
.
.
6
6
8
11
12
13
14
14
15
.
.
.
.
17
17
18
19
20
INDICE
ii
4 Struttura del sistema
4.1 Gestione utenti . . . . . . . . . . . . .
4.2 Base dei dati . . . . . . . . . . . . . .
4.3 Servizio di gestione Master . . . . . . .
4.3.1 Modulo di identificazione Slave
4.3.2 Modulo di gestione coda . . . .
4.4 Modulo di controllo di stato del Master
4.5 Altre modifiche . . . . . . . . . . . . .
4.5.1 Master . . . . . . . . . . . . . .
4.5.2 FRED e GDUMP . . . . . . . .
4.5.3 Slave . . . . . . . . . . . . . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
22
22
23
25
25
27
29
30
30
30
31
Conclusioni
32
Bibliografia
33
A Appendice
A.1 Servizio di controllo stato Master
A.1.1 IMasterStatus . . . . . . .
A.1.2 MasterStatus . . . . . . .
A.2 Servizio di coda . . . . . . . . . .
A.2.1 IMasterQueue . . . . . . .
A.2.2 MasterQueue . . . . . . .
A.2.3 QueueHandler . . . . . . .
A.3 Servizio identificazione slave . . .
A.3.1 IVPNIDResolver . . . . .
A.3.2 VPNIDResolver . . . . . .
34
34
34
34
37
37
37
41
48
48
49
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
Capitolo 1
Introduzione
1.1
Grid Computing
Al giorno d’oggi i sistemi di Grid Computing (Griglia Computazionale)
rappresentano una diffusa infrastruttura di calcolo distribuito, utilizzati per
l’elaborazione di grandi quantità di dati mediante l’uso di un grande numero
di risorse.
Il termine “griglia” fu coniato nella prima metà degli anni Novanta. Il
principale problema alla base del concetto di griglia è la condivisione coordinata di risorse all’interno di un’organizzazione virtuale. La condivisione
non è limitata solo allo scambio dei file, ma si estende all’accesso diretto a
computer, a software ed in generale a tutto l’hardware necessario alla risoluzione di un problema scientifico, ingegneristico o industriale. Gli individui
e le istituzioni, che mettono a disposizione della griglia le loro risorse per la
medesima finalità, fanno parte della stessa organizzazione.
1.2
Motivazioni
Caratteristica comune dei progetti di grid computing è la necessità di disporre un ambiente di calcolo data-intensive, all’interno del quale le applicazioni
1
CAPITOLO 1. INTRODUZIONE
2
hanno il bisogno di accedere a grandi quantità di dati geograficamente distribuiti in maniera veloce ed affidabile. Compito della griglia è far operare tali
applicazioni nel miglior modo possibile. È facile osservare che nessun computer attualmente in commercio sarebbe in grado, da solo, di elaborare moli
di dati abbastanza grandi in tempi ragionevoli. Tuttavia la condivisione di
risorse quali CPU e dischi opportunamente coordinati può dare l’impressione all’utente di accedere ad un supercomputer virtuale, con una incredibile
potenza computazionale e capacità di memorizzazione in grado di sopportare
grandi carichi di lavoro.
Tutta l’architettura di una griglia, vista come un unico supercomputer
virtuale, nasconde una grande complessità interna. Per esempio è importante notare l’esigenza di progettare e realizzare uno scheduler di risorse, che
rappresenta uno dei componenti critici del sistema di gestione delle risorse.
Questo ha il compito di assegnare le risorse ai job, in modo da soddisfare le esigenze delle applicazioni e del sistema. Le risorse di cui esso deve
tenere traccia e gestire includono sistemi di calcolo e sistemi di immagazzinamento dati. Lo scheduling è un campo tradizionale dell’informatica, ma
nonostante siano state studiate molte tecniche per numerose tipologie di sistemi, le caratteristiche tipiche delle griglie di dati rendono molti di questi
approcci inadeguati. Infatti, mentre nei sistemi tradizionali le risorse e i job
sono sotto il diretto controllo dello scheduler, le risorse delle griglie invece
sono geograficamente distribuite. Queste inoltre sono di natura eterogenea
e appartengono a diversi individui o organizzazioni, ciascuna con le proprie
politiche di scheduling, costi d’accesso, carichi di lavoro e disponibilità di
risorse che varia dinamicamente nel tempo. La mancanza di un controllo
centralizzato, insieme alla presenza di utenti che generano job, molto diversi
l’uno dall’altro, rendono lo scheduling più complicato rispetto a quello dei
sistemi di calcolo tradizionali.
CAPITOLO 1. INTRODUZIONE
1.3
3
Caso di studio
Nel corso del documento si discuterà delle modifiche apportate a GRIMD
(Grid for Molecular Dynamics), un sistema concepito per effettuare calcolo
distribuito tramite l’utilizzo di YASARA (Yet Another Scientific Artificial
Reality Application) su una griglia di computer, sfruttando la loro potenza
di calcolo nei periodi di inutilizzo. L’architettura prevede la presenza di
una macchina master che coordina il lavoro di un numero indeterminato di
slave.
Attualmente il sistema è installato su alcune delle macchine presenti nel
laboratorio Turing della facoltà di Informatica, nell’aula 33 e nel laboratorio
di bioinformatica del dipartimento di scienze farmaceutiche e biomediche
dell’Università degli Studi di Salerno.
1.3.1
Obiettivi
L’intento è quello di estendere le capacità di GRIMD ad un ambito più ampio,
accademico o aziendale, mantenendo la versione precedente e sviluppando
una versione web che consenta l’utilizzo di computer appartenenti a diverse subnet, scavalcando i problemi dovuti alla presenza di NAT (Network
Address Translation) e che permetta l’utilizzo a più utenti contemporaneamente. La versione attuale infatti è stata pensata per un utilizzo ristretto ad
un ambito di laboratorio, la nuova versione dovrà invece far operare i computer attualmente disponibili insieme ad altri appartenenti a diversi laboratori.
Tali computer sono normalmente inaccessibili dall’esterno della propria rete a
causa della presenza di servizi come NAT o firewall. La nuova versione dovrà
ovviare a questi problemi fornendo un’interfaccia web alla quale i vari utenti
possano autenticarsi e sottomettere i propri lavori che saranno distribuiti sulla griglia ed eseguiti non appena questa sarà disponibile. Dovrà quindi essere
gestita una coda dei vari lavori sottomessi dagli utenti ed eseguirli cercando
di utilizzare la massima potenza di calcolo disponibile.
CAPITOLO 1. INTRODUZIONE
1.4
4
Stato dell’arte
Uno dei progetti, forse anche il più famoso, che più si avvicina agli argomenti
trattati in precedenza è SETI@home (SETI at home) [2], un progetto di
calcolo distribuito volontario che usa computer connessi ad internet, ospitato
dalla Space Sciences Laboratory all’Università della California, Berkeley, negli
Stati Uniti d’America. SETI è l’acronimo di Search for Extra-Terrestrial
Intelligence ed il suo scopo è quello di analizzare segnali radio in cerca di
segni di intelligenze extraterrestri.
Chiunque con un computer connesso ad internet può partecipare a SETI@home eseguendo un software gratuito che scarica ed analizza dati provenienti dal radio-telescopio. Il software di calcolo distribuito di SETI@home
può essere eseguito sia come screensaver sia mentre l’utente è a lavoro, sfruttando la potenza di elaborazione che altrimenti sarebbe inutilizzata. La prima piattaforma software, ora denominata “SETI@home Classic” [3] è stata
utilizzata dal 17 maggio 1999 al 15 dicembre 2005. Quest’ultima consentiva
di eseguire solo SETI@home. Fu sostituito da Berkeley Open Infrastructure
for Network Computing (BOINC) [4], il quale permette agli utenti di contribuire anche ad altri progetti di calcolo distribuito contemporaneamente
all’esecuzione di SETI@home.
Un altro famoso progetto di calcolo distribuito è neuGRID [5], finanziato
dalla Comunità Europea. Il progetto prevede lo sviluppo di un’infrastruttura digitale per la ricerca scientifica, basata sul sistema Grid ed è dotata di
un’interfaccia che permetterà alla comunità di neuroscienziati europei l’avanzamento della ricerca per lo studio delle malattie neurodegenerative (come
il morbo di Alzheimer). All’interno di neuGRID, vi è la possibilità di raccogliere ed archiviare un’ingente quantità di dati di imaging molecolare e di
effettuare analisi computazionalmente impegnative, attraverso il paradigma
del calcolo distribuito. Un ricercatore interagisce con neuGRID per selezionare un gruppo di immagini da analizzare, usando l’algoritmo prescelto.
Completata l’elaborazione dell’immagine sulla griglia, il dato di input viene
confrontato al dato di output per verificare il risultato del processo. Questo
CAPITOLO 1. INTRODUZIONE
5
viene poi trasferito dall’utente in postazione remota per ulteriori eventuali
analisi statistiche e visualizzazioni avanzate.
1.5
Risultati
Tutti gli obiettivi prefissati sono stati raggiunti con successo. La versione
precedente di GRIMD ha dovuto essere modificata allo scopo di permettere
tale gestione multiutente. Infatti sono state introdotte alcune componenti aggiuntive ed inoltre è stato necessario anche effettuare un refactoring a
livello architetturale per risolvere alcune problematiche che saranno presentate successivamente. Allo stato attuale è disponibile un’interfaccia web che
permette l’accesso al sistema agli utenti autorizzati e fornisce loro la possibilità di sottomettere i lavori che si desidera eseguire. I lavori sottomessi
vengono poi gestiti da un apposito servizio di gestione della coda ed eseguiti
utilizzando le basi fornite da GRIMD con le opportune modifiche.
Capitolo 2
Le tecnologie
In questo capitolo saranno mostrate le tecnologie utilizzate durante lo svolgimento del lavoro. Se queste sono già conosciute la lettura del capitolo può
essere tralasciata, in quanto si fornirà solamente una panoramica generale e
non saranno trattati i dettagli delle varie tecnologie.
2.1
.NET Framework
Il .NET Framework è un framework software sviluppato dalla Microsoft, destinato ad essere usato dalla maggior parte delle nuove applicazioni create
per le piattaforme Windows le quali ne forniscono il pieno supporto.
Esso include una vasta gamma di librerie di base, detta Base Class
Library (BCL) e fornisce l’interoperabilità di linguaggio attraverso i diversi
linguaggi di programmazione supportati (cioè ogni linguaggio può utilizzare
del codice scritto in altri linguaggi).
In particolare nel corso del lavoro sono stati utilizzati i seguenti linguaggi
di programmazione .NET:
• C# , linguaggio ad oggetti simile al Java della Oracle Corporation.
• Visual Basic .NET (abbreviato VB.NET), linguaggio orientato agli
oggetti e multi-thread basato sulla sintassi di Visual Basic
6
CAPITOLO 2. LE TECNOLOGIE
7
• ASP.NET, evoluzione del classico ASP (Active Server Pages), linguaggio di programmazione in ambiente web, implementa .NET ed è dotato di librerie .NET, anche se non viene considerato un linguaggio
vero e proprio poiché può essere scritto utilizzando un qualsiasi altro
linguaggio .NET.
• ADO.NET, nuova versione per il .NET Framework di ADO (ActiveX
Data Objects)
BCL fornisce classi per la creazione di interfacce utente, accesso ai dati,
connettività a database, crittografia, sviluppo di applicazioni web, algoritmi
numerici e comunicazione su rete. I programmatori producono software combinando il loro codice sorgente con BCL ed eventuali altre librerie di terze
parti.
Tutto il codice della BCL, librerie di terze parti e qualsiasi altro programma scritto in un qualsiasi linguaggio .NET viene tradotto nel Common Intermediate Language (CIL) che rappresenta il linguaggio di programmazione di più basso livello ancora leggibile dall’uomo definito dalla Common
Figura 2.1: Diagramma della Common Language Infrastructure.
CAPITOLO 2. LE TECNOLOGIE
8
Language Infrastructure (CLI) rappresentata in figura 2.1, ossia lo standard Microsoft che descrive il codice eseguibile e l’ambiente d’esecuzione che
forma il nucleo del .NET Framework.
I programmi trasformati in CIL vengono quindi eseguiti all’interno di
un ambiente software noto come Common Language Runtime (CLR),
una macchina virtuale che fornisce importanti servizi e funzionalità quali la
sicurezza, la gestione della memoria, la gestione delle eccezioni, etc.
Per fare un esempio, il CIL e il CLR possono essere paragonati al Bytecode
ed alla macchina virtuale di Java.
Le librerie di classi BCL e il CLR, insieme costituiscono il .NET Framework. In figura 2.2 è rappresentato lo stack .NET Framework fino alla
versione 4.0.
2.1.1
Entity Framework
Entity Framework è un set di tecnologie ADO.NET (ActiveX Data Objects), ossia un sottoinsieme di librerie della BCL utilizzato per suppor-
Figura 2.2: Lo stack .NET Framework fino alla versione 4.0.
CAPITOLO 2. LE TECNOLOGIE
9
tare lo sviluppo di applicazioni software orientate ai dati. Le tecnologie
ADO.NET rappresentano il primo modello di accesso relazionale ai dati per
le applicazioni basate su Microsoft .NET Framework.
Entity Framework rappresenta una soluzione di mapping relazionale ad
oggetti ed è uno strumento che consente alle applicazioni di accedere e modificare i dati, i quali vengono rappresentati come entità e relazioni. Le informazioni contenute nei file di modello e di mapping, che necessitano di essere
definiti tramite appositi linguaggi, vengono utilizzate per tradurre le query
eseguite sui vari tipi di entità in query specifiche dell’origine dati. Questo
accade poiché le origini dei dati possono essere di tipo differente (Strutture
dati, DBMS, file, etc) ed il risultato delle query viene poi rappresentato da
oggetti gestiti da Entity Framework.
Il meccanismo di traduzione delle query è fornito dai provider di dati
EntityClient. Tali provider gestiscono connessioni alle sorgenti dei dati,
convertono query di entità in query specifiche dell’origine dati e restituiscono un lettore dati utilizzato successivamente da Entity Framework per
materializzare i dati dell’entità in oggetti.
I metodi disponibili per eseguire query su un modello concettuale e restituire oggetti sono fondamentalmente due:
• LINQ to Entities: Fornisce il supporto LINQ (Language-Integrated
Query) per l’esecuzione di query su tipi di entità definiti in un modello
concettuale
• Entity SQL: Sottolinguaggio SQL indipendente dall’archiviazione che
interagisce direttamente con le entità del modello concettuale e supporta il concetto di Entity Data Model (derivante dal modello Entity
Relationship)
La figura 2.3 mostra l’architettura di Entity Framework per l’accesso ai
dati.
CAPITOLO 2. LE TECNOLOGIE
10
Figura 2.3: Architettura di Entity Framework per l’accesso ai dati.
LINQ
Language Integrated Query (LINQ, si pronuncia “link”) è un componente del
.NET Framework che aggiunge ai linguaggi .NET la possibilità di effettuare
interrogazioni su oggetti utilizzando una sintassi simile a SQL. Esso definisce
un insieme di operatori che possono essere usati per interrogare, proiettare
e filtrare dati in matrici, classi enumerabili, XML, database relazionali e
sorgenti dati di terze parti. Consente l’interrogazione di ogni sorgente di
dati che rappresenti i dati sotto forma di oggetti. Per questa ragione, se la
sorgente non memorizza in maniera nativa i dati come oggetti, è necessario
l’utilizzo di un connettore per accedere ai dati. Il risultato di una query viene
restituito come una collezione di oggetti in memoria che possono poi essere
enumerati.
CAPITOLO 2. LE TECNOLOGIE
2.1.2
11
Membership
La Membership è una funzionalità integrata di ASP.NET che consente
di convalidare e archiviare le credenziali utente, facilitando cosı̀ la gestione
dell’autenticazione degli utenti nei siti Web e fornisce il supporto per:
• Creazione di nuovi utenti e password.
• Archiviazione delle informazioni di account utente (nomi utente, password e dati di supporto) in Microsoft SQL Server, Active Directory o
in un archivio dati alternativo.
• Autenticazione degli utenti che visitano il sito. È possibile autenticare gli utenti a livello di codice oppure utilizzare i controlli di accesso
ASP.NET per creare un sistema di autenticazione completo che non
richieda la scrittura di codice o la richieda solo in minima parte.
• Gestione delle password, comprese le operazioni di creazione, modifica
e reimpostazione. A seconda delle impostazioni utilizzate, la Membership può anche fornire un sistema automatico per la reimpostazione
delle password che accetti una domanda ed una risposta segreta fornite
dall’utente.
• Definizione di un provider Membership personalizzato, che è possibile
utilizzare in sostituzione del provider di default per gestire gli account
e mantenere i dati relativi.
Gli utenti possono essere raggruppati per ruolo. La gestione dei ruoli in
ASP.NET consente di gestire le autorizzazioni, permettendo di specificare
quali utenti possono accedere a determinate risorse dell’applicazione. Analogamente ai Membership Provider è possibile definire provider personalizzati
per la gestione dei ruoli.
CAPITOLO 2. LE TECNOLOGIE
2.1.3
12
Windows Communication Foundation
Windows Communication Foundation (WCF), conosciuto in fase di sviluppo con il nome Indigo, è un sistema del .NET Framework che offre la
struttura API per la creazione di applicazioni distribuite. Ogni protocollo
di rete (HTTP, FTP, SMTP, etc.) ha un suo modello di programmazione e
necessita quindi di una conoscenza specifica da parte degli sviluppatori per
poter essere utilizzata. WCF è stato invece realizzato con l’intento di ricondurre ad un unico modello diverse tecnologie, rendendo più semplice ed
uniforme la programmazione. È spesso utilizzato per implementare sistemi
con architettura SOA (Service Oriented Architecture)
Un servizio WCF si basa sul concetto di Endpoint che rappresenta la
porta attraverso la quale le applicazioni comunicano con il mondo esterno.
Si può quindi affermare che un servizio WCF sia una collezione di Endpoint.
A sua volta, un Endpoint è costituito da quelli che sono i pilastri di WCF:
Address, Binding, Contract.
Address
L’Address è l’indirizzo al quale il servizio risponde. L’indirizzo è composto
da un URI, una Identity ed una lista di Header. In fase di definizione di un
Address, l’informazione principale è l’URI, che corrisponde all’indirizzo fisico
del servizio. Header e Identity sono informazioni opzionali che sono necessarie
solo in casi particolari, come ad esempio per specificare un certificato X.509
nel caso sia richiesto un maggior grado di sicurezza.
Binding
Il concetto di Binding è forse il più importante tra quelli proposti in WCF.
Infatti è proprio grazie ad esso se ci si può occupare esclusivamente del codice senza interessarsi minimamente all’infrastruttura di trasporto. I Binding
si occupano di quello che avviene tra il momento in cui il servizio spedisce
CAPITOLO 2. LE TECNOLOGIE
13
logicamente il messaggio ed il momento in cui questo viene fisicamente trasmesso sulla rete. In questo lasso di tempo vengono eseguiti numerosi passi
che seguono una precisa pipeline di cui i binding sono responsabili.
Il messaggio deve attraversare due livelli: il primo si occupa dei Behaviour
(Comportamenti), ovvero delle trasformazioni che deve subire un messaggio,
il secondo si occupa dei Channel (Canali), ovvero dell’instradamento verso il
canale fisico di trasporto.
Nel primo livello ci si occupa della conversione dei dati dal formato originario al formato specifico del messaggio che dipende dal protocollo utilizzato. Ad esempio, potrebbe essere effettuata la serializzazione di una classe
nel formato XML di un messaggio SOAP. In aggiunta i Behaviour si occupano anche della sicurezza, ad esempio della cifratura delle informazioni e
di altre funzioni di gestione del dato. Durante la seconda fase il messaggio
viene tramesso sul canale di trasporto. La gestione dei Binding può essere
interamente gestita in fase di configurazione, si può quindi intuire come semplicemente cambiando la configurazione si può passare da un protocollo ad
un altro, come ad esempio da HTTPS ad un trasporto diverso del messaggio
come i semplici TCP o HTTP senza dover modificare il codice.
Contract
Il Contract rappresenta l’interfaccia software vera e propria che il servizio
pubblica ed espone all’esterno. Ogni operazione definita nel contract consiste
in un semplice scambio di messaggi utilizzando il protocollo specificato in fase
di configurazione.
2.2
SQL Server
Microsoft SQL Server è un DBMS relazionale, meglio noto come Relational Database Management System (RDBMS), prodotto da Microsoft. Nelle
prime versioni era utilizzato per basi dati medio-piccole, ma a partire dalla
CAPITOLO 2. LE TECNOLOGIE
14
versione 2000 è stato utilizzato anche per la gestione di basi dati di grandi
dimensioni.
SQL Server utilizza una variante del linguaggio SQL standard chiamata
Transact-SQL (T-SQL) comunicando sulla rete utilizzando un protocollo
a livello di applicazione chiamato Tabular Data Stream (TDS). Supporta
anche Open Database Connectivity (ODBC).
2.3
Windows Server 2003
Successore di Windows 2000, Microsoft Windows Server 2003 rappresenta
una tappa della evoluzione della serie server dei sistemi operativi di Microsoft.
Il lancio è avvenuto il 24 aprile 2003 ma conserva ancora oggi la compatibilità
con molte delle caratteristiche presenti nei sistemi fino a Windows XP e
Windows 7.
2.3.1
Internet Information Services
Internet Information Services (abbreviato in IIS), è un complesso di
servizi server Internet per sistemi operativi Microsoft Windows. Inizialmente
venne distribuito come Option Pack per il sistema operativo Windows NT,
venne poi integrato in Windows 2000 e Windows Server 2003. La versione
corrente, integrata in Windows Server 2008 R2, è la 7.5 ed include i servizi
server per i protocolli FTP, SMTP, NNTP e HTTP/HTTPS.
L’applicazione server non è in grado, di per sé, di eseguire elaborazioni
Server-side ma ne delega l’esecuzione ad applicazioni ISAPI (Internet Server Application Programming Interface), una interfaccia di programmazione
(API) messa a disposizione da Microsoft per gli sviluppatori che intendono
interagire ed ampliare le funzionalità del server web. Microsoft stessa fornisce una serie di applicazioni tra le quali il modulo per Active Server Pages ed
ASP.NET. Altri sviluppatori hanno reso disponibili i moduli per il supporto
ai linguaggi PHP e Perl.
CAPITOLO 2. LE TECNOLOGIE
15
Sebbene il mercato dei server web sia controllato saldamente da Apache,
IIS è riuscito, negli anni, a guadagnarsi una fetta di server pari a circa il 20%
dei domini totali.
2.4
Virtual Private Network
Una Rete Privata Virtuale (Virtual Private Network o VPN) è una rete di
telecomunicazioni privata, instaurata tra soggetti che utilizzano un sistema
di trasmissione pubblico e condiviso, come per esempio Internet. Lo scopo
delle reti VPN è di offrire alle aziende, a un costo inferiore, le stesse possibilità delle linee private in affitto sfruttando reti condivise pubbliche. Si
può vedere una VPN come l’estensione, a scala geografica, di una rete locale
privata aziendale che colleghi tra loro siti interni all’azienda stessa variamente dislocati su un ampio territorio sfruttando una rete IP pubblica per
il trasporto su scala geografica e realizzando una rete LAN, detta appunto
virtuale e privata, logicamente del tutto equivalente ad una infrastruttura
fisica di rete appositamente dedicata.
Per mezzo di una VPN, utilizzando una connessione Internet, è ad esempio possibile collegarsi dall’esterno alla rete privata del proprio ufficio, scavalcando tutti i problemi dovuti alla raggiungibilità ad esempio per la presenza
di firewall o NAT (Network Address Translation). Generalmente una VPN
comprende due parti: una interna alla rete, e quindi protetta, che preserva
la trasmissione, e una meno affidabile e sicura che è quella esterna alla rete
privata, ad esempio via Internet. Le reti VPN utilizzano collegamenti che
necessitano di autenticazione in modo da garantire l’accesso ai soli utenti
autorizzati. Per garantire la sicurezza che i dati inviati in Internet non siano
intercettati o utilizzati da altri non autorizzati, le reti utilizzano sistemi di
crittografia. Le reti VPN sicure adottano dunque protocolli che provvedono
a cifrare il traffico transitante sulla rete virtuale. Oltre alla cifratura, una
VPN sicura deve prevedere nei suoi protocolli dei meccanismi che impedisca-
CAPITOLO 2. LE TECNOLOGIE
16
no violazioni della sicurezza, come ad esempio il furto dell’identità digitale o
l’alterazione dei messaggi.
Alcuni dei protocolli più comuni utilizzati nelle VPN sono:
• IPsec (IP security), comunemente usate su IPv4 (parte obbligatoria
dell’IPv6).
• PPTP (point-to-point tunneling protocol), sviluppato da Microsoft.
• SSL/TLS, utilizzata nel progetto OpenVPN, è un framework molto
spesso associato con il commercio elettronico, che s’è rivelato di grande flessibilità ed è quindi usato come strato di sicurezza per varie
implementazioni (più o meno standard) di reti private virtuali.
In particolare nel corso del lavoro si è scelto di utilizzare il servizio VPN
offerto da Windows Server 2003 che fa uso del protocollo PPTP.
Capitolo 3
Refactoring architettura
In questo capitolo sarà presentata l’architettura di GRIMD 1.1 [1], e le modifiche apportate nella nuova versione allo scopo di fornire un servizio di gestione
web e multiutente. Ci si concentrerà quindi solamente sugli aspetti architetturali analizzando i vantaggi derivanti dalle scelte adottate nell’ultima fase
di sviluppo.
3.1
GRIMD 1.1
L’architettura originaria di GRIMD prevede la presenza di una macchina
master che coordina il lavoro di un numero indeterminato di slave.
Il master gestisce una lista statica di slave ai quali si connette all’avvio.
Gli slave che non sono raggiungibili in quel determinato istante, o che vengono
persi durante la computazione, saranno ricontattati ad intervalli regolari per
verificarne la nuova eventuale disponibilità. È importante notare quindi che
la direzione della connessione va dal master agli slave. Una volta instaurata,
la connessione resta aperta fino alla terminazione dello slave o del master.
Allo stesso modo una volta terminata una computazione il master ricontatta tutti gli slave, preleva da ciascuno un file contenente una sintesi dei
risultati ottenuti, ed eventualmente li recupera salvandoli sulla macchina che
lo ospita.
17
CAPITOLO 3. REFACTORING ARCHITETTURA
3.2
18
Modifiche apportate
La precedente versione di GRIMD si è rivelata particolarmente adatta all’utilizzo in un ambito di laboratorio, dove ogni computer si trova all’interno
della stessa rete e i requisiti di sicurezza sono limitati.
Con l’intento di estendere le capacità di GRIMD ad un ambito più ampio,
accademico o aziendale, abbiamo scelto di mantenere la versione precedente
di GRIMD per un utilizzo di laboratorio e sviluppare una versione web che
consenta l’utilizzo di computer appartenenti a diverse subnet, scavalcando
i problemi dovuti alla presenza di NAT (Network Address Translation), e
più utenti contemporaneamente e che, soprattutto, preservi l’integrità di ciascuna macchina slave negando l’accesso ad utenti malintenzionati. Maggiori
dettagli sulla sicurezza saranno forniti nella successiva sezione.
Nella versione precedente di GRIMD, era il master ad instaurare la connessione verso gli slave. Questo risulta essere un grosso limite architetturale
nell’ottica di fornire accesso ad un numero maggiore di utenti, infatti non
era possibile contattare slave che non si trovavano nella stessa sottorete del
master.
Inoltre, dal momento che il master comunica con gli slave utilizzando
il protocollo SMB e richiede la disponibilità di una determinata porta
(di default TCP 8883) la presenza di firewall sulle macchine slave potrebbe
impedire la comunicazione, a meno che non siano configurate appositamente.
Si è pertanto pensato di usufruire di un servizio VPN (Virtual Private
Network). Il server che ospita il master, dotato di Windows Server 2003, è
particolarmente adatto a far da server anche nella VPN, essendo già raggiungibile da tutti tramite IP pubblico (yadamp.unisa.it). La nuova versione dello
slave all’avvio si preoccuperà di instaurare una connessione alla rete virtuale utilizzando il supporto nativo del sistema operativo tramite protocollo
PPTP (Point-to-Point Tunneling Protocol).
CAPITOLO 3. REFACTORING ARCHITETTURA
19
Figura 3.1: Diagramma dell’architettura di GRIMD.
3.2.1
Sicurezza
Nella versione precedente di Grimd le password utilizzate per la comunicazione tra master e slave erano memorizzate in chiaro sul master e nel file batch
di installazione dello slave. Dovendo la nuova versione lavorare con un insieme più vasto di slave, dislocati in diversi laboratori dell’ateneo, si è deciso
di memorizzare tali informazioni sensibili in un unico database consultabile
solo dagli addetti ai lavori, per evitare intrusioni nel file system distribuito
del sistema, anche da parte di computer che appartengono alla griglia. Verranno, inoltre, impostate per la cartella dello slave maggiori restrizioni, in
modo tale da permettere solo all’utente amministratore l’accesso in lettura e
scrittura.
La connessione e la comunicazione alla VPN sono cifrate tramite MSCHAPv2 (Microsoft Challenge Handshake Authentication Protocol) e MP-
CAPITOLO 3. REFACTORING ARCHITETTURA
20
PE (Microsoft Point-to-Point Encryption), che fa uso di RSA RC4 con chiave
di sessione a 128bit.
Qualunque operazione sul file system degli slave continuerà a richiedere
username e password.
GRIMD 1.1
password in chiaro
nei file di configurazione del master
GRIMD 1.2
rimozione file di
configurazione
e
gestione dinamica
degli account degli
slave
password in chia- rimozione del file di
ro in file batch di installazione
installazione
permessi non impo- accesso consentito
stati per la directo- solo agli utenti griry slave
md e administrator
Tabella 3.1: Sicurezza in GRIMD 1.1 e 1.2
3.3
Requisiti minimi
Il codice sorgente del master e dello slave è stato scritto utilizzando i linguaggi VB.NET e C# appartenenti alla famiglia di linguaggi Microsoft
.NET Framework, mentre per l’interfaccia web è stato utilizzato ASP.NET.
La comunicazione interprocesso avviene utilizzando WCF (Windows Communication Foundation), mentre lo spostamento dei files sfrutta il protocollo
SMB. Per garantire il funzionamento del sistema pertanto è necessario che
tutti i pc slave dispongano dei seguenti requisiti:
• Windows XP SP3 o successiva
CAPITOLO 3. REFACTORING ARCHITETTURA
21
• .NET Framework v.4 o successiva
• Raggiungibilità al file system locale tramite protocollo SMB (Configurazione del firewall su interfaccia VPN)
• Raggiungibilità tramite protocollo TCP alla porta 8883 (Configurazione del firewall su interfaccia VPN)
Capitolo 4
Struttura del sistema
In questo capitolo saranno descritte nel dettaglio l’architettura ed il funzionamento di tutte le componenti del sistema introdotte per svolgere il lavoro.
Saranno riportati anche gli schemi relazionali delle tabelle che compongono
il database.
4.1
Gestione utenti
Dal momento che uno degli obiettivi principali è quello di fornire l’accesso a
GRIMD ad un determinato numero di utenti, si è pensato fosse necessario
introdurre, per motivi di ordine, una semplice gerarchia tra questi ultimi.
Sono infatti stati definiti due ruoli per gli utenti, uno con privilegi amministrativi e l’altro con normale accesso al sistema.
In particolare, l’utente amministratore ha il potere di:
• Creare o eliminare nuovi utenti dal sistema e gestirne i ruoli.
• Alterare arbitrariamente l’ordine dei lavori in coda.
• Eliminare o modificare la posizione dei lavori in coda.
• Terminare il sistema.
22
CAPITOLO 4. STRUTTURA DEL SISTEMA
23
Gli utenti normali possono invece sottomettere le macro per uno o più
lavori, le quali una volta caricate vengono inserite nella coda.
4.2
Base dei dati
In figura 4.1 è mostrato il diagramma ER della base dati utilizzata. Per
esigenze di spazio sono mostrate solamente le entità ritenute di maggior
importanza. Di seguito sarà riportata una breve descrizione per ogni entità.
Figura 4.1: Diagramma Entità-Relazione della base di dati utilizzata per
immagazzinare tutte le informazioni necessarie.
CAPITOLO 4. STRUTTURA DEL SISTEMA
24
Workset
Rappresenta un lavoro caricato da un utente e mantiene traccia di tutte le
informazioni relative come il path e il nome del file della macro, data di
inizio e fine computazione, tipo di computazione, tipo di scheduler utilizzato
ed utente proprietario.
Slaves
Qui sono memorizzate le informazioni di tutti gli slave disponibili. Indirizzo
IP nella VPN, porta in ascolto, stato (online/offline), nome NetBIOS della
macchina, numero di core per processore, versione del sistema operativo,
username e password di accesso per GRIMD e data di ultimo accesso.
Queue
Questa tabella viene utilizzata per tener traccia di tutti i workset che sono
presenti nella coda dei lavori e la relativa posizione.
SecondaryQueue
Analoga a Queue, con la differenza che viene utilizzata per tener traccia di
tutti i workset nella coda secondaria.
aspnet User
Tabella gestita quasi interamente dalla Membership di ASP.NET per tener
traccia di tutti gli utenti che sono abilitati ad accedere al sistema.
aspnet Roles
Tabella gestita dalla Membership di ASP.NET per tener traccia di tutti i ruoli degli utenti che sono abilitati ad accedere al sistema. La relazione di tipo molti-a-molti con gli utenti è mantenuta tramite la tabella
aspnet UsersInRoles
CAPITOLO 4. STRUTTURA DEL SISTEMA
4.3
25
Servizio di gestione Master
Come già spiegato in precedenza abbiamo deciso di mantenere quanto più
possibile della struttura originale di GRIMD, modificando solo ciò che era
strettamente necessario. Nella precedente versione l’avvio del master corrisponde con l’avvio di un nuovo lavoro. Il workset nella nuova versione dovrà
essere reperito dalla coda e disposto nell’apposito path. La terminazione del
lavoro corrisponde alla terminazione del master. Pertanto si è reso necessario
introdurre un servizio, mantenuto costantemente in esecuzione, che avvii il
master ogni volta che in testa alla coda è presente un lavoro da eseguire.
Chiaramente è necessario che questo servizio possa comunicare con il
modulo di gestione della coda per prelevare da questa il prossimo workset
e che si preoccupi di tenere avviato il servizio di identificazione degli slaves
per poter conoscere le risorse a disposizione che possono essere assegnate al
workset in elaborazione.
La figura 4.2 mostra il diagramma delle classi del servizio di gestione del
master. Le classi MasterQueue e VPNIDResolver contengono le implementazioni dei contract dei servizi di gestione coda e di identificazione slave esposti
dal servizio di gestione master tramite WCF.
4.3.1
Modulo di identificazione Slave
Nella precedente versione di GRIMD era il master a tener traccia degli indirizzi di tutti i possibili slave, i quali venivano contattati ad intervalli regolari
per verificarne la loro eventuale disponibilità. Nella nuova versione, sia per i
motivi di sicurezza descritti nel capitolo precedente che a causa dalla presenza della VPN, non è più possibile tener traccia staticamente di tutti gli slave
dal momento che l’assegnazione degli indirizzi IP nella VPN avviene tramite
l’utilizzo di un server DHCP e quindi uno stesso indirizzo, nel tempo, può
essere assegnato a slave diversi. Si è deciso quindi di gestire dinamicamente
l’intera situazione facendo in modo che siano gli slave a comunicare la loro
CAPITOLO 4. STRUTTURA DEL SISTEMA
26
Figura 4.2: Diagramma delle classi per il gestore del master.
disponibilità al servizio di gestione del master, il quale conserva lo stato di
tutti gli slave in un unico registro.
Per identificare ogni slave, all’atto della registrazione, è necessario che
questi forniscano ogni volta un ID univoco assegnato loro dal sistema di
gestione, tramite il quale sarà possibile tener traccia di tutte le informazioni
relative. Nel caso che uno slave non fornisca un ID valido, o nel caso che
non lo fornisca affatto, gli viene assegnato un nuovo ID e vengono reperite e
memorizzate tutte le informazioni mostrate nella descrizione della base dati.
In figura 4.3 è mostrato il diagramma delle classi per il servizio di identificazione slave. L’interfaccia IVPNIDResolver rappresenta il contract esposto
CAPITOLO 4. STRUTTURA DEL SISTEMA
27
Figura 4.3: Diagramma delle classi per il servizio di identificazione slave.
tramite WCF, mentre la classe VPNIDResolver ne fornisce l’implementazione tramite l’ausilio della classe GRIMDEntities utilizzata per l’accesso alla
base dati.
4.3.2
Modulo di gestione coda
Nonostante per un utente sia prevista la possibilità di sottomettere più lavori,
nella coda non potrà essere presente un lavoro dello stesso utente per più di
una volta. Più precisamente il sistema si preoccuperà di gestire due code
differenti, una primaria ed una secondaria.
Nella coda primaria, per la quale è prevista una politica di gestione di
tipo FIFO (First In First Out), è presente il vincolo di una singola presenza
in coda per ogni utente al fine di impedire che si possa monopolizzare il
sistema e tenerlo impegnato per un periodo di tempo troppo lungo. Nella
coda secondaria invece non sono presenti vincoli, ogni utente puo inserire un
numero illimitato di lavori. Il più “anziano” tra questi sarà spostato in coda
primaria non appena si sarà liberato l’unico posto disponibile per ciascun
CAPITOLO 4. STRUTTURA DEL SISTEMA
28
Figura 4.4: Diagramma delle classi per il modulo di gestione coda.
utente. La coda secondaria è stata pensata per permettere di inserire in coda
più lavori facendo in modo che venga data priorità all’ordine di inserimento
per utente, invece che per lavoro.
In figura 4.4 è mostrato il diagramma delle classi del modulo di gestione
coda. L’interfaccia IMasterQueue rappresenta il contract in WCF che viene
esposto al sistema di gestione coda per interagire con essa. La classe MasterQueue ne fornisce l’implementazione tramite l’utilizzo della classe ausiliaria
QueueHandler che si preoccupa di mantenere lo stato della coda nel database
utilizzando l’apposita classe GRIMDEntities.
CAPITOLO 4. STRUTTURA DEL SISTEMA
4.4
29
Modulo di controllo di stato del Master
Tutti i dati riguardanti l’andamento del lavoro, come ad esempio il numero di
slave totali, disponibili o persi durante la computazione, sono contenuti solamente all’interno del processo del master e quindi praticamente inaccessibili
dall’esterno.
Figura 4.5: Diagramma delle classi per il modulo di controllo di stato del
master.
Per permettere l’accesso a questi dati tramite il pannello di controllo
utente presente sull’interfaccia web, è stato necessario introdurre nel master un modulo che esponga all’esterno la possibilità di reperirli e quindi di
visualizzarli.
Come si può vedere in figura 4.5 il contract WCF (IMasterStatus) contiene
un semplice metodo che restituisce un oggetto contenente lo stato del lavoro
in esecuzione all’istante dell’invocazione. Per l’implementazione nella classe
MasterStatus è stato creato un apposito bean, GRIMDStatus, che viene costantemente aggiornato dal master e restituito come risultato dell’invocazione
del metodo presente nell’interfaccia.
CAPITOLO 4. STRUTTURA DEL SISTEMA
4.5
30
Altre modifiche
Di seguito viene riportato l’elenco di modifiche, di minore impatto, apportate
ai servizi già esistenti nella versione precedente che non sono state ancora
presentate.
4.5.1
Master
Sono state effettuate altre modifiche minori nel master per quanto riguarda la
creazione dei file di log. Infatti, in origine, nei file di log si teneva traccia degli
indirizzi IP degli slave che, allo stato attuale, non forniscono un’informazione
sufficiente per la loro identificazione a causa dei problemi precedentemente
descritti. Sono quindi state apportate modifiche al logging facendo in modo
che oltre all’indirzzo IP venga memorizzato anche l’ID di ogni slave.
4.5.2
FRED e GDUMP
Le informazioni conservate nei file di log sono utilizzate successivamente dai
servizi FRED e GDUMP rispettivamente per forzare l’operazione di reduce
e per il recupero dell’intero insieme dei risultati conservati sugli slave. È
da precisare che la nuova versione di GDUMP permette anche il recupero
selettivo dei risultati e non obbligatoriamente quello dell’intero insieme.
È stato necessario modificare le versioni precedenti di FRED e GDUMP,
sia a causa del cambiamento del formato di log che per permettere il loro
funzionamento tramite gli ID degli slave, utilizzati al posto di indirizzi IP.
Infatti ora per ogni job cotenuto nel workset viene effettuata la risoluzione
dell’ID dello slave associato utilizzando l’apposito servizio. In tal modo è
possibile controllare se lo slave di riferimento è disponibile ed eventualmente ottenerne l’indirizzo IP corrente per contattarlo e prelevare i risultati di
interesse.
CAPITOLO 4. STRUTTURA DEL SISTEMA
4.5.3
31
Slave
Le modifiche apportate allo slave riguardano essenzialmente l’introduzione
dell’ingresso in VPN e della registrazione al servizio di identificazione. Dopo
queste due fasi iniziali lo slave funziona esattamente come nella precedente
versione, ad eccezione della gestione dei risultati memorizzati.
Nella precedente versione infatti, all’inizio di un nuovo lavoro, il master
provvedeva ad inviare allo slave una richiesta RESET DFS che causava la
cancellazione dell’intero insieme di risultati memorizzati sullo slave. Nella
nuova versione invece, a prescindere dall’inizio di un nuovo lavoro, si garantisce che i risultati siano conservati per un periodo di tempo minimo pari a
quattro giorni dall’ultimazione del lavoro, dopo i quali non si garantisce più
la permanenza di tali informazioni sulla macchina. Pertanto, se queste sono
oggetto di interesse, è obbligatorio effettuarne il recupero da parte dell’utente
entro questo termine.
Conclusioni
Per quanto i sistemi di grid computing siano oggi estremamente utilizzati,
esistono molti problemi, di difficile soluzione, quali la gestione dell’alto grado
di eterogeneità e la sicurezza, che rendono improponibile un avvento del Grid
in qualità di tecnologia pervasiva. Ad oggi, il suo utilizzo resta circoscritto
a grandi attori in grado di poter effettuare investimenti importanti in manodopera specializzata in grado di gestire e utilizzare i sistemi Grid di presente
generazione.
Questo lavoro può essere considerato come la base di partenza per lo
sviluppo di applicazioni distribuite condivise tra più utenti, da proseguire sia
attraverso l’approfondimento progettuale sia attraverso l’implementazione di
ulteriori sviluppi tecnologici. Il progetto nasce come tentativo di allargare
l’esperienza d’uso di un sistema condividendolo in un gruppo più vasto di
utenti, cercando di facilitare il più possibile la comunicazione tra le risorse
interne al sistema, spesso impedite da servizi di protezione come firewall
oppure come il NAT. Il sistema sviluppato rimane comunque un progetto
sperimentale, durante il quale si sono scoperti numerosi risvolti interessanti.
Sviluppi futuri potrebbero consistere in miglioramenti nell’organizzazione e nella comunicazione interna al sistema, nello sviluppo dell’applicazione
slave con compatibilità per sistemi LINUX, nell’introduzione del supporto di
nuove applicazioni anche non inerenti al calcolo scientifico o nell’inserimento di un sistema che renda possibile la distribuzione e quindi l’esecuzione
di un’applicazione generica, sempre seguendo il modello di programmazione
Map/Reduce.
32
Bibliografia
[1] Alessandro Bove, Alfonso Martorelli, Luigi Di Biasi. “Distributed
Map/Reduce Grid for YASARA” 2011
[2] SETI Institute (Search for Extra-Terrestrial Intelligence) http://
www.seti.org
[3] SETI@Home - SETI at home Classic http://setiathome.
berkeley.edu
[4] Berkeley Open Infrastructure for Network Computing (BOINC)
http://boinc.berkeley.edu
[5] Grid-Based e-Infrastructure for computationally data-intensive application in medical sciences http://www.neugrid.eu/pagine/home.
php
33
Appendice A
Appendice
A.1
A.1.1
Servizio di controllo stato Master
IMasterStatus
1 namespace M a s t e r S t a t u s L i b
2 {
3
[ ServiceContract ]
4
public i n t e r f a c e IMasterStatus
5
{
6
[ O p e r a t i o n C o n t r a c t ( IsOneWay = f a l s e ) ]
7
GRIMDStatus g e t S t a t u s ( ) ;
8
}
9 }
A.1.2
MasterStatus
1 namespace M a s t e r S t a t u s L i b
2 {
3
[ S e r v i c e B e h a v i o r ( InstanceContextMode =
InstanceContextMode . S i n g l e ) ]
4
public c l a s s MasterStatus : IMasterStatus
5
{
6
#r e g i o n V a r i a b i l i d ’ i s t a n z a
7
8
p r i v a t e GRIMDStatus s t a t u s ;
9
private ServiceHost host ;
10
11
#e n d r e g i o n
12
34
APPENDICE A. APPENDICE
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
#r e g i o n Implementazione i n t e r f a c c i a
p u b l i c GRIMDStatus g e t S t a t u s ( )
{
return status ;
}
#e n d r e g i o n
#r e g i o n Metodi p u b b l i c i
public void Listen ( )
{
h o s t = new S e r v i c e H o s t ( t h i s ) ;
h o s t . Open ( ) ;
}
public void Close ( )
{
host . Close () ;
}
#e n d r e g i o n
#r e g i o n P r o p r i e t à
p u b l i c GRIMDStatus S t a t u s
{
set
{
status = value ;
}
}
#e n d r e g i o n
}
p u b l i c c l a s s GRIMDStatus
{
#r e g i o n V a r i a b i l i d ’ i s t a n z a
p r i v a t e i n t numberOfSlave , a c t i v e S l a v e ,
l o s t S l a v e , MFFAQueue ;
p r i v a t e i n t t o t a l J o b s , completedJobs ,
s l a v e L o s s C o u n t , workToReassign ;
#e n d r e g i o n
#r e g i o n P r o p r i e t à
p u b l i c i n t SlaveLossCount
35
APPENDICE A. APPENDICE
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
{
get { return slaveLossCount ; }
set { slaveLossCount = value ; }
}
p u b l i c i n t WorkToReassign
{
g e t { r e t u r n workToReassign ; }
s e t { workToReassign = v a l u e ; }
}
p u b l i c i n t CompletedJobs
{
get { return completedJobs ; }
s e t { completedJobs = value ; }
}
public i n t TotalJobs
{
get { return totalJobs ; }
set { totalJobs = value ; }
}
p u b l i c i n t MFFAQueue
{
g e t { r e t u r n MFFAQueue ; }
s e t { MFFAQueue = v a l u e ; }
}
public int LostSlave
{
get { return l o s t S l a v e ; }
set { l o s t S l a v e = value ; }
}
public int ActiveSlave
{
get { return active Slave ; }
set { a c t i v e S l a v e = value ; }
}
p u b l i c i n t NumberOfSlave
{
g e t { r e t u r n numberOfSlave ; }
s e t { numberOfSlave = v a l u e ; }
}
#e n d r e g i o n
}
36
APPENDICE A. APPENDICE
37
112 }
A.2
A.2.1
Servizio di coda
IMasterQueue
1 namespace Q u e u e H a n d l e r I n t e r f a c e L i b
2 {
3
[ ServiceContract ]
4
p u b l i c i n t e r f a c e IMasterQueue
5
{
6
[ O p e r a t i o n C o n t r a c t ( IsOneWay = f a l s e ) ]
7
Workset IsUserInQueue ( S t r i n g username , out i n t
positionInQueue ) ;
8
9
[ O p e r a t i o n C o n t r a c t ( IsOneWay = f a l s e ) ]
10
v o i d Enqueue ( S t r i n g u s e r , S t r i n g macroFileName ,
I n t 1 6 s c h e d u l e r , S t r i n g computation , S t r i n g
workName ) ;
11
12
[ O p e r a t i o n C o n t r a c t ( IsOneWay = f a l s e ) ]
13
v o i d RemoveFromQueue ( S t r i n g u s e r ) ;
14
15
[ O p e r a t i o n C o n t r a c t ( IsOneWay = f a l s e ) ]
16
v o i d MoveTo ( S t r i n g u s e r , I n t 1 6 newIndex ) ;
17
18
[ O p e r a t i o n C o n t r a c t ( IsOneWay = f a l s e ) ]
19
Workset GetNextWorkset ( ) ;
20
21
[ O p e r a t i o n C o n t r a c t ( IsOneWay = f a l s e ) ]
22
v o i d RemoveCurrentWorkset ( ) ;
23
24
[ O p e r a t i o n C o n t r a c t ( IsOneWay = f a l s e ) ]
25
v o i d RemoveWorkset ( i n t i d ) ;
26
27
[ O p e r a t i o n C o n t r a c t ( IsOneWay = t r u e ) ]
28
v o i d StartDump ( Workset w, S t r i n g arg1 , S t r i n g a r g 2 )
;
29
30
[ O p e r a t i o n C o n t r a c t ( IsOneWay = t r u e ) ]
31
v o i d Shutdown ( ) ;
32
}
33 }
A.2.2
MasterQueue
1 namespace Q u e u e H a n d l e r I n t e r f a c e L i b
APPENDICE A. APPENDICE
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
38
[ S e r v i c e B e h a v i o r ( InstanceContextMode =
InstanceContextMode . P e r C a l l ) ]
p u b l i c c l a s s MasterQueue : IMasterQueue
{
#r e g i o n V a r i a b i l i d ’ i s t a n z a
p r i v a t e QueueHandler queue ;
private ServiceHost host ;
#e n d r e g i o n
#r e g i o n C o s t r u t t o r e
p u b l i c MasterQueue ( )
{
queue = new QueueHandler ( ) ;
}
#e n d r e g i o n
#r e g i o n Implementazione i n t e r f a c c i a
p u b l i c Workset IsUserInQueue ( s t r i n g username , out
int positionInQueue )
{
r e t u r n queue . GetUserWorkset ( username , out
positionInQueue ) ;
}
p u b l i c v o i d Enqueue ( S t r i n g u s e r , S t r i n g
remoteFileName , I n t 1 6 s c h e d u l e r , S t r i n g
computation , S t r i n g workName )
{
Configuration c o n f i g = ConfigurationManager .
OpenExeConfiguration ( C o n f i g u r a t i o n U s e r L e v e l .
None ) ;
WebClient c l i e n t = new WebClient ( ) ;
S t r i n g newDir = c o n f i g . A p p S e t t i n g s . S e t t i n g s [ ”
W o r k s e t R e p o s i t o r y ” ] . Value + remoteFileName +
” \\ ” ;
S t r i n g URIWorkset = c o n f i g . A p p S e t t i n g s . S e t t i n g s
[ ” URIWorksetBaseAddress ” ] . Value +
remoteFileName + ” . z i p ” ;
S t r i n g saveTo = c o n f i g . A p p S e t t i n g s . S e t t i n g s [ ”
W o r k s e t R e p o s i t o r y ” ] . Value + remoteFileName +
” . zip ” ;
APPENDICE A. APPENDICE
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
39
c l i e n t . DownloadFile ( URIWorkset , saveTo ) ;
D i r e c t o r y . C r e a t e D i r e c t o r y ( newDir ) ;
Z i p F i l e w o r k s e t Z i p = new Z i p F i l e ( saveTo ) ;
w o r k s e t Z i p . E x t r a c t A l l ( newDir ) ;
queue . Enqueue ( u s e r , remoteFileName , s c h e d u l e r ,
computation , workName ) ;
}
[ O b s o l e t e ( ” Use RemoveWorkset” ) ]
p u b l i c v o i d RemoveFromQueue ( S t r i n g u s e r )
{
queue . RemoveUser ( u s e r ) ;
}
p u b l i c v o i d RemoveWorkset ( i n t i d )
{
queue . RemoveWorkset ( i d ) ;
}
p u b l i c v o i d MoveTo ( S t r i n g u s e r , s h o r t newIndex )
{
queue . MoveTo ( u s e r , newIndex ) ;
}
p u b l i c Workset GetNextWorkset ( )
{
r e t u r n queue . GetNextWorkset ( ) ;
}
p u b l i c v o i d RemoveCurrentWorkset ( )
{
queue . RemoveCurrentWorkset ( ) ;
}
p u b l i c v o i d StartDump ( Workset w, s t r i n g arg1 ,
s t r i n g arg2 )
{
Configuration c o n f i g = ConfigurationManager .
OpenExeConfiguration ( C o n f i g u r a t i o n U s e r L e v e l .
None ) ;
S t r i n g baseDir = c o n f i g . AppSettings . S e t t i n g s [ ”
W o r k s e t R e p o s i t o r y ” ] . Value ;
P r o c e s s dump = new P r o c e s s ( ) ;
dump . S t a r t I n f o . FileName = b a s e D i r + ” . . \ \ gdump .
exe ” ;
APPENDICE A. APPENDICE
81
82
83
dump . S t a r t I n f o . R ed ir e ct S ta n da rd O ut pu t = t r u e ;
dump . S t a r t I n f o . U s e S h e l l E x e c u t e = f a l s e ;
dump . S t a r t I n f o . Arguments = a r g 1 + ” ” + a r g 2 +
” / createzip ” ;
dump . S t a r t ( ) ;
dump . WaitForExit ( ) ;
84
85
86
87
88
MailMessage message = new MailMessage ( ) ;
message . From = new MailAddress ( ” noreply@yadamp .
u n i s a . i t ” , ”GRIMD S e r v i c e ” ) ;
message . To . Add( new MailAddress (w . a s p n e t U s e r s .
aspnet Membership . LoweredEmail ) ) ;
89
90
91
92
93
94
95
CreateMessage ( message ) ;
ContentType c t = new ContentType ( ) ;
c t . MediaType = MediaTypeNames . Text . P l a i n ;
c t . Name = ” dumplog ” + w . ID + ” ” + DateTime . Now
. T o S t r i n g ( ”ddMMMyyyy” ) + ” . l o g ” ;
Attachment l o g = new Attachment (dump .
StandardOutput . BaseStream , c t ) ;
message . Attachments . Add( l o g ) ;
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
40
SmtpClient c l i e n t = new SmtpClient ( ” 1 2 7 . 0 . 0 . 1 ” )
;
c l i e n t . Send ( message ) ;
}
p u b l i c v o i d Shutdown ( )
{
Environment . E x i t ( 0 ) ;
}
#e n d r e g i o n
#r e g i o n Metodi P u b b l i c i
public void Listen ( )
{
h o s t = new S e r v i c e H o s t ( t y p e o f ( MasterQueue ) ) ;
h o s t . Open ( ) ;
}
public void Close ( )
{
host . Close () ;
}
#e n d r e g i o n
APPENDICE A. APPENDICE
125
126
127 }
41
}
A.2.3
QueueHandler
1 namespace Q u e u e H a n d l e r I n t e r f a c e L i b
2 {
3
c l a s s QueueHandler
4
{
5
#r e g i o n V a r i a b i l i d ’ i s t a n z a
6
7
p r i v a t e GRIMDEntities db = new GRIMDEntities ( ) ;
8
9
#e n d r e g i o n
10
11
#r e g i o n Metodi P r i v a t i
12
13
p r i v a t e Boolean SecondaryEnqueue ( a s p n e t U s e r s
u t e n t e , S t r i n g pathName , I n t 1 6 s c h e d u l e r , S t r i n g
computation , S t r i n g workName )
14
{
15
try
16
{
17
// Crea i l nuovo w o r k s e t e l o a g g i u n g e a l
db
18
Workset w o r k s e t = new Workset ( ) ;
19
w o r k s e t . PathName = pathName ;
20
workset . UserId = utente . UserId ;
21
workset . Scheduler = s ch e du le r ;
22
w o r k s e t . Computation = computation ;
23
w o r k s e t . WorkName = workName ;
24
25
db . Workset . AddObject ( w o r k s e t ) ;
26
db . SaveChanges ( ) ;
27
28
SecondaryQueue queue = new SecondaryQueue ( )
;
29
queue . IDUser = u t e n t e . U s e r I d ;
30
queue . IDWorkset = w o r k s e t . ID ;
31
32
db . SecondaryQueue . AddObject ( queue ) ;
33
db . SaveChanges ( ) ;
34
35
return true ;
36
}
37
catch ( Exception )
38
{
39
return f a l s e ;
40
}
APPENDICE A. APPENDICE
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
42
}
p r i v a t e v o i d MoveToPrimaryQueue ( Guid uid , Queue
queue , i n t p o s i t i o n )
{
SecondaryQueue nextUserWork = db . SecondaryQueue
. F i r s t O r D e f a u l t ( p => p . IDUser . Equals ( u i d ) ) ;
queue . IDWorkset = nextUserWork . IDWorkset ;
db . SecondaryQueue . D e l e t e O b j e c t ( nextUserWork ) ;
db . Workset . D e l e t e O b j e c t ( nextUserWork . Workset ) ;
db . SaveChanges ( ) ;
}
p u b l i c Boolean I s U se r I nS e c o nd a ry Q u eu e ( S t r i n g u s e r )
{
// V e r i f i c a che l ’ u t e n t e s i a p r e s e n t e n e l db
a s p n e t U s e r s u t e n t e = db . a s p n e t U s e r s .
S i n g l e O r D e f a u l t ( p => p . UserName == u s e r ) ;
i f ( u t e n t e == n u l l ) r e t u r n f a l s e ;
// V e r i f i c a che l ’ u t e n t e s i a p r e s e n t e i n Coda
SecondaryQueue utenteInCoda = db . SecondaryQueue
. S i n g l e ( p => p . IDUser == u t e n t e . U s e r I d ) ;
r e t u r n ( utenteInCoda != n u l l ) ;
}
p u b l i c Boolean IsWorksetInQueue ( i n t i d )
{
// V e r i f i c a che i l w o r k s e t s i a p r e s e n t e n e l db
Queue queue = db . Queue . S i n g l e O r D e f a u l t ( q => q .
IDWorkset == i d ) ;
i f ( queue == n u l l ) r e t u r n f a l s e ;
e l s e return true ;
}
p u b l i c Boolean IsWorksetInSecondaryQueue ( i n t i d )
{
// V e r i f i c a che i l w o r k s e t s i a p r e s e n t e n e l db
SecondaryQueue queue = db . SecondaryQueue .
S i n g l e O r D e f a u l t ( q => q . IDWorkset == i d ) ;
i f ( queue == n u l l ) r e t u r n f a l s e ;
e l s e return true ;
}
#e n d r e g i o n
#r e g i o n Metodi p u b b l i c i
APPENDICE A. APPENDICE
84
85
86
87
88
89
90
91
p u b l i c Boolean Enqueue ( S t r i n g u s e r , S t r i n g
macroFileName , I n t 1 6 s c h e d u l e r , S t r i n g
computation , S t r i n g workName )
{
a s p n e t U s e r s u t e n t e = db . a s p n e t U s e r s .
S i n g l e O r D e f a u l t ( p => p . UserName == u s e r ) ;
// Se l ’ u t e n t e non e s i s t e r e s t i t u i s c e s u b i t o ’
false ’
i f ( u t e n t e == n u l l ) r e t u r n f a l s e ;
// Se l ’ u t e n t e è i n coda l o i n s e r i s c o n e l l a
coda s e c o n d a r i a
i f ( IsUserInQueue ( u s e r ) ) r e t u r n
SecondaryEnqueue ( u t e n t e , macroFileName ,
s c h e d u l e r , computation , workName ) ;
92
93
94
95
96
97
98
99
100
101
102
103
104
// Crea i l nuovo w o r k s e t e l o a g g i u n g e a l db
Workset w o r k s e t = new Workset ( ) ;
w o r k s e t . PathName = macroFileName ;
workset . UserId = utente . UserId ;
workset . Scheduler = s ch ed u le r ;
w o r k s e t . Computation = computation ;
w o r k s e t . WorkName = workName ;
db . Workset . AddObject ( w o r k s e t ) ;
// Recupera d a l db l a p o s i z i o n e d e l l ’ u l t i m o
e l e m e n t o i n coda
var queues = ( from q i n db . Queue s e l e c t q .
Position ) ;
105
106
107
108
i n t newPosition = 1 ;
i f ( queues != n u l l && queues . Count ( ) > 0 )
n e w P o s i t i o n = queues . Max ( ) + 1 ;
109
110
111
112
113
114
115
116
117
118
119
120
121
122
43
// Crea l a t u p l a da i n s e r i r e n e l l a t a b e l l a
Queue e l a i n s e r i s c e
Queue queue = new Queue ( ) ;
queue . P o s i t i o n = n e w P o s i t i o n ;
queue . IDWorkset = w o r k s e t . ID ;
queue . IDUser = u t e n t e . U s e r I d ;
db . Queue . AddObject ( queue ) ;
db . SaveChanges ( ) ;
return true ;
}
p u b l i c Workset GetNextWorkset ( )
APPENDICE A. APPENDICE
123
124
{
// Se c ’ è un w o r k s e t a l p o s t o 0 v i e n e
restituito
Queue e x e c u t i n g W o r k s e t = db . Queue .
S i n g l e O r D e f a u l t ( q => q . P o s i t i o n == 0 ) ;
125
126
127
i f ( e x e c u t i n g W o r k s e t != n u l l ) r e t u r n
e x e c u t i n g W o r k s e t . Workset ;
128
129
// S c a l a l a p o s i t i o n d i t u t t i g l i e l e m e n t i i n
coda d i una p o s i z i o n e
var r e s u l t = ( from q i n db . Queue s e l e c t q ) ;
130
131
132
133
134
135
136
137
138
139
f o r e a c h ( Queue q i n r e s u l t )
{
q . Position = q . Position − 1;
}
db . SaveChanges ( ) ;
// Recupera i l primo Workset i n coda e ne
a g g i o r n a i l campo ’ DateStart ’
Queue queueToReturn = db . Queue . S i n g l e O r D e f a u l t (
q => q . P o s i t i o n == 0 ) ;
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
44
i f ( queueToReturn == n u l l ) r e t u r n n u l l ;
Workset c u r r e n t W o r k s e t = queueToReturn . Workset ;
c u r r e n t W o r k s e t . D a t e S t a r t = DateTime . Now ;
db . SaveChanges ( ) ;
r e t u r n queueToReturn . Workset ;
}
p u b l i c Boolean IsUserInQueue ( S t r i n g u s e r )
{
// V e r i f i c a che l ’ u t e n t e s i a p r e s e n t e n e l db
a s p n e t U s e r s u t e n t e = db . a s p n e t U s e r s .
S i n g l e O r D e f a u l t ( p => p . UserName == u s e r ) ;
i f ( u t e n t e == n u l l ) r e t u r n f a l s e ;
// V e r i f i c a che l ’ u t e n t e s i a p r e s e n t e i n Coda
Queue utenteInCoda = db . Queue . S i n g l e O r D e f a u l t ( p
=> p . IDUser == u t e n t e . U s e r I d ) ;
r e t u r n ( utenteInCoda != n u l l ) ;
}
p u b l i c Workset GetUserWorkset ( S t r i n g u s e r , out i n t
position )
APPENDICE A. APPENDICE
164
165
{
// Recupera l a t u p l a d e l l a t a b e l l a Queue che
r i g u a r d a l ’ u t e n t e dato
a s p n e t U s e r s u t e n t e = db . a s p n e t U s e r s .
S i n g l e O r D e f a u l t ( p => p . UserName == u s e r ) ;
Queue userQueue = db . Queue . S i n g l e O r D e f a u l t ( p =>
p . IDUser == u t e n t e . U s e r I d ) ;
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
45
// Se l ’ u t e n t e non è i n coda
i f ( userQueue == n u l l )
{
p o s i t i o n = −1;
return null ;
}
e l s e // Se l ’ u t e n t e è i n coda ( o i n e s e c u z i o n e )
{
p o s i t i o n = userQueue . P o s i t i o n ;
r e t u r n userQueue . Workset ;
}
}
p u b l i c v o i d RemoveCurrentWorkset ( )
{
Queue c u r r e n t = db . Queue . S i n g l e O r D e f a u l t ( q => q
. P o s i t i o n == 0 ) ;
c u r r e n t . Workset . DateEnd = DateTime . Now ;
S t r i n g username = c u r r e n t . a s p n e t U s e r s . UserName
;
Guid u i d = c u r r e n t . a s p n e t U s e r s . U s e r I d ;
db . Queue . D e l e t e O b j e c t ( c u r r e n t ) ;
db . SaveChanges ( ) ;
194
// Recupero i l p r o s s i m o w o r k s e t d e l l ’ u t e n t e
d a l l a coda s e c o n d a r i a
SecondaryQueue nextUserWork = db . SecondaryQueue
. F i r s t O r D e f a u l t ( p => p . IDUser . Equals ( u i d ) ) ;
195
196
197
198
i f ( nextUserWork == n u l l ) r e t u r n ;
199
200
201
202
203
204
// S p o s t o un e l e m e n t o d a l l a s e c o n d a r y queue
a l l a coda p r i n c i p a l e
Queue newQueue = new Queue ( ) ;
newQueue . IDWorkset = nextUserWork . IDWorkset ;
newQueue . IDUser = nextUserWork . IDUser ;
// Recupera d a l db l a p o s i z i o n e d e l l ’ u l t i m o
e l e m e n t o i n coda
var queues = ( from q i n db . Queue s e l e c t q .
APPENDICE A. APPENDICE
46
Position ) ;
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
i n t newPosition = 1 ;
i f ( queues != n u l l && queues . Count ( ) > 0 )
n e w P o s i t i o n = queues . Max ( ) + 1 ;
newQueue . P o s i t i o n = n e w P o s i t i o n ;
db . Queue . AddObject ( newQueue ) ;
db . SecondaryQueue . D e l e t e O b j e c t ( nextUserWork ) ;
db . SaveChanges ( ) ;
}
p u b l i c v o i d RemoveUser ( S t r i n g u s e r )
{
// Recupera l a p o s i z i o n e d e l l ’ u t e n t e i n coda ed
elimina la tupla corrispondente dalla
t a b e l l a Queue
a s p n e t U s e r s u t e n t e = db . a s p n e t U s e r s .
S i n g l e O r D e f a u l t ( p => p . UserName == u s e r ) ;
Queue userQueue = db . Queue . S i n g l e O r D e f a u l t ( p =>
p . IDUser == u t e n t e . U s e r I d ) ;
I n t 3 2 p o s i t i o n = userQueue . P o s i t i o n ;
i f ( p o s i t i o n == 0 ) r e t u r n ;
// Se un u t e n t e è i n coda s e c o n d a r i a s p o s t o i l
prossimo workset a l l a p o s i z i o n e c o r r e n t e
i f ( I sU s e r In S e co n d ar y Q ue u e ( u t e n t e . UserName ) )
{
MoveToPrimaryQueue ( u t e n t e . UserId , userQueue
, position ) ;
return ;
}
db . Queue . D e l e t e O b j e c t ( userQueue ) ;
db . SaveChanges ( ) ;
// S c a l a d i una p o s i z i o n e g l i u t e n t i i n coda
n e l l e p o s i z i o n i su cc es s iv e all ’ utente
rimosso
var q u e r y R e s u l t = ( from q i n db . Queue where q .
Position > position select q) ;
f o r e a c h ( Queue q i n q u e r y R e s u l t )
{
q . Position = q . Position − 1;
}
db . SaveChanges ( ) ;
APPENDICE A. APPENDICE
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
47
}
p u b l i c v o i d RemoveWorkset ( i n t i d )
{
// Recupero i l w o r k s e t
Workset w o r k s e t = db . Workset . S i n g l e O r D e f a u l t (w
=> w . ID == i d ) ;
i f ( IsWorksetInQueue ( w o r k s e t . ID ) )
{
// Caso1 : Workset i n coda p r i m a r i a
RemoveUser ( w o r k s e t . a s p n e t U s e r s . UserName ) ;
}
else
{
// Caso2 : Workset i n coda s e c o n d a r i a
db . Workset . D e l e t e O b j e c t ( w o r k s e t ) ;
db . SaveChanges ( ) ;
}
}
p u b l i c v o i d MoveTo ( S t r i n g u s e r , I n t 1 6 newIndex )
{
// Recupera l a p o s i z i o n e d e l l ’ u t e n t e i n coda
a s p n e t U s e r s u t e n t e = db . a s p n e t U s e r s .
S i n g l e O r D e f a u l t ( p => p . UserName == u s e r ) ;
Queue userQueue = db . Queue . S i n g l e O r D e f a u l t ( p =>
p . IDUser == u t e n t e . U s e r I d ) ;
I n t 3 2 p o s i t i o n = userQueue . P o s i t i o n ;
// C o n t r o l l a che i l nuovo i n d i c e s i a minore d e l l
’ u l t i m o i n d i c e i n coda e maggiore d i 0
var queues = ( from q i n db . Queue s e l e c t q .
Position ) ;
i f ( queues != n u l l && queues . Count ( ) == 0 )
return ;
i n t l a s t P o s i t i o n = queues . Max ( ) ;
i f ( newIndex > l a s t P o s i t i o n ) newIndex = Convert
. ToInt16 ( l a s t P o s i t i o n ) ;
i f ( newIndex < 1 ) newIndex = 1 ;
// Assegna a l l ’ u t e n t e dato i l p o s t o dato
userQueue . P o s i t i o n = newIndex ;
db . SaveChanges ( ) ;
// Recupera g l i u t e n t i i n coda d a l l a nuova
posizione dell ’ utente e riassegna l e
APPENDICE A. APPENDICE
48
p o s i z i o n i in ordine crescente
284
285
286
287
i f ( newIndex < p o s i t i o n )
{
var q u e r y R e s u l t = ( from q i n db . Queue where
( q . P o s i t i o n >= newIndex && q . IDUser !=
utente . UserId ) orderby q . P o s i t i o n s e l e c t
q) ;
I n t 3 2 s t a r t P o s = newIndex + 1 ;
288
289
290
291
292
293
294
295
296
297
298
f o r e a c h ( Queue q i n q u e r y R e s u l t )
{
q . Position = startPos ;
s t a r t P o s ++;
}
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315 }
}
e l s e i f ( newIndex > p o s i t i o n )
{
var q u e r y R e s u l t = ( from q i n db . Queue where
( q . P o s i t i o n > p o s i t i o n && q . P o s i t i o n <=
newIndex && q . IDUser != u t e n t e . U s e r I d )
orderby q . P o s i t i o n s e l e c t q ) ;
Int32 startPos = p o s i t i o n ;
f o r e a c h ( Queue q i n q u e r y R e s u l t )
{
q . Position = startPos ;
s t a r t P o s ++;
}
}
e l s e i f ( newIndex == p o s i t i o n ) r e t u r n ;
db . SaveChanges ( ) ;
}
#e n d r e g i o n
}
A.3
A.3.1
Servizio identificazione slave
IVPNIDResolver
1 namespace VPNIDResolverLib
2 {
3
[ ServiceContract ]
APPENDICE A. APPENDICE
4
5
6
7
49
p u b l i c i n t e r f a c e IVPNIDResolver
{
[ O p e r a t i o n C o n t r a c t ( IsOneWay = f a l s e ) ]
Guid GetNewID ( S t r i n g os , S t r i n g machineName , s h o r t
coreNum ) ;
8
9
10
11
12
13
14
15
16
17
18
19
20
21 }
[ O p e r a t i o n C o n t r a c t ( IsOneWay = f a l s e ) ]
Boolean Update ( Guid myGuid ) ;
[ O p e r a t i o n C o n t r a c t ( IsOneWay = f a l s e ) ]
v o i d S e t O f f l i n e ( Guid myGuid ) ;
[ O p e r a t i o n C o n t r a c t ( IsOneWay = f a l s e ) ]
S l a v e s GetSlaveByID ( Guid g u i d ) ;
[ O p e r a t i o n C o n t r a c t ( IsOneWay = f a l s e ) ]
L i s t <S t r i n g > g e t A v a i l a b l e S l a v e s L i s t ( ) ;
}
A.3.2
VPNIDResolver
1 namespace VPNIDResolverLib
2 {
3
[ S e r v i c e B e h a v i o r ( InstanceContextMode =
InstanceContextMode . S i n g l e ) ]
4
p u b l i c c l a s s VPNIDResolver : IVPNIDResolver
5
{
6
#r e g i o n V a r i a b i l i d ’ i s t a n z a
7
8
p r i v a t e GRIMDEntities db ;
9
private ServiceHost host ;
10
p r i v a t e L i s t <S l a v e O b j e c t > s l a v e L i s t = new L i s t <
S l a v e O b j e c t >() ;
11
private s t a t i c Configuration config =
C o n f i g u r a t i o n M a n a g e r . OpenExeConfiguration (
C o n f i g u r a t i o n U s e r L e v e l . None ) ;
12
13
#e n d r e g i o n
14
15
#r e g i o n C o s t r u t t o r e
16
17
p u b l i c VPNIDResolver ( )
18
{
19
db = new GRIMDEntities ( ) ;
20
21
var s l a v e s = ( from s i n db . S l a v e s where s .
I s O n l i n e == t r u e s e l e c t s ) ;
22
APPENDICE A. APPENDICE
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
50
foreach ( Slaves slave in slaves )
{
a d d S l a v e T o L i s t ( new S l a v e O b j e c t ( s l a v e . IP ,
s l a v e . Port . T o S t r i n g ( ) , ” \\\\ ” + s l a v e . IP
+ ” \\ y d f s ” , ” \\\\ ” + s l a v e . IP + ” \\ temp
” , s l a v e . Username , s l a v e . Password , s l a v e
. SlaveID ) ) ;
}
}
#e n d r e g i o n
#r e g i o n Implementazione i n t e r f a c c i a
p u b l i c Guid GetNewID ( S t r i n g os , S t r i n g machineName ,
s h o r t coreNum )
{
S l a v e s s l a v e = new S l a v e s ( ) ;
s l a v e . SlaveID = Guid . NewGuid ( ) ;
s l a v e . IP = getRemoteIP ( ) ;
slave . IsOnline = true ;
s l a v e . MachineName = machineName ;
s l a v e . OSVersion = o s ;
s l a v e . CoreNumber = coreNum ;
s l a v e . Port = Convert . ToInt32 ( c o n f i g . A p p S e t t i n g s
. S e t t i n g s [ ” D e f a u l t P o r t ” ] . Value ) ;
s l a v e . Username = c o n f i g . A p p S e t t i n g s . S e t t i n g s [ ”
DefaultUsername ” ] . Value ;
s l a v e . Password = c o n f i g . A p p S e t t i n g s . S e t t i n g s [ ”
D e f a u l t P a s s w o r d ” ] . Value ;
s l a v e . LastUpdate = DateTime . Now ;
try
{
db . S l a v e s . AddObject ( s l a v e ) ;
db . SaveChanges ( ) ;
a d d S l a v e T o L i s t ( new S l a v e O b j e c t ( s l a v e . IP ,
s l a v e . Port . T o S t r i n g ( ) , ” \\\\ ” + s l a v e . IP
+ ” \\ y d f s ” , ” \\\\ ” + s l a v e . IP + ” \\ temp
” , s l a v e . Username , s l a v e . Password , s l a v e
. SlaveID ) ) ;
r e t u r n s l a v e . SlaveID ;
}
catch ( Exception )
{
r e t u r n Guid . Empty ;
APPENDICE A. APPENDICE
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
51
}
}
p u b l i c b o o l Update ( Guid myGuid )
{
S l a v e s s l a v e = db . S l a v e s . S i n g l e O r D e f a u l t ( p => p
. SlaveID . Equals ( myGuid ) ) ;
try
{
s l a v e . IP = getRemoteIP ( ) ;
slave . IsOnline = true ;
s l a v e . LastUpdate = DateTime . Now ;
db . SaveChanges ( ) ;
a d d S l a v e T o L i s t ( new S l a v e O b j e c t ( s l a v e . IP ,
s l a v e . Port . T o S t r i n g ( ) , ” \\\\ ” + s l a v e . IP
+ ” \\ y d f s ” , ” \\\\ ” + s l a v e . IP + ” \\ temp
” , s l a v e . Username , s l a v e . Password , s l a v e
. SlaveID ) ) ;
return true ;
}
catch ( Exception )
{
return f a l s e ;
}
}
p u b l i c v o i d S e t O f f l i n e ( Guid myGuid )
{
S l a v e s s l a v e = db . S l a v e s . S i n g l e O r D e f a u l t ( p => p
. SlaveID . Equals ( myGuid ) ) ;
slave . IsOnline = f a l s e ;
db . SaveChanges ( ) ;
}
p u b l i c S l a v e s GetSlaveByID ( Guid g u i d )
{
S l a v e s s l a v e = db . S l a v e s . S i n g l e O r D e f a u l t ( p => p
. SlaveID . Equals ( g u i d ) ) ;
return slave ;
}
p u b l i c L i s t <S t r i n g > g e t A v a i l a b l e S l a v e s L i s t ( )
{
L i s t <S t r i n g > toReturn = new L i s t <s t r i n g >() ;
foreach ( SlaveObject s in s l a v e L i s t )
APPENDICE A. APPENDICE
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
52
{
toReturn . Add( S l a v e T o S t r i n g ( s ) ) ;
}
r e t u r n toReturn ;
}
#e n d r e g i o n
#r e g i o n Metodi p r i v a t i
p r i v a t e S t r i n g getRemoteIP ( )
{
OperationContext c o n t e x t = OperationContext .
Current ;
MessageProperties messageProperties = context .
IncomingMessageProperties ;
RemoteEndpointMessageProperty e n d p o i n t P r o p e r t y
= messageProperties [
RemoteEndpointMessageProperty . Name ] a s
RemoteEndpointMessageProperty ;
r e t u r n e n d p o i n t P r o p e r t y . Address ;
}
p r i v a t e i n t getRemotePort ( )
{
OperationContext c o n t e x t = OperationContext .
Current ;
MessageProperties messageProperties = context .
IncomingMessageProperties ;
RemoteEndpointMessageProperty e n d p o i n t P r o p e r t y
= messageProperties [
RemoteEndpointMessageProperty . Name ] a s
RemoteEndpointMessageProperty ;
r e t u r n e n d p o i n t P r o p e r t y . Port ;
}
p r i v a t e void addSlaveToList ( SlaveObject s l a v e )
{
removeSlaveFromList ( s l a v e . SlaveID ) ;
s l a v e L i s t . Add( s l a v e ) ;
}
p r i v a t e v o i d removeSlaveFromList ( Guid SlaveID )
{
S l a v e O b j e c t toRemove = n u l l ;
foreach ( SlaveObject s in s l a v e L i s t )
{
i f ( s . SlaveID . Equals ( SlaveID ) )
APPENDICE A. APPENDICE
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
53
{
toRemove = s ;
break ;
}
}
s l a v e L i s t . Remove ( toRemove ) ;
}
private String SlaveToString ( SlaveObject s )
{
r e t u r n ( s . sIPAddress + ” ∗” + s . s I P P o r t + ” ∗ ” +
s . DFSPath + ”∗ ” + s . UNC Username + ” | ” + s .
UNC Password + ” ∗” + s . SlaveID ) . R e pl a ce ( ” : : 1
” , ” 127.0.0.1 ”) ;
}
#e n d r e g i o n
#r e g i o n Metodi P u b b l i c i
public void Listen ( )
{
h o s t = new S e r v i c e H o s t ( t h i s ) ;
h o s t . Open ( ) ;
}
public void Close ( )
{
host . Close () ;
}
#e n d r e g i o n
#r e g i o n Metodi S t a t i c i
p u b l i c s t a t i c L i s t <S l a v e O b j e c t > g e t S l a v e s O b j e c t L i s t
( L i s t <S t r i n g > l i s t a )
{
L i s t <S l a v e O b j e c t > toReturn = new L i s t <
S l a v e O b j e c t >() ;
foreach ( String s in l i s t a )
{
toReturn . Add( new S l a v e O b j e c t ( s . T o S t r i n g ( ) ) )
;
}
r e t u r n toReturn ;
}
APPENDICE A. APPENDICE
185
186
187 }
#e n d r e g i o n
}
54