Realizzazione di una biglietteria per lo stadio Olimpico in C

Progetto programmazione concorrente

olimpico


DOWNLOAD PROGETTO


La seguente tesina risolve il problema della gestione di una biglietteria online per la prenotazione dei posti per assistere ad una partita che si giocherà presso lo Stadio Olimpico di Roma.
Il problema della gestione della biglietteria è il seguente: ciascun utente (il client) indica il numero del settore in cui intende prenotare i biglietti e il numero di posti consecutivi desiderati. Occorre ottenere un buon grado di parallellismo evitando le interferenze nelle prenotazioni e le attese attive.
Sono sufficienti i seguenti flussi di esecuzione per il server:
  • un flusso primario P che inizializza il server, le socket e che accetta connessioni dal client
  • un flusso C (thread) per ogni client che si connette al server, con il compito di gestire la prenotazione di quel client. Ciascun flusso C è creato da P nonappena questo riceve una nuova connessione da parte di un client.
L'header "stadioOlimpico.h" modella lo stadio, composto da 9 settori, ciascuno caratterizzato da un certo numero di file con un certo numero di posti. Lo stadio è dunque un array di strutture che modellano i settori. Le strutture che rappresentano il settore e le file contengono i mutex per aggiornare la struttura in mutua esclusione. Tali mutex sono definiti di tipo errorChecking.
//settore dello stadio
struct settore{
   int codice;
   char nome[64];
   int nFile;
   struct fila* file;
   int postiDisponibili;
   int costoIntero;
   pthread_mutex_t mx_aggiornamentoSettore;
};

L'algoritmo di prenotazione (presente nel file "gestioneStadio.c") non si occupa di determinare i posti nella posizione migliore (in genere quelli più centrali), ma controlla se esiste una fila con un numero di posti consecutivi liberi pari a quelli richiesti, fermandosi alla prima occorrenza. Prende in input il numero del settore e il numero n di posti adiacenti richiesti. Appena trova un posto libero in una fila del settore specificato dall'utente, verifica che ci siano n-1 posti adiacenti accanto; se ci sono prenota tutto, altrimenti va avanti. Dopo aver scorso tutte le file, se non trova n posti adiacenti ritorna con esito negativo, altrimenti effettua la prenotazione.
Il file "server.c" modella il server che gestisce le prenotazioni. Il dialogo fra client e server è realizzato mediante socket; al momento dell'avvio il server delega al cinema la sua inizializzazione e poi si mette in ascolto su una porta usando una socket di ascolto. Ogni volta che client si connette, il server estrae la connessione dalla coda della sua socket e lancia un thread che gestisce il dialogo fra il server e il client appena estratto, consentendo al flusso di esecuzione principale di continuare ad estrarre altre connessioni dalla coda. I thread creati in questo modo sono di tipo DETACHED, cioè alla loro terminazione rilasciano tutte le risorse senza dover effettuare su di essi una join (che per giunta non sarebbe permessa).
Il server riceve le informazioni dal client, ne valuta la correttezza ed effettua la prenotazione. Ogni accesso del server a campi delle strutture che modellano lo stadio che possono essere oggetto di modifiche concorrenti da parte di altri thread è protetto con un lock esclusivo sulla struttura.
All'inizio della comunicazione col client e dopo ogni prenotazione effettuata, il server invia al client le informazioni di riepilogo sulla situazione dei posti disponibili nei settori dello stadio: una situazione che può verificarsi è quella in cui due o più client stanno osservando la stessa vista (cioè la stessa situazione di disponibilità dei posti nei settori dello stadio) e un client effettua una prenotazione; se questa prenotazione esaurisce i poti nel settore e l'altro client effettua una prenotazione sullo stesso settore, allora gli sarà comunicato che i posti sono esauriti, nonostante l'ultimo aggiornamento gli avesse comunicato la disponibilità di posti in quel settore.
  • Codice: 1, Curva Sud, posti liberi: 1050, prezzo: 20, posti fila: 30
  • Codice: 2, Distinti Sud, posti liberi: 900, prezzo: 28, posti fila: 30
  • Codice: 3, Distinti Ovest, posti liberi: 900, prezzo: 28, posti fila: 30
  • Codice: 4, Tribuna Tevere, posti liberi: 2000, prezzo: 55, posti fila: 40
  • Codice: 5, Tribuna Monte Mario, posti liberi: 1750, prezzo: 90, posti fila: 35
  • Codice: 6, Tribuna d'Onore, posti liberi: 400, prezzo: 200, posti fila: 20
  • Codice: 7, Curva Nord, posti liberi: 1050, prezzo: 20, posti fila: 30
  • Codice: 8, Distinti Est, posti liberi: 900, prezzo: 28, posti fila: 30
  • Codice: 9, Distinti Nord, posti liberi: 900, prezzo: 28, posti fila: 30
Quando tutti i posti saranno esauriti, ovviamente il server non accetterà più prenotazioni (accetterà invece connessioni, rispondendo ad una prenotazione che i posti sono terminati).
Per quanto riguarda il client, questo è caratterizzato da diverse modalità di esecuzione. La modalità 0 è quella normale, in cui richiede l'input della prenotazione all'utente. La modalità 1 è quella di test concreto, in cui effettua una prenotazione di 20 posti in tribuna d'onore e termina. La modalità 2 è quella di test randomico, in cui effettua una prenotazione casuale e termina. Nella modalità normale, per interrompere la sessione senza prenotare basta inserire 0 o qualunque altro carattere non numerico.

Passiamo ora a descrivere i test. Il file "test.c" contiene due modalità di test: 0 indica la modalità con dati concreti e 1 randomica, dove questi test hanno lo stesso significato descritto per il client. Per avviare un test occorre specificare il numero di client che partecipano al test, un numero di porta, l'host e la modalità del test. Ovviamente l'esecuzione del main di questo file causa la partenza di n client, ma si presuppone che il server stia già in ascolto sulla porta usata dai client.

Infine, "testInit.c" rappresenta un test che visualizza il risultato dell'inizializzazione dello stadio, mostrando i settori e le file dei settori (non i posti per brevità dell'output mostrato). Inoltre effettua anche una prenotazione predefinita corretta e una in cui si indica un numero di posti adiacenti maggiori di quelli esistenti.