aboutsummaryrefslogtreecommitdiff
path: root/pa6_threaded_resolver/multi-lookup.c
diff options
context:
space:
mode:
Diffstat (limited to 'pa6_threaded_resolver/multi-lookup.c')
-rw-r--r--pa6_threaded_resolver/multi-lookup.c256
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);
}