/*********************************************************************** * Code contenant les fonctions qui doivent etre adaptees par * * l'etudiant pour son TP note * ***********************************************************************/ #include #include #include #include #include #include #include #include #include void handle_connection (int connection_fd); void *thread_gestion_connexion_entrante(void *arg); void *thread_gestion_sauvegarde(void *arg); #define NOMFICHIER "./sauvegardeCompteurReponse" /*************************************/ /* Definition des variables globales */ /*************************************/ int compteurReponse; pthread_mutex_t mutex; int fd; /********************************************/ /* Procedures appelees par le reste du code */ /********************************************/ /* Procedure chargee de toutes les initialisations specifiques au code de l'etudiant */ void init(){ pthread_t thread; int rc; /* Initialisation de compteurReponse. On essaye d'ouvrir le fichier (avec */ /* l'option O_SYNC pour que l'ecriture se fasse au plus tot sur disque et */ /* qu'on perde donc le moins d'increments de compteurReponse possible en */ /* cas de panne) */ fd = open(NOMFICHIER, O_RDWR|O_SYNC, 0); if (fd < 0){ if (errno == ENOENT){ /* Le fichier n'existe pas : on le cree donc (meme argument que precedemment */ /* pour O_SYNC) */ fd = open(NOMFICHIER, O_CREAT|O_RDWR|O_SYNC, S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH); if (fd < 0){ perror("open fichier"); exit(EXIT_FAILURE); } /* Le fichier venant d'etre cree, compteurReponse vaut forcement 0 */ compteurReponse = 0; }else{ perror("open fichier2"); exit(EXIT_FAILURE); } }else{ /* Pas d'erreur a l'ouverture du fichier : on recupere donc la valeur de */ /* compteurReponse */ if (read(fd, &compteurReponse, sizeof(compteurReponse)) != sizeof(compteurReponse)){ perror("Pb lors de l'initialisation de compteurReponse"); exit(EXIT_FAILURE); } } /* Initialisation de mutex */ if (pthread_mutex_init(&mutex, NULL) != 0){ perror("pthread_mutex_init"); exit(EXIT_FAILURE); } /* Demarrage de la thread chargee de faire les sauvegardes */ /* NB : Inutile de detacher ce thread, vu qu'il tournera eternellement */ /* (plus precisement jusqu'a la mort du processus) */ rc = pthread_create(&thread, NULL, thread_gestion_sauvegarde, NULL); if (rc < 0){ perror("pthread_create"); exit(EXIT_FAILURE); } } /* Procedure chargee de la gestion d'une connexion entrante (liee a une requete http */ void gestion_connexion_entrante(int connexion_fd){ pthread_t thread; int rc; /* On cree le thread */ rc = pthread_create(&thread, NULL, thread_gestion_connexion_entrante, (void*)connexion_fd); if (rc < 0){ perror("pthread_create"); exit(EXIT_FAILURE); } /* On detache le thread de sorte que, quand il se terminera, les ressources */ /* qu'il utilise pourront etre liberees. */ rc = pthread_detach(thread); if (rc < 0){ perror("pthread_detach"); exit(EXIT_FAILURE); } } /* Fonction chargee de faire les traitements lies a compteurReponse lorsque le serveur repond a une requete http. Cette focntion doit au minimum incrementer compteurReponse. Cette fonction renvoie la valeur de compteurReponse. */ int gestion_compteurReponse(){ if (pthread_mutex_lock(&mutex) != 0){ perror("pthread_mutex_init"); exit(EXIT_FAILURE); } /* Incrementation de compteurReponse */ compteurReponse += 1; if (pthread_mutex_unlock(&mutex) != 0){ perror("pthread_mutex_init"); exit(EXIT_FAILURE); } return compteurReponse; } /********************************************/ /* Procedures specifiques a l'etudiant */ /********************************************/ /* Procedure chargee des traitements liees a une reponse a une requete http */ void *thread_gestion_connexion_entrante(void *arg){ int connection_fd = (int) arg; handle_connection(connection_fd); pthread_exit(NULL); } void *thread_gestion_sauvegarde(void *arg){ struct timespec sleeptime={1,0}; do{ int compteurReponseLocal; /* On recupere la valeur courante de compteurReponse (dans une variable */ /* locale pour que la recuperation de cette valeur bloque le moins de */ /* temps possible les autres threads) */ if (pthread_mutex_lock(&mutex) != 0){ perror("pthread_mutex_init"); exit(EXIT_FAILURE); } compteurReponseLocal = compteurReponse; if (pthread_mutex_unlock(&mutex) != 0){ perror("pthread_mutex_init"); exit(EXIT_FAILURE); } /* Ecriture de compteurReponse dans le fichier */ if (lseek(fd, 0, SEEK_SET) < 0){ perror("lseek"); exit(EXIT_FAILURE); } if (write(fd, &compteurReponse, sizeof(compteurReponse)) != sizeof(compteurReponse)){ perror("write"); exit(EXIT_FAILURE); } /* On dort */ if (nanosleep(&sleeptime, NULL) != 0){ perror("nanosleep"); exit(EXIT_FAILURE); } }while(1); pthread_exit(NULL); }