diff --git a/Relazione/Relazione.tex b/Relazione/Relazione.tex new file mode 100644 index 0000000..73b0f92 --- /dev/null +++ b/Relazione/Relazione.tex @@ -0,0 +1,259 @@ +\documentclass[11pt, oneside]{article} +\usepackage[ + left=2cm, + right=2cm, + top=2cm, + bottom=2cm, +]{geometry} +\geometry{a4paper} + +\usepackage{graphicx} %% for pictures +\usepackage{float} +\usepackage{amssymb} %% math symbols +\usepackage{amsmath} %% math matrix etc +\usepackage{listings} %% code block + +\lstset{ + language=C, + showspaces=false, + basicstyle=\small\ttfamily, + numbers=left, + numberstyle=\tiny, + breaklines=true, + postbreak=\mbox{\textcolor{red}{$\hookrightarrow$}\space}, + backgroundcolor = \color{lightgray}, +} + +\usepackage{enumitem} %% for lists and enumerating +\usepackage{color} +\usepackage{xcolor,colortbl} % xcolor for defining colors, colortbl for table colors +\usepackage{makecell} %% for multiple lines in cell of table +\usepackage{hyperref} %% links for table of contents + +\usepackage{pgfplots} %% plots used with \begin{tikzpicture} +\usepackage{tikz} %% for pictures +\usetikzlibrary{trees} +\pgfplotsset{width=10cm,compat=newest} + +\usepackage{cancel} + +%% set max table of contents recursion to subsection (3->subsubsecition) +\setcounter{tocdepth}{2} +\setcounter{secnumdepth}{2} + +%% +\definecolor{red}{rgb}{1, 0.1, 0.1} +\definecolor{lightgreen}{rgb}{0.55, 0.87, 0.47} +\definecolor{gray}{rgb}{0.3, 0.3, 0.3} +\newcommand{\lgt}{\cellcolor{lightgreen}} %% light green in tables +\newcommand{\gry}{\textcolor{gray}} %% gray text + + +%% use bar instead of arrow for vectors +\renewcommand{\vec}[1]{\bar{#1}} + +%% itemize use less vertical space (use olditemize for default behaviour) +\let\olditemize=\itemize +\let\endolditemize=\enditemize +\renewenvironment{itemize}{\olditemize \itemsep-0.2em}{\endolditemize} + +%% items in itemize emph+box +%% usage: \ieb{Class:} for simple item +%% \ieb[4cm]{Class:} for specific size of box +\newcommand{\ieb}[2][2cm]{ + \makebox[#1][l]{\emph{#2}} +} %% TODO: replace with description environment (? maybe) + +%---------------------------------% + +\title{Progetto di Laboratorio di Sistemi Operativi} +\author{ + Elvis Rossi - Matricola 561394 +} +\date{\today} + +%---------------------------------% + +%%% BEGIN DOCUMENT +\begin{document} +\maketitle +\tableofcontents + +\newpage + +%% ------------------------- %% + +\section{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: \href{http://google.com}{TODO}.\\ +Si può accedere usando le credenziali: + +\begin{center} +\begin{tabular}{||c|c||} + \hline + Username & Password \\ \hline + Guest & CNs7Vbx3vLJQ2aK \\ \hline +\end{tabular} +\end{center} + +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 \texttt{-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 \textit{testFiles}. + + +%% ------------------------- %% + +\section{Server} +Il server prende come unico argomento il path al file di configurazione. Un esempio di file di configurazione è \texttt{config.ini} presente nella root del progetto. La struttura del file è analoga a quella di un file \href{https://en.wikipedia.org/wiki/INI_file}{INI}, quindi l'ordine degli argomenti è irrilevante. +Il file di configurazione viene letto da una libreria di "\textit{terza parte}" ottenuta da \href{https://github.com/rxi/ini}{rxi/ini}. +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 \texttt{strsep} invece di \texttt{strtok} o \texttt{strtok\_r} sia nel programma server che client. +Il codice è stato adattato leggermente da quello presente nella libreria C GNU (\href{https://sourceware.org/git/?p=glibc.git;a=blob;f=string/strsep.c;h=b534a1ec17fd2e91087af04abe1c3f1ac3e74ce0;hb=HEAD}{strsep}) in modo da utilizzare la funzione omonima su piattaforme BSD. + + +\subsection{Main} +Il thread principale accetta le connessioni in arrivo da i client su un socket di tipo \texttt{AF\_UNIX} con nome di default \textit{socket}. Viene interrotto dal thread \texttt{sighandler\_thread} se ricevuto un segnale fra: \texttt{SIGHUP}, \texttt{SIGINT} o \texttt{SIGQUIT}. + +\subsection{serverWorker} +Il thread main dopo aver accettato la connessione di un client crea un thread "\textit{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 \textit{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 \textit{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 \texttt{waiting\_t}. +La richiesta accodata non è quindi gestita dal thread corrente, ma dal thread che rilascerà la lock al file associato. +Si evitano quindi \textit{polling} o l'utilizzo di \textit{condition}. + +\subsection{sighandler\_thread} +Il thread gestisce i segnali in arrivo al server. +Se il segnale ricevuto è di tipo \texttt{SIGINT} o \texttt{SIGQUIT}, il server termina prima possibile. +Se il segnale ricevuto è del tipo \texttt{SIGHUP} invece si attende che ogni worker abbiano servito le richieste dei client precedentemente connessi. + + +%% ------------------------- %% + +\section{Storage} + +Il server gestisce la memorizzazione dei file tramite la libreria \textit{fileQueue}. +La struttura principale è una linked list chiamata \texttt{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 da un file: \texttt{size} e \texttt{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 \texttt{size}, lasciando invariato la dimensione \texttt{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. + + +%% ------------------------- %% + +\section{Logging} + +Il server usa la libreria "\texttt{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: \texttt{taglia\_write}, \texttt{taglia\_log}. +\texttt{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, come ad esempio il numero massimo di file memorizzati o la dimensione massima raggiunta. + + +%% ------------------------- %% + +\section{Client} + +Oltre alle funzioni di API richieste dalla specifica è stata implementata la funzione \texttt{setDirectory}, perchè si è interpretata come se le opzioni \texttt{-d} e \texttt{-D} dovessero poter essere associate a più di un comando. Tuttavia questa funzionalità non è presente nel client in modo diretto dato che vengono inserite \texttt{-d}/\texttt{-D /dev/null} fra due opzioni \texttt{-w}/\texttt{-W} o \texttt{-r}/\texttt{-R} successive. +L'opzione \texttt{-d /dev/null} o \texttt{-D /dev/null} è stata ottimizzata leggermente in modo da non fare chiamate di sistema. + +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. + +\begin{center} +\begin{tabular}{|c|l|} + \hline + Number & Meaning \\ \hline +2\gry{*} & positive completion reply \\ \hline +4\gry{*} & transient negative completion reply (command not executed) \\ \hline +5\gry{*} & permanent negative completion reply (errors) \\ \hline + \hline +\gry{*}0 & syntax \\ \hline +\gry{*}1 & information \\ \hline +\gry{*}2 & connection \\ \hline +\gry{*}5 & file system \\ \hline +\end{tabular} +\end{center} + +Di seguito una tabella in cui si associa ogni numero al codice usato: + +\begin{center} +\begin{tabular}{|c|l|c|} + \hline + Number & Meaning & Code \\ \hline + \hline + 20 & OK & \texttt{MEOK} \\ \hline + \gry{21} & \gry{not used} & \gry{\texttt{-}} \\ \hline + \gry{22} & \gry{not used} & \gry{\texttt{-}} \\ \hline + 25 & file purged & \texttt{MEFP} \\ \hline + \hline + \gry{40} & \gry{not used} & \gry{\texttt{-}} \\ \hline + \gry{41} & \gry{not used} & \gry{\texttt{-}} \\ \hline + 42 & shutting down & \texttt{MESD} \\ \hline + 45 & requested file action not taken & \texttt{MENT} \\ \hline + \hline + 50 & syntax error & \texttt{MESY} \\ \hline + \gry{51} & \gry{not used} & \gry{\texttt{-}} \\ \hline + \gry{52} & \gry{not used} & \gry{\texttt{-}} \\ \hline + 55 & server error & \texttt{MESE} \\ \hline +\end{tabular} +\end{center} + +Il client invia per primo la dimensione del messaggio come \texttt{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 \texttt{int64\_t} e poi successivamente il file. + + + +%% ------------------------- %% + + +\end{document} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Relazione/Response numbers.txt b/Relazione/Response numbers.txt index 3f8c34f..2d987eb 100644 --- a/Relazione/Response numbers.txt +++ b/Relazione/Response numbers.txt @@ -43,7 +43,7 @@ II number) 20 OK MEOK -21 help message MEHE +21 not used - 22 not used - 25 file purged MEFP diff --git a/lib/threadpool/fileQueue.h b/lib/threadpool/fileQueue.h index 49093d6..b92affe 100644 --- a/lib/threadpool/fileQueue.h +++ b/lib/threadpool/fileQueue.h @@ -24,7 +24,7 @@ typedef struct node { struct node *next; } nodeT; -/* coda FIFO */ +/* coda */ typedef struct { nodeT *head; /* puntatore al primo elemento */ nodeT *tail; /* puntatore all'ultimo elemento */ @@ -39,10 +39,10 @@ typedef struct { /** * Creazione di un fileT. - * @param f: string che identifica il fileT tramite il suo path assoluto - * @param O_LOCK: 1 locked, 0 unlocked - * @param client: client associato - * @param open: apertura del file dopo la creazione + * @param f string che identifica il fileT tramite il suo path assoluto + * @param O_LOCK 1 locked, 0 unlocked + * @param client client associato + * @param open apertura del file dopo la creazione * * @return puntatore al fileT, NULL se errore (errno) */ @@ -50,9 +50,9 @@ fileT* createFileT(char *f, int O_LOCK, int client, int open); /** * Append su un fileT. - * @param f: fileT sul quale scrivere - * @param data: puntatore al buffer da scrivere - * @param size: dimensione in bytes del buffer + * @param f fileT sul quale scrivere + * @param data puntatore al buffer da scrivere + * @param size dimensione in bytes del buffer * * @return 0 se successo, -1 se errore (errno) */ @@ -69,8 +69,8 @@ void destroyFile(fileT *f); /** * Alloca ed inizializza una coda di fileT. Deve essere chiamata da un solo * thread. - * @param maxLen: lunghezza massima della coda - * @param maxSize: dimensione massima della coda in bytes + * @param maxLen lunghezza massima della coda + * @param maxSize dimensione massima della coda in bytes * * @return puntatore alla coda allocata, NULL se errore */ @@ -78,8 +78,8 @@ queueT* createQueue(size_t maxLen, size_t maxSize); /** * Inserisce un fileT nella coda. - * @param q: puntatore alla coda - * @param data: puntatore al fileT da inserire + * @param q puntatore alla coda + * @param data puntatore al fileT da inserire * * @return 0 se successo, -1 se errore (errno) */ @@ -87,7 +87,7 @@ int enqueue(queueT *q, fileT* data); /** * Estrae un fileT dalla coda. - * @param q: puntatore alla coda + * @param q puntatore alla coda * * @return puntatore al file estratto, NULL se errore */ @@ -95,9 +95,9 @@ fileT* dequeue(queueT *q); /** * Estrae fileT dalla coda fino ad ottenere abbastanza spazio in q. - * @param q: puntatore alla coda - * @param filepath: file a cui bisogna aggiungere s di spazio - * @param s: dimensione da aggiungere al file + * @param q puntatore alla coda + * @param filepath file a cui bisogna aggiungere s di spazio + * @param s dimensione da aggiungere al file * * @return puntatore alla lista di file estratti (NULL terminated), NULL se errore */ @@ -107,15 +107,15 @@ fileT ** dequeueN(queueT *q, char *filepath, size_t s); * Estrae un fileT dalla coda come la dequeue, ma invece di restituire il * file estratto lo distrugge immediatamente, liberandone la memoria. * - * @param q: puntatore alla coda + * @param q puntatore alla coda */ void voidDequeue(queueT *q); /** * Stampa l'intero contenuto della coda. - * @param stream: file su cui stampare - * @param q: puntatore alla coda da stampare + * @param stream file su cui stampare + * @param q puntatore alla coda da stampare * * @retval 0 se successo, -1 se errore (errno) */ @@ -126,9 +126,9 @@ int printQueue(FILE *stream, queueT *q); /** * Cerca di ottenere il lock su un fileT, fallisce se un altro client ha gia' * richiesto la lock - * @param q: puntatore alla coda che contiene il fileT - * @param filepath: path assoluto (identificatore) del fileT - * @param owner: client che ha richiesto l'operazione + * @param q puntatore alla coda che contiene il fileT + * @param filepath path assoluto (identificatore) del fileT + * @param owner client che ha richiesto l'operazione * * @return 0 se successo, -1 se errore (errno) */ @@ -136,9 +136,9 @@ int lockFileInQueue(queueT *q, char *filepath, int owner); /** * Rilascia il lock di un file, fallisce se non si e' il possessore del lock - * @param q: puntatore alla coda che contiene il fileT - * @param filepath -> path assoluto (identificatore) del fileT - * @param owner -> client che ha richiesto l'operazione + * @param q puntatore alla coda che contiene il fileT + * @param filepath path assoluto (identificatore) del fileT + * @param owner client che ha richiesto l'operazione * * @return 0 se successo, -1 se errore (errno) */ @@ -147,10 +147,10 @@ int unlockFileInQueue(queueT *q, char *filepath, int owner); /** * Apre un fileT contenuto nella coda. Fallisce se il lock appartiene a un * client diverso. - * @param q: puntatore alla coda che contiene il fileT da aprire - * @param filepath: path assoluto (identificatore) del fileT da aprire - * @param O_LOCK: 1 locked, 0 unlocked - * @param owner: client che ha richiesto l'apertura + * @param q puntatore alla coda che contiene il fileT da aprire + * @param filepath path assoluto (identificatore) del fileT da aprire + * @param O_LOCK 1 locked, 0 unlocked + * @param owner client che ha richiesto l'apertura * * @return 0 se successo, -1 se errore (errno) */ @@ -159,9 +159,9 @@ int openFileInQueue(queueT *q, char *filepath, int O_LOCK, int owner); /** * Chiude un file contenuto nella coda. Ha successo se fileT non e' stato aperto. * Fallisce se il file e' stato messo in modalita' locked da un client diverso. - * @param q: puntatore alla coda che contiene il fileT da chiudere - * @param filepath: path assoluto (identificatore) del fileT da chiudere - * @param owner: client che ha richiesto la chiusura + * @param q puntatore alla coda che contiene il fileT da chiudere + * @param filepath path assoluto (identificatore) del fileT da chiudere + * @param owner client che ha richiesto la chiusura * * @return 0 se successo, -1 se errore (errno) */ @@ -170,11 +170,11 @@ int closeFileInQueue(queueT *q, char *filepath, int owner); /** * Scrive del contenuto su un fileT all'interno della coda. Fallisce se il file * non e' stato aperto o se il lock appartiene a un client diverso. - * @param q: puntatore alla coda che contiene il fileT su cui scrivere - * @param filepath: path assoluto (identificatore) del fileT - * @param data: buffer che contiene i dati - * @param size: dimensione in bytes del buffer - * @param owner: client che ha richiesto l'operazione di scrittura + * @param q puntatore alla coda che contiene il fileT su cui scrivere + * @param filepath path assoluto (identificatore) del fileT + * @param data buffer che contiene i dati + * @param size dimensione in bytes del buffer + * @param owner client che ha richiesto l'operazione di scrittura * * @return 0 se successo, -1 se errore (errno) */ @@ -183,11 +183,11 @@ int writeFileInQueue(queueT *q, char *filepath, void *data, size_t size, int own /** * Scrive del contenuto in append su un fileT all'interno della coda. Fallisce * se il file non e' stato aperto o se il lock appartiene a un client diverso. - * @param q: puntatore alla coda che contiene il fileT su cui effettuare l'append - * @param filepath: path assoluto (identificatore) del fileT - * @param data: buffer che contiene i dati - * @param size: dimensione in bytes del buffer - * @param owner: client che ha richiesto l'operazione di append + * @param q puntatore alla coda che contiene il fileT su cui effettuare l'append + * @param filepath path assoluto (identificatore) del fileT + * @param data buffer che contiene i dati + * @param size dimensione in bytes del buffer + * @param owner client che ha richiesto l'operazione di append * * @return 0 se successo, -1 se errore (setta errno) */ @@ -196,9 +196,9 @@ int appendFileInQueue(queueT *q, char *filepath, void *data, size_t size, int ow /** * Rimuove un fileT dalla coda. Fallisce se non si è in possesso della lock o se * la lock e' posseduta da un client diverso. - * @param q: puntatore alla coda che contiene il fileT da rimuovere - * @param filepath: path assoluto (identificatore) del fileT da rimuovere - * @param owner: client che ha richiesto la rimozione + * @param q puntatore alla coda che contiene il fileT da rimuovere + * @param filepath path assoluto (identificatore) del fileT da rimuovere + * @param owner client che ha richiesto la rimozione * * @return 0 se successo, -1 se errore (errno) */ @@ -208,8 +208,8 @@ int removeFileFromQueue(queueT *q, char *filepath, int owner); /** * Cerca un fileT nella coda e ritorna una copia. - * @param q: puntatore alla coda sulla quale cercare il fileT - * @param filepath: path assoluto del fileT da cercare + * @param q puntatore alla coda sulla quale cercare il fileT + * @param filepath path assoluto del fileT da cercare * * @return puntatore a una copia del fileT se trovato, NULL se non trovato o errore (errno) */ @@ -217,8 +217,8 @@ fileT* find(queueT *q, char *filepath); /** * Cerca il fileT nella coda e ritorna il siultato dell'operazione - * @param q: puntatore alla coda sulla quale cercare il fileT - * @param filepath: path assoluto del fileT da cercare + * @param q puntatore alla coda sulla quale cercare il fileT + * @param filepath path assoluto del fileT da cercare * * @return 0 se non trovato, 1 se trovato */ @@ -226,7 +226,7 @@ int searchFile(queueT *q, char *filepath); /** * Numero di elementi presenti nella coda. - * @param q: puntatore alla coda + * @param q puntatore alla coda * * @return numero di elementi presenti, -1 se errore (errno) */ @@ -234,7 +234,7 @@ size_t getLen(queueT *q); /** * Restituisce la dimensione attuale della coda in bytes. - * @param q: puntatore alla coda + * @param q puntatore alla coda * * @return dimensione della coda in bytes, -1 se errore (errno) */ @@ -242,7 +242,7 @@ size_t getSize(queueT *q); /** * Cancella una coda allocata con createQueue e ne libera la memoria. - * @param q: puntatore alla coda da distruggere + * @param q puntatore alla coda da distruggere */ void destroyQueue(queueT *q);