diff --git a/Secured/secured_transaction.c b/Secured/secured_transaction.c index e69de29..b8e70b0 100644 --- a/Secured/secured_transaction.c +++ b/Secured/secured_transaction.c @@ -0,0 +1,179 @@ +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <fcntl.h> +#include <time.h> +#include <sys/wait.h> +#include <string.h> + +#define ACCOUNT_SIZE 16 +#define MAX_NAME_LEN 10 +#define MAX_BALANCE_LEN 5 +#define FILENAME "../Data/accounts.db" + +// Fonction pour lire un compte dans le fichier avec verrouillage +void read_account(int fd, int index, char *name, int *balance) { + char buffer[ACCOUNT_SIZE]; + + // Placer un verrou exclusif sur la section du fichier correspondant au compte + lockf(fd, F_LOCK, ACCOUNT_SIZE); + lseek(fd, index * ACCOUNT_SIZE, SEEK_SET); + read(fd, buffer, ACCOUNT_SIZE); + sscanf(buffer, "%10s %d", name, balance); + // Libérer le verrou après lecture + lockf(fd, F_ULOCK, ACCOUNT_SIZE); +} + +// Fonction pour écrire un compte dans le fichier avec verrouillage +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 + snprintf(buffer, ACCOUNT_SIZE, "%-10s%5d", 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 + + // Placer un verrou exclusif sur la section du fichier correspondant au compte + lockf(fd, F_LOCK, ACCOUNT_SIZE); + lseek(fd, index * ACCOUNT_SIZE, SEEK_SET); + write(fd, buffer, ACCOUNT_SIZE); + // Libérer le verrou après écriture + lockf(fd, F_ULOCK, ACCOUNT_SIZE); +} + +// Fonction pour effectuer une transaction avec verrouillage +void perform_transaction(int fd, int account_count) { + int from_idx = rand() % account_count; + int to_idx = rand() % account_count; + while (from_idx == to_idx) { + to_idx = rand() % account_count; + } + + char from_name[MAX_NAME_LEN], to_name[MAX_NAME_LEN]; + int from_balance, to_balance; + + // Lire les comptes source et destination + read_account(fd, from_idx, from_name, &from_balance); + read_account(fd, to_idx, to_name, &to_balance); + + // Calculer un montant aléatoire à transférer (max 20% du solde source) + int max_transfer = from_balance / 5; + if (max_transfer > 0) { + int transfer_amount = rand() % max_transfer; + + // Effectuer la transaction + from_balance -= transfer_amount; + to_balance += transfer_amount; + + // Écrire les nouveaux soldes dans le fichier + write_account(fd, from_idx, from_name, from_balance); + write_account(fd, to_idx, to_name, to_balance); + + printf("Transaction : %s -> %s : %d€\n", from_name, to_name, transfer_amount); + } else { + printf("Transaction annulée : Fonds insufisants %s\n", from_name); + } +} + +// Fonction pour un processus de transactions +void process_transactions(int transactions, int account_count) { + int fd = open(FILENAME, O_RDWR); + if (fd < 0) { + perror("Erreur : Impossible d'ouvrir le fichier"); + exit(1); + } + + for (int i = 0; i < transactions; i++) { + perform_transaction(fd, account_count); + //usleep(rand() % 100000); // Temporisation aléatoire + } + + close(fd); +} + +int calculate_total_balance() { + int fd = open(FILENAME, O_RDONLY); + if (fd < 0) { + perror("Erreur : Impossible d'ouvrir le fichier"); + return -1; + } + + off_t file_size = lseek(fd, 0, SEEK_END); + int account_count = file_size / ACCOUNT_SIZE; + + int total_balance = 0; + char name[MAX_NAME_LEN]; + int balance; + + for (int i = 0; i < account_count; i++) { + read_account(fd, i, name, &balance); + total_balance += balance; + } + + close(fd); + return total_balance; +} + +int main(int argc, char *argv[]) { + if (argc != 3) { + fprintf(stderr, "Usage: %s <number_of_processes> <transactions_per_process>\n", argv[0]); + return 1; + } + + int num_processes = atoi(argv[1]); + int transactions_per_process = atoi(argv[2]); + + srand(time(NULL)); + + // Calcul du solde total initial + int initial_balance = calculate_total_balance(); + if (initial_balance < 0) { + return 1; // Erreur lors de l'ouverture du fichier + } + printf("Solde total initial : %d€\n", initial_balance); + + // Ouvrir le fichier pour déterminer le nombre de comptes + int fd = open(FILENAME, O_RDONLY); + if (fd < 0) { + perror("Erreur : Impossible d'ouvrir le fichier"); + return 1; + } + off_t file_size = lseek(fd, 0, SEEK_END); + close(fd); + + int account_count = file_size / ACCOUNT_SIZE; + + printf("Nombre de comptes : %d\n", account_count); + + // Créer les processus enfants + for (int i = 0; i < num_processes; i++) { + if (fork() == 0) { + process_transactions(transactions_per_process, account_count); + exit(0); + } + } + + // Attendre les processus enfants + for (int i = 0; i < num_processes; i++) { + wait(NULL); + } + + // Calcul du solde total final + int final_balance = calculate_total_balance(); + if (final_balance < 0) { + return 1; // Erreur lors de l'ouverture du fichier + } + printf("Solde total final : %d€\n", final_balance); + + if (initial_balance != final_balance) { + printf("Le solde final est différent du solde initial...\n"); + } + + printf("Tout les processus sont terminés !\n"); + + return 0; +}