summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSanto Cariotti <santo@dcariotti.me>2021-09-25 20:20:59 +0200
committerSanto Cariotti <santo@dcariotti.me>2021-09-26 00:45:20 +0200
commitf6bf5e48ecaa499faaa1483e9d5c1e5718424eb9 (patch)
tree32d87d1a894f6e2299f119dcf403ef179a7e7a6d
parent08860d002a81ca71406c49c33e300441bc110d50 (diff)
os: add exercise 2021-09-15
-rw-r--r--Year_2/OS/lookup-database.c346
1 files changed, 346 insertions, 0 deletions
diff --git a/Year_2/OS/lookup-database.c b/Year_2/OS/lookup-database.c
new file mode 100644
index 0000000..d600898
--- /dev/null
+++ b/Year_2/OS/lookup-database.c
@@ -0,0 +1,346 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/ipc.h>
+#include <sys/sem.h>
+#include <sys/shm.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <unistd.h>
+
+#define DIM_MSG 1024
+
+typedef struct {
+ char name[256];
+ int value;
+} pairs;
+
+typedef struct {
+ int n;
+ long value;
+} out_row;
+
+int
+WAIT(int id_sem, int n)
+{
+ struct sembuf sops[1] = { { n, -1, 0 } };
+ return semop(id_sem, sops, 1);
+}
+
+int
+SIGNAL(int id_sem, int n)
+{
+ struct sembuf sops[1] = { { n, 1, 0 } };
+ return semop(id_sem, sops, 1);
+}
+
+pairs*
+find_row(char* name, pairs* rows, int n)
+{
+ for (int i = 0; i < n; ++i) {
+ if (strcmp(rows[i].name, name) == 0)
+ return &rows[i];
+ }
+
+ return NULL;
+}
+
+void
+parse_rows(FILE* f, pairs* rows)
+{
+ int i, ci; /* ci stands for character index */
+ char* token;
+ char buf[1024];
+ int pi; /* pi stands for pair index */
+ i = ci = 0;
+ char ch;
+
+ while ((ch = (char)fgetc(f)) != EOF) {
+ if (ch != '\n') {
+ buf[ci++] = ch;
+ } else {
+ buf[ci] = '\0';
+ token = strtok(buf, ";");
+ if (token == NULL) {
+ goto free_and_return;
+ }
+
+ pi = 0;
+ while (token != NULL) {
+ if (pi == 0) {
+ strcpy(rows[i].name, token);
+ } else if (pi == 1) {
+ rows[i].value = atoi(token);
+ } else {
+ goto free_and_return;
+ }
+ pi++;
+ token = strtok(NULL, ";");
+ }
+
+ ci = 0;
+ i++;
+ }
+ }
+
+ return;
+
+free_and_return:
+ perror("<db-file> has a bad format");
+ free(rows);
+ exit(1);
+}
+
+void
+db(pairs* rows, char* db_path, int id_shm_db_in, int id_shm_db_out, int id_sem, int fin_n)
+{
+ FILE* f;
+ int n; /* It represents the number of lines of the file <db-file> */
+ char ch;
+ char* msg;
+ char* msgout;
+ int count_newline;
+ char* token;
+ int in_n;
+ pairs* row;
+
+ if ((f = fopen(db_path, "r")) == NULL) {
+ perror("fopen");
+ exit(1);
+ }
+
+ n = 0;
+ while ((ch = (char)fgetc(f)) != EOF) {
+ if (ch == '\n')
+ n++;
+ }
+
+ fseek(f, 0, SEEK_SET);
+ rows = malloc(sizeof(pairs) * n);
+ parse_rows(f, rows);
+ fclose(f);
+
+ printf("DB: letti n. %d record da file\n", n);
+
+ if ((msg = (char*)shmat(id_shm_db_in, NULL, 0)) == (char*)-1) {
+ perror("shmat");
+ exit(1);
+ }
+
+ if ((msgout = (char*)shmat(id_shm_db_out, NULL, 0)) == (char*)-1) {
+ perror("shmat");
+ exit(1);
+ }
+
+ count_newline = 0;
+ while (count_newline < fin_n) {
+ WAIT(id_sem, 0);
+ if (strcmp(msg, "") == 0) {
+ count_newline++;
+ } else {
+ token = strtok(msg, ";");
+ in_n = atoi(token);
+ token = strtok(NULL, ";");
+ row = find_row(token, rows, n);
+ if (row == NULL) {
+ printf("DB: query '%s' da IN%d non trovata\n", token, in_n);
+ } else {
+ WAIT(id_sem, 3);
+ sprintf(msgout, "%d;%s;%d", in_n, row->name, row->value);
+ SIGNAL(id_sem, 2);
+ printf("DB: query '%s' da IN%d trovata con valore %d\n", token, in_n, row->value);
+ }
+ }
+ SIGNAL(id_sem, 1);
+ }
+
+ WAIT(id_sem, 3);
+ strcpy(msgout, "");
+ SIGNAL(id_sem, 2);
+}
+
+void
+out(int id_shm_db_out, int id_sem, int fin_n)
+{
+ char* msg;
+ out_row* processes; /* at i-index there is the data of process-i */
+ char* token;
+ int* n = &fin_n;
+ int index;
+ int i;
+
+ processes = malloc(sizeof(out_row) * (*n));
+ for (i = 0; i < *n; ++i) {
+ processes[i].n = 0;
+ processes[i].value = 0;
+ }
+
+ if ((msg = (char*)shmat(id_shm_db_out, NULL, 0)) == (char*)-1) {
+ perror("shmat");
+ exit(1);
+ }
+
+ while (1) {
+ WAIT(id_sem, 2);
+
+ if (strcmp(msg, "") == 0)
+ break;
+
+ token = strtok(msg, ";");
+ index = atoi(token);
+ strtok(NULL, ";"); /* Ignore the `name` param */
+ token = strtok(NULL, ";");
+ processes[index - 1].n++;
+ processes[index - 1].value += atol(token);
+
+ SIGNAL(id_sem, 3);
+ }
+
+ for (i = 0; i < *n; ++i) {
+ printf("OUT: ricevuti n.%d valori validi per IN%d con totale %lu\n", processes[i].n, i + 1, processes[i].value);
+ }
+
+ free(processes);
+}
+
+void
+fn_in(int id_in, char* input_file, int id_shm_db_in, int id_sem)
+{
+ FILE* f;
+ char buf[DIM_MSG];
+ char ch;
+ int ci;
+ char* msg;
+ int i;
+ char id_in_str[5]; /* Max process is 99999 */
+
+ sprintf(id_in_str, "%d", id_in);
+
+ if ((f = fopen(input_file, "r")) == NULL) {
+ perror("fopen");
+ exit(1);
+ }
+
+ if ((msg = (char*)shmat(id_shm_db_in, NULL, 0)) == (char*)-1) {
+ perror("shmat");
+ exit(1);
+ }
+
+ ci = strlen(id_in_str) + 1;
+ for (i = 0; i < strlen(id_in_str); ++i) {
+ buf[i] = id_in_str[i];
+ }
+ buf[i] = ';';
+
+ i = 1;
+
+ while ((ch = fgetc(f)) != EOF) {
+ buf[ci++] = ch;
+ if (ch == '\n') {
+ buf[ci - 1] = '\0';
+
+ WAIT(id_sem, 1);
+ /* Write the `buf` into the shared memory buffer with db */
+ strncpy(msg, buf, ci);
+
+ printf("IN%d: inviata query n.%d '%s'\n", id_in, i, msg + strlen(id_in_str) + 1);
+
+ ci = strlen(id_in_str) + 1;
+ SIGNAL(id_sem, 0);
+ i++;
+ }
+ }
+ WAIT(id_sem, 1);
+ strncpy(msg, "", 1);
+ SIGNAL(id_sem, 0);
+
+ fclose(f);
+}
+
+int
+main(int argc, char** argv)
+{
+ int i;
+ int id_shm_db_in;
+ int id_shm_db_out;
+ int id_sem;
+
+ pid_t pid_db;
+ pid_t pid_out;
+ pid_t pid_in[argc - 2];
+
+ pairs* rows;
+ rows = NULL;
+
+ if (argc < 3) {
+ fprintf(stderr, "Usage: %s <db-file> <query-file-1> [<query-file-2>] .. [<query-file-n>]", argv[0]);
+ exit(1);
+ }
+
+ /* Create the shared memory blocks */
+ if ((id_shm_db_in = shmget(IPC_PRIVATE, DIM_MSG, IPC_CREAT | 0644)) == -1) {
+ perror("shmget");
+ exit(1);
+ }
+
+ if ((id_shm_db_out = shmget(IPC_PRIVATE, DIM_MSG, IPC_CREAT | 0644)) == -1) {
+ perror("shmget");
+ exit(1);
+ }
+
+ /* These are two semaphore used as mutexs */
+ if ((id_sem = semget(IPC_PRIVATE, 4, IPC_CREAT | IPC_EXCL | 0644)) == -1) {
+ perror("semget");
+ exit(1);
+ }
+ /* Set values to 0 */
+ semctl(id_sem, 0, SETVAL, 0);
+ semctl(id_sem, 1, SETVAL, 1);
+ semctl(id_sem, 2, SETVAL, 0);
+ semctl(id_sem, 3, SETVAL, 1);
+
+ pid_db = fork();
+ if (pid_db == -1) {
+ perror("fork");
+ exit(1);
+ }
+
+ if (pid_db == 0) {
+ db(rows, argv[1], id_shm_db_in, id_shm_db_out, id_sem, argc - 2);
+ exit(0);
+ }
+
+ pid_out = fork();
+ if (pid_out == -1) {
+ perror("fork");
+ exit(1);
+ }
+
+ if (pid_out == 0) {
+ out(id_shm_db_out, id_sem, argc - 2);
+ exit(0);
+ }
+
+ for (i = 0; i < argc - 2; ++i) {
+ pid_in[i] = fork();
+ if (pid_in[i] == -1) {
+ perror("fork");
+ exit(1);
+ }
+
+ if (pid_in[i] == 0) {
+ fn_in(i + 1, argv[i + 2], id_shm_db_in, id_sem);
+ exit(0);
+ }
+ }
+
+ for (i = 0; i < argc; ++i)
+ wait(NULL);
+
+ shmctl(id_shm_db_in, IPC_RMID, 0);
+ shmctl(id_shm_db_out, IPC_RMID, 0);
+ semctl(id_sem, 4, IPC_RMID);
+ free(rows);
+
+ return 0;
+}