#include #include #include #include #include #include #include #include #include "key_value_pair.h" #include "transfer_defines.h" typedef struct{ int port; char *data; TYPE type; }THREAD_ARGS; pthread_mutex_t words_mutex; char *words_list; char *get_file_content(FILE *fp) { char *buffer = (char*)malloc(sizeof(char) * MESSAGE_LENGTH); if (buffer == NULL) { perror("Failed to allocate memory for buffer"); return NULL; } const size_t bytes_read = fread(buffer, sizeof(char), MESSAGE_LENGTH - 1, fp); if (bytes_read == 0) { perror("File is empty or nothing is left to read"); free(buffer); return NULL; } buffer[bytes_read] = '\0'; int delimiter_pos = (int)bytes_read - 1; while (delimiter_pos >= 0 && !isalpha(buffer[delimiter_pos])) { delimiter_pos--; } if (delimiter_pos < 0) { printf("No delimiting character was found -> taking whole buffer"); delimiter_pos = (int)bytes_read; } buffer[delimiter_pos + 1] = '\0'; if (fseek(fp, delimiter_pos - (int) bytes_read + 2, SEEK_CUR) != 0) { perror("Failed to seek in file"); free(buffer); return NULL; } return buffer; } void *receiverFunc(void *args) { THREAD_ARGS *params = (THREAD_ARGS*)args; void *context = zmq_ctx_new(); if(!context){ perror("[THREAD] Failed to create context"); free(params); return NULL; } void *requester = zmq_socket(context, ZMQ_REQ); if(!requester){ perror("[THREAD] Failed to create socket"); free(params); zmq_ctx_destroy(context); return NULL; } char addr[22]; snprintf(addr, 21, "tcp://localhost:%d", params->port); int rc = zmq_connect(requester, addr); if (rc != 0){ perror("Failed to connect"); free(params); zmq_close(requester); zmq_ctx_destroy(context); return NULL; } printf("[THREAD] Connected to worker: %s\n", addr); size_t len = strlen(params->data) + 4; char *request = (char*)malloc(sizeof(char) * len); if(!request){ perror("[THREAD] Failed to allocate memory for request"); free(params); zmq_close(requester); zmq_ctx_destroy(context); return NULL; } switch(params->type){ case MAP: snprintf(request, len, "map%s", params->data); break; case RED: snprintf(request, len, "red%s", params->data); break; case RIP: snprintf(request, len, "rip"); break; default: perror("[THREAD] Got unsupported request"); free(params); free(request); zmq_close(requester); zmq_ctx_destroy(context); return NULL; } printf("[THREAD] Sent request: %s\n", request); if(zmq_send(requester, request, strlen(request), 0) == -1){ perror("[THREAD] Failed to send request"); free(params); free(request); zmq_close(requester); zmq_ctx_destroy(context); return NULL; } free(request); printf("[THREAD]: Waiting for response\n"); char reply[MESSAGE_LENGTH]; int bytes_recv = zmq_recv(requester, reply, MESSAGE_LENGTH - 1, 0); if (bytes_recv == -1){ perror("[THREAD] Failed to receive reply"); free(params); zmq_close(requester); zmq_ctx_destroy(context); return NULL; } reply[bytes_recv] = '\0'; if(strcmp(reply, "rip") == 0){ free(params); zmq_close(requester); zmq_ctx_destroy(context); return NULL; } pthread_mutex_lock(&words_mutex); len = strlen(reply); if(!words_list){ words_list = (char*)malloc(len + 1); if(!words_list){ perror("[THREAD] Failed to allocate memory for words_list"); free(params); pthread_mutex_unlock(&words_mutex); zmq_close(requester); zmq_ctx_destroy(context); return NULL; } } else{ char *tmp = realloc(words_list , sizeof(char) * (strlen(words_list) + len + 1)); if(tmp == NULL){ perror("[THREAD] Failed to realloc memory for words_list"); free(params); pthread_mutex_unlock(&words_mutex); zmq_close(requester); zmq_ctx_destroy(context); return NULL; } words_list = tmp; } strcat(words_list, reply); free(params); pthread_mutex_unlock(&words_mutex); zmq_close(requester); zmq_ctx_destroy(context); return NULL; } int main(const int argc, char **argv) { if(argc < 3){ fprintf(stderr, "Usage: %s ... ", argv[0]); exit(1); } pthread_mutex_init(&words_mutex, NULL); FILE *fp = fopen(argv[1], "r"); char *file_content_chunks; int worker_index = 2; int worker_count = argc - 2; int thread_count = 0; pthread_t *threads = (pthread_t*)malloc(sizeof(pthread_t) * worker_count); while (thread_count < worker_count && (file_content_chunks = get_file_content(fp)) != NULL) { pthread_t receiver; THREAD_ARGS *args = (THREAD_ARGS*)malloc(sizeof(THREAD_ARGS)); if(!args){ perror("[MAIN] Failed to allocate memory for args"); free(threads); pthread_mutex_destroy(&words_mutex); exit(1); } args->port = atol(argv[worker_index]); args->data = strdup(file_content_chunks); args->type = MAP; if(pthread_create(&threads[thread_count++], NULL, receiverFunc, (void*)args) != 0){ perror("[MAIN] Failed to create thread"); free(args); free(threads); pthread_mutex_destroy(&words_mutex); exit(1); } free(file_content_chunks); worker_index++; } fclose(fp); // wait for workers to finish for(int i = 0; i < thread_count; i++){ pthread_join(threads[i], NULL); } free(threads); printf("MAP:\n%s\n\n", words_list); // TODO: REDUCE // TODO: RIP return 0; }