2022-06-08 12:33:03 +02:00
2022-03-11 12:05:38 +01:00
2022-06-08 12:33:03 +02:00
2022-03-11 12:03:59 +01:00
2022-03-11 12:03:59 +01:00
2022-05-20 19:34:54 +02:00
2022-05-19 21:32:44 +02:00
2022-04-29 00:15:56 +02:00
2022-05-20 19:36:07 +02:00
2022-05-03 23:14:39 +02:00
2022-03-08 17:26:13 +01:00
2022-05-19 21:32:44 +02:00
2022-05-20 19:53:43 +02:00

Introduzione

Il progetto realizzato consiste in un file storage gestito da un server multithreaded e un client che possono comunicarsi attraverso le funzioni implementate dall'API. Il codice è presente sulla repository privata al link: tautocrono.it.
Si può accedere usando le credenziali:

::: center Username Password


Guest     CNs7Vbx3vLJQ2aK

:::

Il progetto è compilato in modo automatico tramite makefile con i target: all, test1, test2, test3. Il target all fa partire un'altro sottoprocesso make che eseguirà il target multi con degli argomenti aggiuntivi, tipo -j in modo da rendere la compilazione multiprocesso. Ci sono anche i target clean e cleanall che rimuovono gli eseguibili creati con i precedenti target.

Sono inclusi anche dei file per testare le funzionalità del client e del server nella cartella testFiles.

Gli oggetti vengono creati nella directory obj/, mentre gli eseguibili vengono creati nella directory build/. La directory src/ contiene il codice che fa parte del main del server e del client; il resto del codice è contenuto nella directory lib/.

È stata implementata sia la politica di rimpiazzamento FIFO che la politica LRU.

Server

Il server prende come unico argomento il path al file di configurazione. Un esempio di file di configurazione è config.ini presente nella root del progetto. La struttura del file è analoga a quella di un file INI, quindi l'ordine degli argomenti dentro a sezione è irrilevante. Il file di configurazione viene letto da una libreria di "terza parte" ottenuta da rxi/ini. Si sarebbe potuto usare la libreria Glib tuttavia si è riscontrata una memory leak con valgrind.

La libreria threadpool e la libreria conn sono state tratte dalla soluzione dell'esercitazione 11 pubblicata sulla pagina del corso. Si è preferito l'utilizzo di strsep invece di strtok o strtok_r sia nel programma server che client. Il codice è stato adattato leggermente da quello presente nella libreria C GNU (strsep) in modo da utilizzare la funzione omonima su piattaforme BSD e MacOS.

Main

Il thread principale accetta le connessioni in arrivo da i client su un socket di tipo AF_UNIX con nome di default socket. Viene interrotto dal thread sighandler_thread se ricevuto un segnale fra: SIGHUP, SIGINT o SIGQUIT.

serverWorker

Il thread main dopo aver accettato la connessione di un client crea un thread "worker" che aggiunge alla threadpool (definita nei file omonimi). Ogni worker serve una singola richiesta da parte di un qualsiasi client connesso. Se le richieste contemporanee dei client fossero maggiori della dimensione della threadpool, le richieste vengono accodate in una pending queue di dimensione stabilita nel file di configurazione del server. La singola richiesta viene letta dal worker thread e viene poi eseguita la funzione associata alla richiesta presente nella libreria apiFile. Alcune di queste operazioni possono richiedere la presa di una lock associata a un file, quindi per gestire queste richieste si è fatto uso di una struttura di dati interna waiting_t. La richiesta accodata non è quindi gestita dal thread corrente, ma dal thread che rilascerà la lock al file associato. Si evitano quindi polling o l'utilizzo di condition.

sighandler_thread

Il thread gestisce i segnali in arrivo al server. Se il segnale ricevuto è di tipo SIGINT o SIGQUIT, il server termina prima possibile. Se il segnale ricevuto è del tipo SIGHUP invece si attende che ogni worker abbiano servito le richieste dei client precedentemente connessi.

Storage

Il server gestisce la memorizzazione dei file tramite la libreria fileQueue. Nel header file fileQueue.h la costante ALGORITHM imposta la politica di rimpiazzamento. Le funzioni che differiscono in comportamento sono: dequeueN, lockFileInQueue, unlockFileInQueue, openFileInQueue, find, request, searchFile. Infatti l'elemento che richiedono come input viene accodato alla fine della struttura nella politica LRU. Le altre funzioni invece non modificano l'ordine degli elementi.

La struttura principale è una linked list chiamata nodeT che contiene i dati del file associato e un puntatore al prossimo elemento. Dato che l'operazione di scrittura di un file in memoria non è atomica, si è deciso di usare due misure dell'occupazione della memoria di un file: size e valid. L'unico momento in cui potrebbero essere differenti è quando il client ha richiesto la scrittura di dati, comunicando la dimensione, quindi il server "alloca" tale dimensione come size, lasciando invariato la dimensione valid. Dopo che il client ha inviato i dati da inserire nel file, le dimensioni dovrebbero di nuovo combaciare. Una singola operazione di scrittura può richiedere più di un file rimosso per aver abbastanza memoria libera; questa operazione viene attuata atomicamente e viene considerata come un'unica operazione di rimpiazzamento.

Logging

Il server usa la libreria "taglialegna" per scrivere i messaggi di log su un file specificato nel file di configurazione. Le scritture vengono sincronizzate tramite lock. Sono state scritte due funzioni che permettono la scrittura: taglia_write, taglia_log. taglia_log scrive anche un timestamp prima del messaggio di log. All'inizio dell'esecuzione del server vengono stampate alcune informazioni lette dal file di configurazione, come ad esempio la dimensione del threadpool o la dimensione massima della struttura di cache del server. Al termine vengono invece scritti alcuni dati di sunto delle operazioni, ad esempio il numero massimo di file memorizzati o la dimensione massima raggiunta.

Client

Oltre alle funzioni di API richieste dalla specifica è stata implementata la funzione setDirectory, perchè si è interpretata come se le opzioni -d e -D dovessero poter essere associate a più di un comando. Tuttavia questa funzionalità non è presente nel client in modo diretto dato che vengono inserite -d/-D /dev/null fra due opzioni -w/-W o -r/-R successive. L'opzione -d /dev/null o -D /dev/null è stata ottimizzata leggermente in modo da non fare chiamate di sistema.
Il client esegue prima l'opzione -f, in seguito l'opzione -t, poi in ordine tutti gli altri argomenti. In caso di errore durante la scrittura su un file dopo la creazione, il client richiede la rimozione del file.
Per la comunicazione con il server si è optato per un protocollo ispirato a quello html o ftp, costituito da due cifre, la prima denota il risultato (positive completion/transient negative completion/permanent negative completion), la seconda invece è una specifica della prima. Non tutte le combinazioni sono state usate.

::: center Number Meaning


2[*]{style="color: gray"} positive completion reply 4[*]{style="color: gray"} transient negative completion reply (command not executed) 5[*]{style="color: gray"} permanent negative completion reply (errors) [*]{style="color: gray"}0 syntax [*]{style="color: gray"}1 information [*]{style="color: gray"}2 connection [*]{style="color: gray"}5 file system :::

Di seguito una tabella in cui si associa ogni numero al codice usato:

::: center Number Meaning Code


          20              OK                                           `MEOK`

[21]{style="color: gray"} [not used]{style="color: gray"} [-]{style="color: gray"} [22]{style="color: gray"} [not used]{style="color: gray"} [-]{style="color: gray"} 25 file purged MEFP [40]{style="color: gray"} [not used]{style="color: gray"} [-]{style="color: gray"} [41]{style="color: gray"} [not used]{style="color: gray"} [-]{style="color: gray"} 42 shutting down MESD 45 requested file action not taken MENT 50 syntax error MESY [51]{style="color: gray"} [not used]{style="color: gray"} [-]{style="color: gray"} [52]{style="color: gray"} [not used]{style="color: gray"} [-]{style="color: gray"} 55 server error MESE :::

Il client invia per primo la dimensione del messaggio come long, poi il messaggio. Il server risponde prima con due caratteri che simboleggiano is response number, seguito dal errno se si è riscontrato un errore, oppure i file richiesti o espulsi. Il server per inviare i file richiesti o espulsi, prima invia il numero di file, poi per ogni file la dimensione come int64_t e poi successivamente il file.

Description
No description provided
Readme GPL-3.0 351 KiB
Languages
C 88.4%
TeX 5.8%
Shell 2.9%
Makefile 2.9%