diff options
Diffstat (limited to 'pa6_threaded_resolver/multi-lookup.c')
-rw-r--r-- | pa6_threaded_resolver/multi-lookup.c | 256 |
1 files changed, 126 insertions, 130 deletions
diff --git a/pa6_threaded_resolver/multi-lookup.c b/pa6_threaded_resolver/multi-lookup.c index 2956b8f..a7e02dd 100644 --- a/pa6_threaded_resolver/multi-lookup.c +++ b/pa6_threaded_resolver/multi-lookup.c @@ -2,171 +2,167 @@ // CSCI3753 SP24 // PA6 Threaded Resolver #include "multi-lookup.h" +#include "array.h" +#include "util.h" #include <sys/time.h> int main(int argc, char **argv) { if (argc < 6) { fprintf(stderr, "usage: %s <# requester> <# resolver> <requester log> <resolver " - "log> [ <data file> ... ]\n", + "log> <data file(s)>\n", argv[0]); - return EXIT_FAILURE; + exit(EXIT_FAILURE); } else if (argc > MAX_INPUT_FILES + 6) { fprintf(stderr, "%s error: too many input files\n", argv[0]); return EXIT_FAILURE; } - struct timeval proc_begin, proc_end; - gettimeofday(&proc_begin, NULL); - uint8_t req_thread = atoi(argv[1]); - if (req_thread < 1) { + int req_thread_cnt = atoi(argv[1]); + if (req_thread_cnt < 1) { fprintf(stderr, "%s error: minimum 1 requester thread\n", argv[0]); return EXIT_FAILURE; - } else if (req_thread > MAX_REQUESTER_THREADS) { + } else if (req_thread_cnt > MAX_REQUESTER_THREADS) { fprintf(stderr, "%s error: requester threads cannot exceed %d\n", argv[0], MAX_REQUESTER_THREADS); return EXIT_FAILURE; } - uint8_t res_threads = atoi(argv[2]); - if (res_threads < 1) { + int res_thread_cnt = atoi(argv[2]); + if (res_thread_cnt < 1) { fprintf(stderr, "%s error: minimum 1 resolver thread\n", argv[0]); return EXIT_FAILURE; - } else if (res_threads > MAX_RESOLVER_THREADS) { + } else if (res_thread_cnt > MAX_RESOLVER_THREADS) { fprintf(stderr, "%s error: resolver threads cannot exceed %d\n", argv[0], MAX_RESOLVER_THREADS); return EXIT_FAILURE; } - queue input_files; - queue_init(&input_files, MAX_INPUT_FILES); + double start_time = get_time_sec(); + array stack; + array_init(&stack); + struct requester_data req_data; + struct resolver_data res_data; + req_data.stack = &stack; + res_data.stack = &stack; + req_data.req_log = argv[3]; + res_data.res_log = argv[4]; + pthread_mutex_init(&res_data.res_log_lock, NULL); + pthread_mutex_init(&req_data.req_log_lock, NULL); + pthread_mutex_init(&res_data.term_lock, NULL); + req_data.res_thread_cnt = res_thread_cnt; + res_data.res_thread_cnt = res_thread_cnt; + int total_files = argc - 5; + char **filenames = (char **)malloc(total_files * sizeof(char *)); for (int i = 5; i < argc; i++) { - if (access(argv[i], F_OK) == -1) - fprintf(stderr, "%s error: invalid data file '%s'\n", argv[0], argv[i]); - else - queue_push(&input_files, strndup(argv[i], strlen(argv[i]))); - } - if (!queue_size(&input_files)) { - fprintf(stderr, "%s error: no valid data file given\n", argv[0]); - return EXIT_FAILURE; + filenames[i - 5] = (char *)malloc((strlen(argv[i]) + 1) * sizeof(char)); + strcpy(filenames[i - 5], argv[i]); } - pthread_mutex_t m = PTHREAD_MUTEX_INITIALIZER; - pthread_cond_t c_req = PTHREAD_COND_INITIALIZER; - pthread_cond_t c_res = PTHREAD_COND_INITIALIZER; - pthread_mutex_t input_lock = PTHREAD_MUTEX_INITIALIZER; - pthread_mutex_t req_log_lock = PTHREAD_MUTEX_INITIALIZER; - pthread_mutex_t res_log_lock = PTHREAD_MUTEX_INITIALIZER; - bool req_done = 0; - queue buffer; - queue_init(&buffer, ARRAY_SIZE); - request_data req_data; - req_data.req_log = fopen(argv[3], "w"); - req_data.file_names = &input_files; - req_data.buffer = &buffer; - req_data.m = &m; - req_data.c_req = &c_req; - req_data.c_res = &c_res; - req_data.input_lock = &input_lock; - req_data.req_log_lock = &req_log_lock; - resolve_data res_data; - res_data.res_log = fopen(argv[4], "w"); - res_data.buffer = &buffer; - res_data.m = &m; - res_data.c_req = &c_req; - res_data.c_res = &c_res; - res_data.res_log_lock = &res_log_lock; - res_data.req_done = &req_done; - pthread_t request_tid[req_thread]; - pthread_t resolve_tid[res_threads]; - for (int i = 0; i < req_thread; i++) - pthread_create(&request_tid[i], NULL, request, &req_data); - for (int i = 0; i < res_threads; i++) - pthread_create(&resolve_tid[i], NULL, resolve, &res_data); - for (int i = 0; i < req_thread; i++) - pthread_join(request_tid[i], NULL); - pthread_mutex_lock(&m); - req_done = 1; - pthread_mutex_unlock(&m); - for (int i = 0; i < res_threads; i++) - pthread_join(resolve_tid[i], NULL); - fclose(req_data.req_log); - fclose(res_data.res_log); - queue_free(&input_files); - queue_free(&buffer); - printf("Number of Requestor Threads: %d\n", req_thread); - printf("Number of Resolver Threads: %d\n", res_threads); - gettimeofday(&proc_end, NULL); - fprintf(stdout, "%s: total time is %f seconds\n", argv[0], - ELAPSED_SECONDS(proc_begin, proc_end)); - return EXIT_SUCCESS; + req_data.input_filenames = filenames; + req_data.total_files = total_files; + static int file_idx = 0; + pthread_mutex_init(&req_data.file_idx_lock, NULL); + req_data.file_idx = &file_idx; + pthread_t *requester_threads = + (pthread_t *)malloc(req_thread_cnt * sizeof(pthread_t)); + pthread_t *resolver_threads = + (pthread_t *)malloc(res_thread_cnt * sizeof(pthread_t)); + for (int i = 0; i < req_thread_cnt; i++) + pthread_create(&requester_threads[i], NULL, requester, (void *)&req_data); + for (int i = 0; i < res_thread_cnt; i++) + pthread_create(&resolver_threads[i], NULL, resolver, (void *)&res_data); + for (int i = 0; i < req_thread_cnt; i++) + pthread_join(requester_threads[i], NULL); + for (int i = 0; i < res_thread_cnt; i++) + pthread_join(resolver_threads[i], NULL); + pthread_mutex_destroy(&req_data.file_idx_lock); + pthread_mutex_destroy(&req_data.req_log_lock); + pthread_mutex_destroy(&res_data.res_log_lock); + pthread_mutex_destroy(&res_data.term_lock); + for (int i = 5; i < argc; i++) + free(filenames[i - 5]); + free(filenames); + array_free(&stack); + free(requester_threads); + free(resolver_threads); + double end_time = get_time_sec(); + printf("%s: total time is %f seconds\n", argv[0], + (double)(end_time - start_time)); + return 0; } -void *request(void *data) { - request_data *req_data = (request_data *)data; - uint8_t file_count = 0; +void *requester(void *a) { + struct requester_data *data = (struct requester_data *)a; + double start_time = get_time_sec(); + int files_serviced = 0; + char hostname[MAX_NAME_LENGTH]; + FILE *input_file = NULL, *log_file = NULL; while (1) { - pthread_mutex_lock(req_data->input_lock); - if (queue_size(req_data->file_names) > 0) { - char *data_file = queue_pop(req_data->file_names); - file_count++; - pthread_mutex_unlock(req_data->input_lock); - FILE *file = fopen(data_file, "r"); - char line[MAX_NAME_LENGTH]; - while (fgets(line, sizeof(line), file)) { - pthread_mutex_lock(req_data->m); - while (queue_full(req_data->buffer)) - pthread_cond_wait(req_data->c_req, req_data->m); - pthread_mutex_lock(req_data->req_log_lock); - fprintf(req_data->req_log, "%s", line); - pthread_mutex_unlock(req_data->req_log_lock); - queue_push(req_data->buffer, strdup(line)); - pthread_mutex_unlock(req_data->m); - pthread_cond_signal(req_data->c_res); - } - fclose(file); - free(data_file); - } else { - pthread_mutex_unlock(req_data->input_lock); + pthread_mutex_lock(&data->file_idx_lock); + int curr_file = *(data->file_idx); + if (curr_file >= data->total_files) { + pthread_mutex_unlock(&data->file_idx_lock); break; } + (*data->file_idx)++; + pthread_mutex_unlock(&data->file_idx_lock); + input_file = fopen(data->input_filenames[curr_file], "r"); + if (!input_file) { + perror("failed to open data file"); + return NULL; + } } - fprintf(stdout, "thread %ld serviced %d files\n", syscall(SYS_gettid), - file_count); - return 0; + while (fgets(hostname, sizeof(hostname), input_file)) { + hostname[strcspn(hostname, "\n")] = '\0'; + array_put(data->stack, hostname); + pthread_mutex_lock(&data->req_log_lock); + log_file = fopen(data->req_log, "a"); + fprintf(log_file, "%s\n", hostname); + fclose(log_file); + pthread_mutex_unlock(&data->req_log_lock); + } + fclose(input_file); + files_serviced++; + for (int i = 0; i < data->res_thread_cnt; i++) + array_put(data->stack, NULL); + double end_time = get_time_sec(); + printf("thread %lx serviced %d files in %f seconds\n", (long)pthread_self(), + files_serviced, (double)(end_time - start_time)); + return NULL; } -void *resolve(void *data) { - resolve_data *res_data = (resolve_data *)data; - char *ip = (char *)malloc(MAX_IP_LENGTH); - uint16_t domain_cnt = 0; - struct timeval thread_begin, thread_end; - gettimeofday(&thread_begin, NULL); +void *resolver(void *a) { + struct resolver_data *data = (struct resolver_data *)a; + double start_time = get_time_sec(); + int hosts_resolved = 0; + char *hostname, ip_addr[MAX_IP_LENGTH]; + FILE *log_file; while (1) { - pthread_mutex_lock(res_data->m); - if (!(*(res_data->req_done)) || queue_size(res_data->buffer)) { - while (!queue_size(res_data->buffer)) - pthread_cond_wait(res_data->c_res, res_data->m); - char *domain = queue_pop(res_data->buffer); - pthread_mutex_unlock(res_data->m); - pthread_cond_signal(res_data->c_req); - if (dnslookup(domain, ip, MAX_IP_LENGTH)) { - pthread_mutex_lock(res_data->res_log_lock); - fprintf(res_data->res_log, "%s, NOT_RESOLVED\n", domain); - pthread_mutex_unlock(res_data->res_log_lock); - domain_cnt++; - } else { - pthread_mutex_lock(res_data->res_log_lock); - fprintf(res_data->res_log, "%s, %s\n", domain, ip); - pthread_mutex_unlock(res_data->res_log_lock); - domain_cnt++; + array_get(data->stack, &hostname); + if (!hostname) { + pthread_mutex_lock(&data->term_lock); + data->res_thread_cnt--; + if (!data->res_thread_cnt) { + pthread_mutex_unlock(&data->term_lock); + break; } - free(domain); - } else { - pthread_mutex_unlock(res_data->m); - break; + pthread_mutex_unlock(&data->term_lock); + continue; } + if (dnslookup(hostname, ip_addr, sizeof(ip_addr))) + strcpy(ip_addr, "NOT_RESOLVED"); + pthread_mutex_lock(&data->res_log_lock); + log_file = fopen(data->res_log, "a"); + fprintf(log_file, "%s, %s\n", hostname, ip_addr); + fclose(log_file); + pthread_mutex_unlock(&data->res_log_lock); + hosts_resolved++; } - free(ip); - gettimeofday(&thread_end, NULL); - fprintf(stdout, "thread %ld resolved %d hostnames in %f seconds\n", - syscall(SYS_gettid), domain_cnt, - ELAPSED_SECONDS(thread_begin, thread_end)); - return 0; + double end_time = get_time_sec(); + printf("thread %lx resolved %d hosts in %f seconds\n", (long)pthread_self(), + hosts_resolved, (double)(end_time - start_time)); + return NULL; +} + +double get_time_sec(void) { + struct timeval time; + gettimeofday(&time, NULL); + return time.tv_sec + (time.tv_usec / 1000000.0); } |