Amélioration
This commit is contained in:
parent
1fdba01789
commit
70bb4fd94e
@ -40,9 +40,9 @@ Exécutez le programme en spécifiant :
|
|||||||
|
|
||||||
Exemple :
|
Exemple :
|
||||||
```bash
|
```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.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
@ -18,11 +18,11 @@
|
|||||||
#define BLUE "\033[34m"
|
#define BLUE "\033[34m"
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
int transactions; // Nombre de transactions à effectuer
|
int transactions; // Nombre de transactions à effectuer
|
||||||
int account_count; // Nombre de comptes disponibles
|
int account_count; // Nombre de comptes disponibles
|
||||||
int transactions_done; // Nombre de transactions effectuées
|
int transactions_done; // Nombre de transactions effectuées
|
||||||
int transactions_failed; // Nombre de transactions annulé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;
|
} ThreadData;
|
||||||
|
|
||||||
pthread_mutex_t file_mutex; // Mutex pour protéger l'accès au fichier
|
pthread_mutex_t file_mutex; // Mutex pour protéger l'accès au fichier
|
||||||
|
@ -37,9 +37,9 @@ Exécutez le programme en spécifiant :
|
|||||||
|
|
||||||
Exemple :
|
Exemple :
|
||||||
```bash
|
```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.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
@ -17,36 +17,85 @@
|
|||||||
#define PINK "\033[35m"
|
#define PINK "\033[35m"
|
||||||
#define BLUE "\033[34m"
|
#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) {
|
void read_account(int fd, int index, char *name, int *balance) {
|
||||||
char buffer[ACCOUNT_SIZE];
|
char buffer[ACCOUNT_SIZE];
|
||||||
|
|
||||||
|
// Se positionner à l'index du compte dans le fichier
|
||||||
lseek(fd, index * ACCOUNT_SIZE, SEEK_SET);
|
lseek(fd, index * ACCOUNT_SIZE, SEEK_SET);
|
||||||
|
|
||||||
|
// Lire l'enregistrement du compte
|
||||||
read(fd, buffer, ACCOUNT_SIZE);
|
read(fd, buffer, ACCOUNT_SIZE);
|
||||||
|
|
||||||
|
// Extraire le nom et le solde du compte
|
||||||
sscanf(buffer, "%7s %d", name, balance);
|
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) {
|
void write_account(int fd, int index, const char *name, int balance) {
|
||||||
char buffer[ACCOUNT_SIZE];
|
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);
|
snprintf(buffer, ACCOUNT_SIZE, "%-7s%8d", name, balance);
|
||||||
|
|
||||||
// S'assurer que le buffer est exactement de taille ACCOUNT_SIZE
|
// S'assurer que le buffer est exactement de taille ACCOUNT_SIZE
|
||||||
for (int i = strlen(buffer); i < ACCOUNT_SIZE - 1; i++) {
|
for (int i = strlen(buffer); i < ACCOUNT_SIZE - 1; i++) {
|
||||||
buffer[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);
|
lseek(fd, index * ACCOUNT_SIZE, SEEK_SET);
|
||||||
write(fd, buffer, ACCOUNT_SIZE);
|
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) {
|
void perform_transaction(int fd, int account_count) {
|
||||||
int from_idx = rand() % account_count;
|
int from_idx = rand() % account_count;
|
||||||
int to_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) {
|
while (from_idx == to_idx) {
|
||||||
to_idx = rand() % account_count;
|
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) {
|
void process_transactions(int transactions, int account_count) {
|
||||||
int fd = open(FILENAME, O_RDWR);
|
int fd = open(FILENAME, O_RDWR);
|
||||||
if (fd < 0) {
|
if (fd < 0) {
|
||||||
@ -87,12 +155,29 @@ void process_transactions(int transactions, int account_count) {
|
|||||||
|
|
||||||
for (int i = 0; i < transactions; i++) {
|
for (int i = 0; i < transactions; i++) {
|
||||||
perform_transaction(fd, account_count);
|
perform_transaction(fd, account_count);
|
||||||
//usleep(rand() % 100000); // Temporisation aléatoire
|
usleep(rand() % 100000); // Temporisation aléatoire
|
||||||
}
|
}
|
||||||
|
|
||||||
close(fd);
|
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 calculate_total_balance() {
|
||||||
int fd = open(FILENAME, O_RDONLY);
|
int fd = open(FILENAME, O_RDONLY);
|
||||||
if (fd < 0) {
|
if (fd < 0) {
|
||||||
@ -116,15 +201,21 @@ int calculate_total_balance() {
|
|||||||
return total_balance;
|
return total_balance;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Fonction principale
|
||||||
int main(int argc, char *argv[]) {
|
int main(int argc, char *argv[]) {
|
||||||
|
// Vérifier que deux arguments sont passés en paramètre
|
||||||
if (argc != 3) {
|
if (argc != 3) {
|
||||||
fprintf(stderr, "Usage: %s <number_of_processes> <transactions_per_process>\n", argv[0]);
|
fprintf(stderr, "Usage: %s <number_of_processes> <transactions_per_process>\n", argv[0]);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Extraire le nombre de processus et le nombre de transactions par processus
|
||||||
int num_processes = atoi(argv[1]);
|
int num_processes = atoi(argv[1]);
|
||||||
int transactions_per_process = atoi(argv[2]);
|
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);
|
unsigned int seed = getpid() ^ time(NULL);
|
||||||
int random_value = rand_r(&seed);
|
int random_value = rand_r(&seed);
|
||||||
|
|
||||||
@ -168,6 +259,7 @@ int main(int argc, char *argv[]) {
|
|||||||
}
|
}
|
||||||
printf("Solde total final : %d€\n", final_balance);
|
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) {
|
if (initial_balance != final_balance) {
|
||||||
printf("Le solde final est différent du solde initial...\n");
|
printf("Le solde final est différent du solde initial...\n");
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user