diff --git a/Projet_M2/README.md b/Projet_M2/README.md index 29eaaa3a1caf77e82b4648b9618330368a458a71..e39f9e63e99905f39bdf66608693e21b380f223d 100644 --- a/Projet_M2/README.md +++ b/Projet_M2/README.md @@ -2,7 +2,7 @@ Pour compiler le programme : make fact -Pour exécuter le fichier exécutable fact : ./fact [-N nombre_de_threads] input output +Pour exécuter le fichier exécutable "fact" : ./fact [-N nombre_de_threads] input output Pour compiler et tester (suite de tests unitaires) le programme : make test @@ -12,3 +12,42 @@ Pour effectuer une analyse avec "cppcheck" : make cpp Pour nettoyer les fichiers auxiliaires générés et l'exécutable : make clean + +Architecture du programme: + +Le travail est décomposé en 3 sections coordonnées via un double problème du producteur-consommateur : + + -> 1 thread s'occupe de: + § lire le fichier input + + § stocker chacune des lignes sous forme de chaine de charactère dans un 1er tableau + + -> N threads s'occupent de : + § récupérer les chaines de caractères dans le premier tableau + + § les convertir en 'unsigned long long' et calculer leur liste de diviseurs premiers + + § Stocker ces listes dans un 2e tableau + + -> 1 thread s'occupe de : + § récupérer les listes de diviseurs dans le 2e tableau + + § Retranscrire dans le bon format le nombre à factoriser et ses diviseurs premiers dans le fichier output + +Note : + § Les accès aux tableaux sont coordonnés par des mutex (1 par tableau) et des sémaphores + + § Les diviseurs premiers d'un même nombre sont stockés dans une circular linked list + + +Architecture des tests : + +6 tests sont réalisés afin de tester: + + § La fonction is_div + § La fonction is_prime (2 tests) + § Le fonctionnement complet pour un fichier vide (N = 4) + § Le fonctionnement complet pour un fichier d'une ligne : check du format et des diviseurs (N = 4) + § Le fonctionnement complet pour un fichier de 100 lignes : check du nombre de lignes (réalisé avec N = 4 puis N = 1) + +# lepl1503-2020-groupe-M2 \ No newline at end of file diff --git a/Projet_M2/run.c b/Projet_M2/run.c index db5a64c8bfdf51602cab8fdcab329d92a5f94481..7c279fe4d7f23920aee61bc092e0bb63c0e62037 100755 --- a/Projet_M2/run.c +++ b/Projet_M2/run.c @@ -1,10 +1,7 @@ #include <stdio.h> #include <stdlib.h> #include <string.h> -#include <fcntl.h> #include <unistd.h> -#include <sys/stat.h> - #include <pthread.h> #include <semaphore.h> @@ -78,7 +75,7 @@ char *get_from_buffer_1(struct buffer_rc *ptr){ // chercher dans le buffer 1 result = ptr->tab[ptr->tail]; // donne un valeur a result //free(ptr->tab[ptr->tail]); ptr->tab[ptr->tail] = NULL; - ptr->len--; //diminue l'espace occupé par le buffer + ptr->len--; //diminue l'espace occupé dans le buffer ptr->tail = (ptr->tail + 1)%ptr->size; return result; @@ -87,12 +84,12 @@ char *get_from_buffer_1(struct buffer_rc *ptr){ // chercher dans le buffer 1 void put_in_buffer_2(struct queue *ptr, struct buffer_cw *buf){ //ajouter un element dans le buffer 2 buf->tab[buf->head] = malloc(sizeof(*ptr)); buf->tab[buf->head] = ptr; - buf->len++; //augmenté l'espace occupé par le buffer + buf->len++; //augmente l'espace occupé dans le buffer buf->head = (buf->head + 1)%buf->size; } queue_t *get_from_buffer_2(struct buffer_cw *buf){ // trouver un element - //printf("%d\n",buf->len); + struct queue *result; result = buf->tab[buf->tail]; //donne une valeur a result buf->tab[buf->tail] = NULL; @@ -104,7 +101,7 @@ queue_t *get_from_buffer_2(struct buffer_cw *buf){ // trouver un element int is_div(unsigned long long number, unsigned long long i) { // Vérifie si i est un diviseur de number. - return (number % i == 0) ; // revoi 0 si le nombre n'est pas divisible par i et 1 si il est divisible + return (number % i == 0) ; // renvoie 0 si le nombre n'est pas divisible par i et 1 si il est divisible } @@ -146,7 +143,7 @@ void enqueue(queue_t* q, unsigned long long val){ *q->tail->next = *ptr; } q->size++; - //return q; + //free(ptr->next); free(ptr); @@ -195,7 +192,7 @@ void *writing(void *param){ if (pr_divs->final == 1) { - //printf("final : %d\n",pr_divs->final); + if (stop == N-1){ for (int i = 0; i < param1->size; i++) { @@ -281,11 +278,6 @@ void *calculating(void *param){ pthread_mutex_unlock(&mutex2); sem_post(&full2); - - //free(pr_divs->tail); - //free(pr_divs); - - } return NULL; @@ -298,7 +290,6 @@ void *reading (void *param){ char chaine[30]; FILE *input; - //input = malloc(sizeof(FILE*)); input = param1->file1; while (fgets(chaine,30,input) != NULL){ @@ -311,14 +302,13 @@ void *reading (void *param){ pthread_mutex_unlock(&mutex1); sem_post(&full1); } - //param1->stop = 1; for (int i = 0; i < N; i++) { sem_wait(&empty1); pthread_mutex_lock(&mutex1); - put_in_buffer_1("stop\0",param1); //put each line in the buffer #1 + put_in_buffer_1("stop\0",param1); //put each stop line in the buffer #1 pthread_mutex_unlock(&mutex1); sem_post(&full1); @@ -449,9 +439,3 @@ int run (char *input,char *output, int n_threads){ return EXIT_SUCCESS; } - - /* int main() { - int err = run("input.txt", "actual_output.txt"); - - return err; - } */ diff --git a/Projet_M2/test.c b/Projet_M2/test.c index cbd982506a831f680edb401d460b3aaca270d0b5..400695f394ee0d8e1397b081d23007f9dc47ccf3 100644 --- a/Projet_M2/test.c +++ b/Projet_M2/test.c @@ -80,7 +80,7 @@ void short_file_test(void){ fclose(file2); } -void file_test(void){ +void file_test_N_4(void){ FILE *file1 = NULL; FILE *file2 = NULL; @@ -93,18 +93,65 @@ void file_test(void){ clock_t start, end; double time; start = clock(); - printf("check1\n"); + int err = run("Test_files/input.txt","actual_output.txt",4); end = clock(); time = (double) (end - start) / CLOCKS_PER_SEC; - printf("Temps = %.2f secondes \n",time); + printf("Temps pour 4 threads de calculs = %.2f secondes \n",time); if (err == -1){ CU_FAIL("method run failed"); fclose(file1); return; } - printf("checkfinal\n"); + + file2 = fopen("actual_output.txt","r"); + if (file2 == NULL){ + CU_FAIL("actual_output opening fail"); + fclose(file1); + return; + } + + char chaine2[50]; + + int n = 0; + + while (fgets(chaine2,50,file2) != NULL) + { + n++; + } + CU_ASSERT_EQUAL(n,100); + + fclose(file1); + fclose(file2); + +} + +void file_test_N_1(void){ + FILE *file1 = NULL; + FILE *file2 = NULL; + + file1 = fopen("Test_files/expected_output.txt","r"); + if (file1 == NULL){ + CU_FAIL("expected_output opening fail"); + return; + } + + clock_t start, end; + double time; + start = clock(); + + int err = run("Test_files/input.txt","actual_output.txt",1); + + end = clock(); + time = (double) (end - start) / CLOCKS_PER_SEC; + printf("Temps pour 1 thread de calcul = %.2f secondes \n",time); + if (err == -1){ + CU_FAIL("method run failed"); + fclose(file1); + return; + } + file2 = fopen("actual_output.txt","r"); if (file2 == NULL){ CU_FAIL("actual_output opening fail"); @@ -112,19 +159,14 @@ void file_test(void){ return; } - //char chaine1[50]; char chaine2[50]; int n = 0; while (fgets(chaine2,50,file2) != NULL) { - //printf("%s\n",chaine1); - //printf("%s\n",chaine2); - //CU_ASSERT_STRING_EQUAL(chaine1,chaine2); n++; } - //printf("%d",n); CU_ASSERT_EQUAL(n,100); fclose(file1); @@ -166,7 +208,8 @@ int main(int argc, char *argv[]){ NULL == CU_add_test(pSuite, "test_is_not_prime",test_is_not_prime) || NULL == CU_add_test(pSuite,"empty_file_test",empty_file_test) || NULL == CU_add_test(pSuite,"short_file_test",short_file_test) || - NULL == CU_add_test(pSuite,"file_test",file_test)) + NULL == CU_add_test(pSuite,"file_test : N = 4",file_test_N_4) || + NULL == CU_add_test(pSuite,"file_test N = 1",file_test_N_1)) { CU_cleanup_registry(); return CU_get_error();