From 70bb4fd94e446b2efae7d6b872ed0eb05328c4c9 Mon Sep 17 00:00:00 2001 From: Moncef STITI <moncef.stiti@etu.u-pec.fr> Date: Thu, 5 Dec 2024 14:25:43 +0100 Subject: [PATCH] =?UTF-8?q?Am=C3=A9lioration?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Secured/README.md | 4 +- SecuredThread/secured_transaction_threads.c | 8 +- Unsecured/README.md | 4 +- Unsecured/unsecured_transaction.c | 106 ++++++++++++++++++-- 4 files changed, 107 insertions(+), 15 deletions(-) diff --git a/Secured/README.md b/Secured/README.md index 920413e..ef33704 100644 --- a/Secured/README.md +++ b/Secured/README.md @@ -40,9 +40,9 @@ Exécutez le programme en spécifiant : Exemple : ```bash -./secured_transaction 4 10 +./secured_transaction 30 50 ``` -Ici, 4 processus seront lancés, chacun effectuant 10 transactions. +Ici, 30 processus seront lancés, chacun effectuant 50 transactions. --- diff --git a/SecuredThread/secured_transaction_threads.c b/SecuredThread/secured_transaction_threads.c index ade36e4..f8c269f 100644 --- a/SecuredThread/secured_transaction_threads.c +++ b/SecuredThread/secured_transaction_threads.c @@ -18,11 +18,11 @@ #define BLUE "\033[34m" typedef struct { - int transactions; // Nombre de transactions à effectuer - int account_count; // Nombre de comptes disponibles - int transactions_done; // Nombre de transactions effectuées + int transactions; // Nombre de transactions à effectuer + int account_count; // Nombre de comptes disponibles + int transactions_done; // Nombre de transactions effectuées int transactions_failed; // Nombre de transactions annulées - int total_transfered; // Montant total transféré par le thread + int total_transfered; // Montant total transféré par le thread } ThreadData; pthread_mutex_t file_mutex; // Mutex pour protéger l'accès au fichier diff --git a/Unsecured/README.md b/Unsecured/README.md index 4a09d44..ae61124 100644 --- a/Unsecured/README.md +++ b/Unsecured/README.md @@ -37,9 +37,9 @@ Exécutez le programme en spécifiant : Exemple : ```bash -./unsecured_transaction 4 10 +./unsecured_transaction 15 30 ``` -Ici, 4 processus seront lancés, chacun effectuant 10 transactions. +Ici, 15 processus seront lancés, chacun effectuant 30 transactions. --- diff --git a/Unsecured/unsecured_transaction.c b/Unsecured/unsecured_transaction.c index c22fc51..7b557e4 100644 --- a/Unsecured/unsecured_transaction.c +++ b/Unsecured/unsecured_transaction.c @@ -17,36 +17,85 @@ #define PINK "\033[35m" #define BLUE "\033[34m" -// Fonction pour lire un compte dans le fichier avec verrouillage +/** + * @brief Écrit les informations d'un compte dans un fichier sans verrouillage. + * + * Cette fonction écrit un compte spécifié par son index dans le fichier + * spécifié par le descripteur de fichier. Avant d'écrire, elle formate les + * données du compte (nom et solde) pour les rendre compatibles avec la taille + * d'un enregistrement. + * + * @param fd Le descripteur de fichier du fichier contenant les comptes. + * @param index L'index du compte à écrire (en termes de position dans le fichier). + * @param name Le nom du compte à écrire. + * @param balance Le solde du compte à écrire. + * + */ void read_account(int fd, int index, char *name, int *balance) { char buffer[ACCOUNT_SIZE]; + // Se positionner à l'index du compte dans le fichier lseek(fd, index * ACCOUNT_SIZE, SEEK_SET); + + // Lire l'enregistrement du compte read(fd, buffer, ACCOUNT_SIZE); + + // Extraire le nom et le solde du compte sscanf(buffer, "%7s %d", name, balance); } -// Fonction pour écrire un compte dans le fichier avec verrouillage + +/** + * @brief Écrit les informations d'un compte dans un fichier sans verrouillage. + * + * Cette fonction écrit un compte spécifié par son index dans le fichier + * spécifié par le descripteur de fichier. Avant d'écrire, elle formate les + * données du compte (nom et solde) pour les rendre compatibles avec la taille + * d'un enregistrement. + * + * @param fd Le descripteur de fichier du fichier contenant les comptes. + * @param index L'index du compte à écrire (en termes de position dans le fichier). + * @param name Le nom du compte à écrire. + * @param balance Le solde du compte à écrire. + * + */ void write_account(int fd, int index, const char *name, int balance) { char buffer[ACCOUNT_SIZE]; - // Formater la chaîne avec un nom de 10 caractères et un solde de 5 caractères, espace rempli si nécessaire + // Formater la chaîne avec un nom et un solde snprintf(buffer, ACCOUNT_SIZE, "%-7s%8d", name, balance); // S'assurer que le buffer est exactement de taille ACCOUNT_SIZE for (int i = strlen(buffer); i < ACCOUNT_SIZE - 1; i++) { buffer[i] = ' '; } - buffer[ACCOUNT_SIZE - 1] = '\n'; // Assurez-vous que la ligne est terminée correctement + buffer[ACCOUNT_SIZE - 1] = '\n'; // S'assurer que la ligne est terminée correctement lseek(fd, index * ACCOUNT_SIZE, SEEK_SET); write(fd, buffer, ACCOUNT_SIZE); } -// Fonction pour effectuer une transaction avec verrouillage +/** + * @brief Effectue une transaction aléatoire entre deux comptes sans verrouillage. + * + * Cette fonction simule une transaction entre deux comptes distincts sélectionnés + * aléatoirement. Le montant transféré est calculé aléatoirement et ne dépasse pas + * 20% du solde du compte source. + * + * @param fd Le descripteur de fichier du fichier contenant les comptes. + * @param account_count Le nombre total de comptes dans le fichier. + * + * @note Les comptes source et destination sont choisis de manière aléatoire, + * mais un compte ne peut pas transférer à lui-même. + * @note La transaction est annulée si le solde du compte source est insuffisant + * pour effectuer un transfert minimal. + * + */ void perform_transaction(int fd, int account_count) { int from_idx = rand() % account_count; int to_idx = rand() % account_count; + + // Sélectionner un autre compte si source et destination sont identiques while (from_idx == to_idx) { to_idx = rand() % account_count; } @@ -77,7 +126,26 @@ void perform_transaction(int fd, int account_count) { } } -// Fonction pour un processus de transactions +/** + * @brief Effectue un ensemble de transactions dans un processus. + * + * Cette fonction ouvre le fichier contenant les comptes en mode lecture/écriture + * et effectue un nombre donné de transactions aléatoires. Chaque transaction est + * réalisée en appelant la fonction `perform_transaction`. Une temporisation aléatoire + * est introduite entre les transactions pour simuler un comportement réaliste. + * + * @param transactions Le nombre de transactions à effectuer. + * @param account_count Le nombre total de comptes dans le fichier. + * + * @note La fonction ouvre le fichier spécifié par `FILENAME` en mode lecture/écriture. + * Elle s'assure de le fermer correctement à la fin. + * + * @warning Si l'ouverture du fichier échoue, la fonction interrompt le programme + * avec un appel à `exit(1)`. + * + * @details + * - La temporisation introduite par `usleep` (avec une durée aléatoire) contribue à la simulation d'un trafic réseau ou de retards dans les transactions. + */ void process_transactions(int transactions, int account_count) { int fd = open(FILENAME, O_RDWR); if (fd < 0) { @@ -87,12 +155,29 @@ void process_transactions(int transactions, int account_count) { for (int i = 0; i < transactions; i++) { perform_transaction(fd, account_count); - //usleep(rand() % 100000); // Temporisation aléatoire + usleep(rand() % 100000); // Temporisation aléatoire } close(fd); } +/** + * @brief Calcule le solde total de tous les comptes dans le fichier. + * + * Cette fonction parcourt tous les comptes stockés dans le fichier spécifié + * par `FILENAME`, en lisant leurs soldes et en les additionnant pour produire + * un solde total. Elle ouvre le fichier en mode lecture seule, le parcourt + * compte par compte, puis le ferme avant de retourner le résultat. + * + * @return Le solde total de tous les comptes, ou -1 en cas d'erreur + * (par exemple, si l'ouverture du fichier échoue). + * + * @note La taille de chaque compte est définie par la constante `ACCOUNT_SIZE`. + * + * @warning Cette fonction ne valide pas les données des comptes lues depuis le fichier. + * Elle suppose que les données sont correctement formatées. + * + */ int calculate_total_balance() { int fd = open(FILENAME, O_RDONLY); if (fd < 0) { @@ -116,15 +201,21 @@ int calculate_total_balance() { return total_balance; } +// Fonction principale int main(int argc, char *argv[]) { + // Vérifier que deux arguments sont passés en paramètre if (argc != 3) { fprintf(stderr, "Usage: %s <number_of_processes> <transactions_per_process>\n", argv[0]); return 1; } + // Extraire le nombre de processus et le nombre de transactions par processus int num_processes = atoi(argv[1]); int transactions_per_process = atoi(argv[2]); + // Initialiser une graine aléatoire basée sur l'ID de processus et l'heure actuelle + // On aurait aussi pu utiliser la fonction rand() directement, mais rand_r() est plus sûr + // Car il permet d'éviter les interférences entre les processus unsigned int seed = getpid() ^ time(NULL); int random_value = rand_r(&seed); @@ -168,6 +259,7 @@ int main(int argc, char *argv[]) { } printf("Solde total final : %d€\n", final_balance); + // Vérifier que le solde initial et le solde final sont identiques if (initial_balance != final_balance) { printf("Le solde final est différent du solde initial...\n"); }