From a5371ad4c729e151a2aa9f165a8d29063189b6bd Mon Sep 17 00:00:00 2001 From: elvis Date: Thu, 31 Mar 2022 22:26:44 +0200 Subject: [PATCH] OpenFile --- lib/threadpool/apiFile.c | 209 +++++++++++++++++++++++++++++++++++-- lib/threadpool/apiFile.h | 22 ++-- lib/threadpool/fileQueue.c | 32 ++++++ lib/threadpool/fileQueue.h | 11 +- lib/utils/conn.h | 2 +- src/server.c | 8 +- 6 files changed, 258 insertions(+), 26 deletions(-) diff --git a/lib/threadpool/apiFile.c b/lib/threadpool/apiFile.c index 2d7e7a0..39a6d50 100644 --- a/lib/threadpool/apiFile.c +++ b/lib/threadpool/apiFile.c @@ -1,32 +1,223 @@ #include +#include + +#define MAXLENMESS 512 + +#define MEOK "20" //OK +#define MEHE "21" // help message +// #define ME "22" // not used +#define MEFP "25" // file purged + +// #define ME "40" // not used +// #define ME "41" // not used +#define MESD "42" // shutting down +#define MENT "45" // requested file action not taken + +#define MESY "50" // syntax error +// #define ME "51" // not used +// #define ME "52" // not used +#define MESE "55" // server error -void openFile(char *filepath, int flags, queueT *q, long fd_c, logT *logFileT); +void openFile(char *filepath, int flags, queueT *q, long fd_c, taglia_t *taglia) { + // messaggio da scrivere sul logfile + char tmp_buf[2048]; + int n = 0; + size_t m = sizeof(tmp_buf); + + if(!filepath || !q || !taglia) { + n += snprintf(tmp_buf+n, m-n, "Client %ld ha richiesto una openFile (flags = %x) sul file \"%s\" e' terminata con errore\n", fd_c, flags, filepath); + errno = EINVAL; + serror(MESY, fd_c, taglia, tmp_buf); + return; + } + + int found = searchFile(q, filepath); // cerco il file nella queue + int create = flags & 0x1; // also %2 + int lock = flags >> 1 & 0x1; // also >>1%2 + fileT *removed = NULL; // file che è stato rimosso + + if(found && create) { // si vuole creare il file ma esiste già + n += snprintf(tmp_buf+n, m-n, "Client %ld ha richiesto una openFile (flags = %x) sul file \"%s\" e' terminata con errore\n", fd_c, flags, filepath); + errno = EEXIST; + serror(MENT, fd_c, taglia, tmp_buf); + return; + } + + if(!found && !create) { // si vuole aprire e non creare un file inesistente + n += snprintf(tmp_buf+n, m-n, "Client %ld ha richiesto una openFile (flags = %x) sul file \"%s\" e' terminato con errore\n", fd_c, flags, filepath); + errno = ENOENT; + serror(MENT, fd_c, taglia, tmp_buf); + return; + } + + if(found && !create) { + if(openFileInQueue(q, file, lock, fd_c) == -1) { + n += snprintf(tmp_buf+n, m-n, "Client %ld ha richiesto una openFile (flags = %x) sul file \"%s\" e' terminato con errore\n", fd_c, flags, filepath); + perror("openFileInQueue"); + serror(MESE, fd_c, taglia, tmp_buf); + return; + } + n += snprintf(tmp_buf+n, m-n, "Client %ld ha richiesto una openFile (flags = %x) sul file \"%s\" e' terminata con successo\n", fd_c, flags, filepath); + sendMessage(MEOK, fd_c, taglia, tmp_buf); + return; + } + + if(!found && create) { // not found and creating new file + if(getLen(q) == queue->maxLen) { // capacity miss + removed = dequeue(q); + if(!removed) { + n += snprintf(tmp_buf+n, m-n, "Client %ld ha richiesto una openFile (flags = %x) sul file \"%s\" e' terminato con errore\n", fd_c, flags, filepath); + perror("dequeue"); + serror(MESE, fd_c, taglia, tmp_buf); + return; + } + + fileT *f = createFileT(filepath, lock, fd_c, 1); // create new file + + if(!f) { + n += snprintf(tmp_buf+n, m-n, "Client %ld ha richiesto una openFile (flags = %x) sul file \"%s\" e' terminato con errore del server\n", fd_c, flags, filepath); + perror("createFileT"); + serror(MESE, fd_c, taglia); + return; + } + + if(enqueue(q, f) != 0) { + n += snprintf(tmp_buf+n, m-n, "Client %ld ha richiesto una openFile (flags = %x) sul file \"%s\" e' terminato con errore del server\n", fd_c, flags, filepath); + perror("enqueue"); + serror(MESE, fd_c, taglia); + return; + } + + taglia_update(taglia, q, 1); // removed only one file + n += snprintf(tmp_buf+n, m-n, "Client %ld ha richiesto una openFile (flags = %x) sul file \"%s\" ha causato una capacity miss. File espulso \"%s\"\n", fd_c, flags, filepath, removed->filepath); + sendMessageFile(MEFP, removed, fd_c, taglia, tmp_buf); + free(removed); + return; + } + + fileT *f = createFileT(filepath, lock, fd_c, 1); + + if(!f) { + n += snprintf(tmp_buf+n, m-n, "Client %ld ha richiesto una openFile (flags = %x) sul file \"%s\" e' terminato con errore del server\n", fd_c, flags, filepath); + perror("createFileT"); + serror(MESE, fd_c, taglia); + return; + } + + if(enqueue(q, f) != 0) { + n += snprintf(tmp_buf+n, m-n, "Client %ld ha richiesto una openFile (flags = %x) sul file \"%s\" e' terminato con errore del server\n", fd_c, flags, filepath); + perror("enqueue"); + serror(MESE, fd_c, taglia); + return; + } + // abbiamo aggiunto un file quindi il numero di file è cambiato + // quindi bisogna fare un update del log + taglia_update(taglia, q, 0); + n += snprintf(tmp_buf+n, m-n, "Client %ld ha richiesto una openFile (flags = %x) sul file \"%s\" e' terminato con successo\n", fd_c, flags, filepath); + sendMessage(MEOK, fd_c, taglia, tmp_buf); + return; + } +} + +// invio il messaggio al client +void sendMessage(char *m, long fd_c, taglia_t *taglia, char *mlog) { + if(!m) { + m = MEOK; + } + + if(writen(fd_c, m, strnlen(m, MAXLENMESS)+1) < 0) { + perror("writen"); + goto _sendM_cleanup; + } + + if(taglia_write(taglia, mlog) < 0) + goto _sendM_cleanup; + + return; + +_sendM_cleanup: + return; +} + +// invio il messaggio al client e poi il file +void sendMessageFile(char *m, fileT *f, long fd_c, taglia_t *taglia, char *mlog) { + if(!f) { + errno = EINVAL; + serror(MESY, fd_c); + goto _sendMF_cleanup; + } + if(!m) { + m = MEPF; + } + + if(writen(fd_c, m, strnlen(m, MAXLENMESS)+1) < 0) { + perror("writen"); + goto _sendMF_cleanup; + } + + if(sendFile(f, fd_c, taglia) < 0) { + perror("sendFile"); + goto _sendMF_cleanup; + } + + if(taglia_write(taglia, mlog) < 0) + goto _sendMF_cleanup; + + return; + +_sendMF_cleanup: + return; +} + +// invio il messaggio al client e poi l'errno +void serror(char *m, long fd_c, taglia_t *taglia, char *mlog) { + if(!m) { + errno = EINVAL; + m = MESY; + } + if(writen(fd_c, m, strnlen(m, MAXLENMESS)+1) < 0) { + perror("writen"); + goto _serror_cleanup; + } + if(writen(fd_c, &errno, sizeof(errno)) < 0) { + perror("writen"); + goto _serror_cleanup; + } + + if(taglia_write(taglia, mlog) < 0) + goto _serror_cleanup; + + return; + +_serror_cleanup: + return; +} -void readFile(char *filepath, queueT *q, long fd_c, logT *logFileT); +void readFile(char *filepath, queueT *q, long fd_c, taglia_t *taglia); -void readNFiles(char *numStr, queueT *q, long fd_c, logT *logFileT); +void readNFiles(char *numStr, queueT *q, long fd_c, taglia_t *taglia); -void writeFile(char *filepath, size_t size, queueT *q, long fd_c, logT *logFileT, int append); +void writeFile(char *filepath, size_t size, queueT *q, long fd_c, taglia_t *taglia, int append); -void lockFile(char *filepath, queueT *q, long fd_c, logT *logFileT, pthread_mutex_t *lock, waitingT **waiting); +void lockFile(char *filepath, queueT *q, long fd_c, taglia_t *taglia, pthread_mutex_t *lock, waitingT **waiting); -void unlockFile(char *filepath, queueT *q, long fd_c, logT *logFileT, pthread_mutex_t *lock, waitingT **waiting); +void unlockFile(char *filepath, queueT *q, long fd_c, taglia_t *taglia, pthread_mutex_t *lock, waitingT **waiting); -void closeFile(char *filepath, queueT *q, long fd_c, logT *logFileT, pthread_mutex_t *lock, waitingT **waiting); +void closeFile(char *filepath, queueT *q, long fd_c, taglia_t *taglia, pthread_mutex_t *lock, waitingT **waiting); -void removeFile(char *filepath, queueT *q, long fd_c, logT *logFileT, pthread_mutex_t *lock, waitingT **waiting); +void removeFile(char *filepath, queueT *q, long fd_c, taglia_t *taglia, pthread_mutex_t *lock, waitingT **waiting); -int sendFile(fileT *f, long fd_c, logT *logFileT); +int sendFile(fileT *f, long fd_c, taglia_t *taglia); int addWaiting(waitingT **waiting, char *file, int fd); diff --git a/lib/threadpool/apiFile.h b/lib/threadpool/apiFile.h index b96894e..c1085aa 100644 --- a/lib/threadpool/apiFile.h +++ b/lib/threadpool/apiFile.h @@ -16,37 +16,37 @@ typedef struct struct_waiting { /** * Apri o crea un nuovo file * \param filepath: nome del file - * \param flags + * \param flags: * \param q: queue in cui inserire il file * \param fd_c: - * \param logFileT: + * \param taglia_t: */ -void openFile(char *filepath, int flags, queueT *q, long fd_c, logT *logFileT); +void openFile(char *filepath, int flags, queueT *q, long fd_c, taglia_t *taglia); // Leggi un file e invialo al client -void readFile(char *filepath, queueT *q, long fd_c, logT *logFileT); +void readFile(char *filepath, queueT *q, long fd_c, taglia_t *taglia); // Invia al client $n file qualsiasi dalla queue -void readNFiles(char *numStr, queueT *q, long fd_c, logT *logFileT); +void readNFiles(char *numStr, queueT *q, long fd_c, taglia_t *taglia); // Scrivi dati su un file già creato (append o overwrite) -void writeFile(char *filepath, size_t size, queueT *q, long fd_c, logT *logFileT, int append); +void writeFile(char *filepath, size_t size, queueT *q, long fd_c, taglia_t *taglia, int append); // Acquisisci lock di un file -void lockFile(char *filepath, queueT *q, long fd_c, logT *logFileT, pthread_mutex_t *lock, waitingT **waiting); +void lockFile(char *filepath, queueT *q, long fd_c, taglia_t *taglia, pthread_mutex_t *lock, waitingT **waiting); // Rilascia una Lock di un file -void unlockFile(char *filepath, queueT *q, long fd_c, logT *logFileT, pthread_mutex_t *lock, waiting_t **waiting); +void unlockFile(char *filepath, queueT *q, long fd_c, taglia_t *taglia, pthread_mutex_t *lock, waiting_t **waiting); // Chiudi un file -void closeFile(char *filepath, queueT *q, long fd_c, logT *logFileT, pthread_mutex_t *lock, waiting_t **waiting); +void closeFile(char *filepath, queueT *q, long fd_c, taglia_t *taglia, pthread_mutex_t *lock, waiting_t **waiting); // Rimuovi un file -void removeFile(char *filepath, queueT *q, long fd_c, logT *logFileT, pthread_mutex_t *lock, waiting_t **waiting); +void removeFile(char *filepath, queueT *q, long fd_c, taglia_t *taglia, pthread_mutex_t *lock, waiting_t **waiting); // Funzione ausiliaria che invia un file al client -int sendFile(fileT *f, long fd_c, logT *logFileT); +int sendFile(fileT *f, long fd_c, taglia_t *taglia); // Aggiunge una coppia client/file alla coda in attesa di ottenere una lock int addWaiting(waiting_t **waiting, char *file, int fd); diff --git a/lib/threadpool/fileQueue.c b/lib/threadpool/fileQueue.c index 16d3fde..b0b84c9 100644 --- a/lib/threadpool/fileQueue.c +++ b/lib/threadpool/fileQueue.c @@ -673,6 +673,38 @@ _end_find_in_queue: return NULL; } +// cerco +int searchFile(queueT *q, char *filepath) { + if(!q || !filepath) { + errno = EINVAL; + return NULL; + } + + LOCK_RETURN(&q->m, NULL); // begin me + + if (q->len == 0) + goto _end_search_file_in_queue; + + nodeT *tmp = q->head; + + while (tmp) { + if (strcmp(filepath, (tmp->data)->filepath) == 0) { // trovato + break; + } + tmp = tmp->next; + } + + if(!tmp) + goto _end_search_file_in_queue; + + UNLOCK_RETURN(&q->m, NULL); // end me + return 1; + +_end_search_file_in_queue: + UNLOCK_RETURN(&q->m, NULL); + return 0; +} + // numero di elementi della queue size_t getLen(queueT *q) { if(!q) { diff --git a/lib/threadpool/fileQueue.h b/lib/threadpool/fileQueue.h index 7cb8d05..c623161 100644 --- a/lib/threadpool/fileQueue.h +++ b/lib/threadpool/fileQueue.h @@ -191,7 +191,7 @@ int removeFileFromQueue(queueT *q, char *filepath, int owner); /** - * Cerca un fileT nella coda. + * 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 * @@ -199,6 +199,15 @@ int removeFileFromQueue(queueT *q, char *filepath, int owner); */ 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 + * + * \retval 0 se non trovato, 1 se trovato + */ +int searchFile(queueT *q, char *filepath); + /** * Numero di elementi presenti nella coda. * \param q: puntatore alla coda diff --git a/lib/utils/conn.h b/lib/utils/conn.h index 0447020..7d9fd2f 100644 --- a/lib/utils/conn.h +++ b/lib/utils/conn.h @@ -50,7 +50,7 @@ static inline int writen(long fd, void *buf, size_t size) { int r; char *bufptr = (char*)buf; while(left>0) { - if ((r=write((int)fd ,bufptr,left)) == -1) { + if ((r=write((int) fd, bufptr, left)) == -1) { if (errno == EINTR) continue; return -1; } diff --git a/src/server.c b/src/server.c index 9243ec1..ae93a35 100644 --- a/src/server.c +++ b/src/server.c @@ -163,7 +163,7 @@ int main(int argc, char *argv[]) { char buf[2048]; int n; n = snprintf(buf, sizeof(buf), "Creato socket: %s\n", socketName); - if( n<0 || m