Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <stdbool.h>
- #include <errno.h>
- #include <fcntl.h>
- #include <sys/mman.h>
- #include <unistd.h>
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include <sys/wait.h>
- #include <semaphore.h>
- #define MAX_CHILDREN 1024
- struct LOGS
- {
- char op[256];
- int suc;
- int number_transaction, value, destination_1, destination_2, new_balance, new_balance2, failure1, failure2;
- };
- void init(struct LOGS *log)
- {
- memset(log->op, 0, 255);
- log->number_transaction = 0;
- log->value = 0;
- log->destination_1 = 0;
- log->destination_2 = 0;
- log->suc = 0;
- log->new_balance = 0;
- log->new_balance2 = 0;
- log->failure1 = 0;
- log->failure2 = 0;
- }
- int is_digit(char c)
- {
- return (c >= '0' && c <= '9');
- }
- int process_transaction(char *operation, int *accounts, struct LOGS *logs, sem_t *account_semaphore, int id)
- {
- sem_wait(account_semaphore);
- int idx = 0, save_i;
- char *cpy = (char*) malloc(128 * sizeof(char));
- pid_t child_pids[MAX_CHILDREN];
- memset(child_pids, 0, MAX_CHILDREN * sizeof(pid_t));
- for(int j = 0; j < strlen(operation); ++j)
- {
- if(operation[j] == '(')
- {
- save_i = j;
- cpy[idx] = '\0';
- break;
- }
- cpy[idx++] = operation[j];
- }
- if(!strcmp(cpy, "Withdraw"))
- {
- int sum = 0, dest = 0;
- save_i++;
- while(operation[save_i] != '\0' && is_digit(operation[save_i]))
- {
- sum = sum * 10 + (operation[save_i] - '0');
- save_i++;
- }
- save_i += 2;
- while(operation[save_i] != '\0' && is_digit(operation[save_i]))
- {
- dest = dest * 10 + (operation[save_i] - '0');
- save_i++;
- }
- if(accounts[dest] - sum < 0)
- {
- logs[id].failure1 = accounts[dest];
- logs[id].suc = 0;
- strcpy(logs[id].op, cpy);
- logs[id].number_transaction = id;
- logs[id].value = sum;
- logs[id].destination_1 = dest;
- free(cpy);
- sem_post(account_semaphore);
- return 1;
- }
- else
- {
- accounts[dest] -= sum;
- logs[id].suc = 1;
- strcpy(logs[id].op, cpy);
- logs[id].number_transaction = id;
- logs[id].value = sum;
- logs[id].destination_1 = dest;
- logs[id].new_balance = accounts[dest];
- free(cpy);
- sem_post(account_semaphore);
- return 0;
- }
- }
- if(!strcmp(cpy, "Deposit"))
- {
- int sum = 0, dest = 0;
- save_i++;
- while(operation[save_i] != '\0' && is_digit(operation[save_i]))
- {
- sum = sum * 10 + operation[save_i] - '0';
- save_i++;
- }
- save_i += 2;
- while(operation[save_i] != '\0' && is_digit(operation[save_i]))
- {
- dest = dest * 10 + operation[save_i] - '0';
- save_i++;
- }
- accounts[dest] += sum;
- logs[id].suc = 1;
- strcpy(logs[id].op, cpy);
- logs[id].number_transaction = id;
- logs[id].value = sum;
- logs[id].destination_1 = dest;
- logs[id].new_balance = accounts[dest];
- free(cpy);
- sem_post(account_semaphore);
- return 0;
- }
- if(!strcmp(cpy, "Transfer"))
- {
- int sum = 0, dest1 = 0, dest2 = 0;
- save_i++;
- while(operation[save_i] != '\0' && is_digit(operation[save_i]))
- {
- sum = sum * 10 + operation[save_i] - '0';
- save_i++;
- }
- save_i += 2;
- while(operation[save_i] != '\0' && is_digit(operation[save_i]))
- {
- dest1 = dest1 * 10 + operation[save_i] - '0';
- save_i++;
- }
- save_i += 2;
- while(operation[save_i] != '\0' && is_digit(operation[save_i]))
- {
- dest2 = dest2 * 10 + operation[save_i] - '0';
- save_i++;
- }
- if(accounts[dest1] - sum < 0)
- {
- logs[id].failure1 = accounts[dest1];
- logs[id].failure2 = accounts[dest2];
- logs[id].suc = 0;
- strcpy(logs[id].op, cpy);
- logs[id].number_transaction = id;
- logs[id].value = sum;
- logs[id].destination_1 = dest1;
- logs[id].destination_2 = dest2;
- logs[id].new_balance = accounts[dest1];
- logs[id].new_balance2 = accounts[dest2];
- free(cpy);
- sem_post(account_semaphore);
- return 1;
- }
- else
- {
- accounts[dest1] -= sum;
- accounts[dest2] += sum;
- logs[id].suc = 1;
- strcpy(logs[id].op, cpy);
- logs[id].number_transaction = id;
- logs[id].value = sum;
- logs[id].destination_1 = dest1;
- logs[id].destination_2 = dest2;
- logs[id].new_balance = accounts[dest1];
- logs[id].new_balance2 = accounts[dest2];
- free(cpy);
- sem_post(account_semaphore);
- return 0;
- }
- }
- sem_post(account_semaphore);
- free(cpy);
- return 0;
- }
- int main()
- {
- setbuf(stdout, NULL);
- int n, count = 0;
- pid_t child_pids[MAX_CHILDREN];
- memset(child_pids, 0, MAX_CHILDREN);
- int fd_accounts = shm_open("/bank_account", O_CREAT | O_RDWR, 0666);
- int fd_retry = shm_open("/bank_retry", O_CREAT | O_RDWR, 0666);
- int fd_stats = shm_open("/bank_stats", O_CREAT | O_RDWR, 0666);
- int ld = shm_open("/logs", O_CREAT | O_RDWR, 0666);
- ftruncate(fd_accounts, 1024);
- ftruncate(fd_retry, 1024);
- ftruncate(fd_stats, 1024);
- ftruncate(ld, sizeof(struct LOGS) * 1024);
- scanf("%d", &n);
- if(n <= 0)
- {
- printf("Invalid number of accounts.\n");
- exit(0);
- }
- printf("\n");
- int *accounts = mmap(0, sizeof(int) * (n + 1), PROT_READ | PROT_WRITE, MAP_SHARED, fd_accounts, 0);
- int *before_retry = mmap(0, sizeof(int) * (n + 1), PROT_READ | PROT_WRITE, MAP_SHARED, fd_retry, 0);
- int *stats = mmap(0, sizeof(int) * (n + 1), PROT_READ | PROT_WRITE, MAP_SHARED, fd_stats, 0);
- struct LOGS *logs = mmap(0, sizeof(struct LOGS) * 1024, PROT_READ | PROT_WRITE, MAP_SHARED, ld, 0);
- for(int i = 0; i < 1000; ++i)
- {
- init(&logs[i]);
- }
- sem_t *account_semaphore = sem_open("/account_semaphore", O_CREAT, 0666, 1);
- printf("Initial account balances:\n");
- for(int i = 0; i < n; ++i)
- {
- int x;
- scanf("%d", &x);
- accounts[i] = x;
- printf("Account %d: %d\n", i, accounts[i]);
- }
- while (getchar() != '\n');
- int i = 0;
- char operations[MAX_CHILDREN][256];
- memset(operations, 0, sizeof(operations));
- int total_tx = 0;
- while(true)
- {
- if(!fgets(operations[total_tx], 256, stdin)) break;
- if(strlen(operations[total_tx]) <= 1) break;
- total_tx++;
- }
- for(int i = 0; i < total_tx; i++)
- {
- pid_t pid = fork();
- if(pid == 0)
- {
- int result = process_transaction(operations[i], accounts, logs, account_semaphore, i);
- exit(result);
- }
- else
- {
- child_pids[i] = pid;
- }
- }
- for (int j = 0; j < total_tx; j++)
- {
- int status;
- waitpid(child_pids[j], &status, 0);
- if (WEXITSTATUS(status) == 1)
- {
- printf("Transaction %d failed, retrying...\n", j);
- pid_t retry_pid = fork();
- if(retry_pid == 0)
- {
- int result = process_transaction(operations[j], accounts, logs, account_semaphore, j);
- exit(result);
- }
- else
- {
- waitpid(retry_pid, &status, 0);
- }
- }
- }
- int m = total_tx;
- printf("\nFinal account balances:\n");
- for(int i = 0; i < n; ++i)
- {
- printf("Account %d: %d\n", i, accounts[i]);
- }
- printf("\nTransaction Log (in order):\n");
- for(int i = 0; i < m; ++i)
- {
- if(strcmp(logs[i].op, "Withdraw") == 0)
- {
- if(logs[i].suc == 1)
- {
- printf("Transaction %d: Withdraw %d from Account %d (Success) New balance: %d\n",
- logs[i].number_transaction, logs[i].value, logs[i].destination_1, logs[i].new_balance);
- }
- else
- {
- printf("Transaction %d: Withdraw %d from Account %d (Failed) Current balance: %d\n",
- logs[i].number_transaction, logs[i].value, logs[i].destination_1, logs[i].failure1);
- }
- }
- if(strcmp(logs[i].op, "Deposit") == 0)
- {
- printf("Transaction %d: Deposit %d to Account %d (Success) New balance: %d\n",
- logs[i].number_transaction, logs[i].value, logs[i].destination_1, logs[i].new_balance);
- }
- if(strcmp(logs[i].op, "Transfer") == 0)
- {
- if(logs[i].suc == 1)
- {
- printf("Transaction %d: Transfer %d from Account %d to Account %d (Success) New balances: Account %d: %d, Account %d: %d\n",
- logs[i].number_transaction, logs[i].value, logs[i].destination_1, logs[i].destination_2,
- logs[i].destination_1, logs[i].new_balance, logs[i].destination_2, logs[i].new_balance2);
- }
- else
- {
- printf("Transaction %d: Transfer %d from Account %d to Account %d (Failed) Current balances: Account %d: %d, Account %d: %d\n",
- logs[i].number_transaction, logs[i].value, logs[i].destination_1, logs[i].destination_2,
- logs[i].destination_1, logs[i].failure1, logs[i].destination_2, logs[i].failure2);
- }
- }
- }
- munmap(accounts, sizeof(int) * (n + 1));
- munmap(logs, sizeof(struct LOGS) * 1024);
- sem_close(account_semaphore);
- shm_unlink("/logs");
- shm_unlink("/bank_account");
- sem_unlink("/account_semaphore");
- close(fd_accounts);
- close(fd_retry);
- close(fd_stats);
- close(ld);
- exit(0);
- return 0;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement