Added some functions
This commit is contained in:
+193
-81
@@ -1,5 +1,6 @@
|
||||
#include <zmq.h>
|
||||
#include <ctype.h>
|
||||
#include <pthread.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
@@ -8,67 +9,143 @@
|
||||
|
||||
#define tolower_str(word) for(int i = 0; i < strlen(word); i++) word[i] = tolower(word[i]);
|
||||
|
||||
char *map(char*);
|
||||
char *reduce(char*);
|
||||
void rip();
|
||||
void* workerFunc(void *args);
|
||||
|
||||
TYPE get_request_type(const char *request)
|
||||
{
|
||||
char* map(const char *content, key_value_pair **head, key_value_pair **tail);
|
||||
char* reduce(char *);
|
||||
|
||||
int main(int argc, char **argv){
|
||||
if(argc < 2){
|
||||
fprintf(stderr, "Usage: %s <port>\n", argv[0]);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
printf("Starting...\n");
|
||||
|
||||
int worker_index = 1;
|
||||
int worker_count = argc - 1;
|
||||
int thread_count = 0;
|
||||
|
||||
pthread_t *threads = (pthread_t*)malloc(sizeof(pthread_t) * worker_count);
|
||||
|
||||
while(thread_count < worker_count){
|
||||
int *port = malloc(sizeof(int));
|
||||
*port = atoi(argv[worker_index]);
|
||||
if(pthread_create(&threads[thread_count++], NULL, workerFunc, port) != 0){
|
||||
perror("[MAIN] Failed to create thread");
|
||||
free(threads);
|
||||
exit(1);
|
||||
}
|
||||
worker_index++;
|
||||
printf("Initialized Thread: %d\n", thread_count);
|
||||
}
|
||||
|
||||
printf("Done initialization");
|
||||
|
||||
// wait for workers to finish
|
||||
for(int i = 0; i < thread_count; i++){
|
||||
pthread_join(threads[i], NULL);
|
||||
}
|
||||
|
||||
free(threads);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
TYPE get_request_type(const char *request){
|
||||
char type_str[4];
|
||||
strncpy(type_str, request, 3);
|
||||
type_str[3] = '\0';
|
||||
|
||||
if (strcmp(type_str, "map") == 0) return MAP;
|
||||
if (strcmp(type_str, "red") == 0) return RED;
|
||||
if (strcmp(type_str, "rip") == 0) return RIP;
|
||||
if(strcmp(type_str, "map") == 0) return MAP;
|
||||
if(strcmp(type_str, "red") == 0) return RED;
|
||||
if(strcmp(type_str, "rip") == 0) return RIP;
|
||||
|
||||
return UNSUPPORTED;
|
||||
}
|
||||
|
||||
void main(int argc, char **argv)
|
||||
{
|
||||
// TODO: Start socket with zmq
|
||||
// TODO: Wait on calls
|
||||
// TODO: Handle calls
|
||||
// TODO: Reply to requester
|
||||
|
||||
char *ret;
|
||||
|
||||
switch (get_request_type(argv[1]))
|
||||
{
|
||||
case MAP:
|
||||
perror("Handling MAP\n");
|
||||
ret = map(argv[1]);
|
||||
break;
|
||||
case RED:
|
||||
perror("Handling RED\n");
|
||||
ret = reduce(argv[1]);
|
||||
break;
|
||||
case RIP:
|
||||
perror("Handling RIP\n");
|
||||
rip();
|
||||
break;
|
||||
case UNSUPPORTED:
|
||||
perror("Got unsupported request\n");
|
||||
break;
|
||||
void* workerFunc(void *args){
|
||||
int port = *(int*)args;
|
||||
free(args);
|
||||
void *context = zmq_ctx_new();
|
||||
if(!context){
|
||||
perror("[THREAD] Failed to create context");
|
||||
return NULL;
|
||||
}
|
||||
void *responder = zmq_socket(context, ZMQ_REP);
|
||||
if(!responder){
|
||||
perror("[THREAD] Failed to create socket");
|
||||
zmq_ctx_destroy(context);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// TODO: just send ret
|
||||
char addr[22];
|
||||
snprintf(addr, sizeof(addr), "tcp://localhost:%d", port);
|
||||
|
||||
int rc = zmq_bind(responder, addr);
|
||||
if(rc != 0){
|
||||
perror("Failed to connect");
|
||||
zmq_close(responder);
|
||||
zmq_ctx_destroy(context);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
while(1){
|
||||
key_value_pair *head = NULL;
|
||||
key_value_pair *tail = NULL;
|
||||
|
||||
char request[MESSAGE_LENGTH + 1]; // CHECK: off by one error
|
||||
int bytes_recv = zmq_recv(responder, request, MESSAGE_LENGTH, 0);
|
||||
|
||||
const TYPE type = get_request_type(request);
|
||||
char *content = request + TYPE_LENGTH;
|
||||
|
||||
char *ret;
|
||||
|
||||
switch(type){
|
||||
case MAP:
|
||||
perror("Handling MAP\n");
|
||||
ret = map(content, &head, &tail);
|
||||
break;
|
||||
case RED:
|
||||
perror("Handling RED\n");
|
||||
ret = reduce(content);
|
||||
break;
|
||||
case RIP:
|
||||
perror("Handling RIP\n");
|
||||
// send errors are redundant to handle because exit
|
||||
zmq_send(responder, "rip", TYPE_LENGTH, 0);
|
||||
zmq_close(responder);
|
||||
zmq_ctx_destroy(context);
|
||||
exit(0);
|
||||
break;
|
||||
case UNSUPPORTED:
|
||||
perror("Got unsupported request\n");
|
||||
// rip();
|
||||
exit(1);
|
||||
break;
|
||||
}
|
||||
|
||||
if(zmq_send(responder, ret, MESSAGE_LENGTH, 0) != 0){
|
||||
perror("Failed to send response");
|
||||
zmq_close(responder);
|
||||
zmq_ctx_destroy(context);
|
||||
exit(1);
|
||||
}
|
||||
} //loop
|
||||
}
|
||||
|
||||
void add_word(const char *word)
|
||||
{
|
||||
void add_word(const char *word, key_value_pair **head, key_value_pair **tail){
|
||||
char *word_copy = strdup(word);
|
||||
tolower_str(word_copy);
|
||||
|
||||
key_value_pair *kv = init_key_value_pair(word, "1");
|
||||
if (kv == NULL)
|
||||
{
|
||||
if(kv == NULL){
|
||||
fprintf(stderr, "Failed to allocate memory for key: %s\n", word);
|
||||
free(word_copy);
|
||||
return;
|
||||
}
|
||||
if (add_key_value_pair(kv) != 0)
|
||||
{
|
||||
if(add_key_value_pair(kv, head, tail) != 0){
|
||||
fprintf(stderr, "Failed to add key value: %s\n", word);
|
||||
free(word_copy);
|
||||
return;
|
||||
@@ -77,54 +154,89 @@ void add_word(const char *word)
|
||||
free(word_copy);
|
||||
}
|
||||
|
||||
char *get_word(const char *request)
|
||||
{
|
||||
static char *iterator = (char*)request;
|
||||
int word_length = 0;
|
||||
char *word = (char*)malloc(sizeof(char) * 1);
|
||||
if (word == NULL) return NULL;
|
||||
*word = '\0';
|
||||
char* get_word(const char *request){
|
||||
if(request == NULL || *request == '\0')
|
||||
return strdup("");
|
||||
|
||||
while (*iterator)
|
||||
{
|
||||
char *word_bak = word;
|
||||
word = (char*)realloc(word, ++word_length);
|
||||
if (word == NULL)
|
||||
{
|
||||
free(word_bak);
|
||||
return NULL;
|
||||
int capacity = 16;
|
||||
int length = 0;
|
||||
char *word = (char*)malloc(capacity);
|
||||
if(!word)
|
||||
return NULL;
|
||||
|
||||
while(*request && isalpha(*request)){
|
||||
if(length + 1 >= capacity){
|
||||
capacity *= 2;
|
||||
char *new_word = (char*)realloc(word, capacity);
|
||||
if(!new_word){
|
||||
free(word);
|
||||
return NULL;
|
||||
}
|
||||
word = new_word;
|
||||
}
|
||||
if (!isalpha(*iterator))
|
||||
{
|
||||
word[word_length] = '\0';
|
||||
return word;
|
||||
}
|
||||
word[word_length] = *iterator;
|
||||
iterator++;
|
||||
word[length++] = *request;
|
||||
request++;
|
||||
}
|
||||
return NULL;
|
||||
|
||||
word[length] = '\0';
|
||||
return word;
|
||||
}
|
||||
|
||||
char *map(const char *content)
|
||||
{
|
||||
char *content_iterator = content;
|
||||
char* map(const char *content, key_value_pair **head, key_value_pair **tail){
|
||||
char *content_iterator = (char*)content;
|
||||
void *content_start_address = (void*)content;
|
||||
size_t content_length = strlen(content);
|
||||
|
||||
while(content_iterator != NULL && content_iterator < content_start_address + content_length){
|
||||
char *word = get_word(content_iterator);
|
||||
if(word != NULL){
|
||||
if(strcmp(word, "") != 0){
|
||||
add_word(word, head, tail);
|
||||
}
|
||||
content_iterator += strlen(word) + 1;
|
||||
free(word);
|
||||
}
|
||||
}
|
||||
|
||||
free_key_value_pairs();
|
||||
return NULL;
|
||||
key_value_pair *kvp_it = *head;
|
||||
|
||||
char *ret = NULL;
|
||||
|
||||
while(kvp_it != NULL){
|
||||
char *kvp2str = kvp_it->toString(kvp_it);
|
||||
if(kvp2str == NULL){
|
||||
kvp_it = kvp_it->next;
|
||||
continue;
|
||||
}
|
||||
if(!ret){
|
||||
ret = strdup(kvp2str);
|
||||
}
|
||||
else{
|
||||
char *tmp = realloc(ret, strlen(ret) + strlen(kvp2str) + 1);
|
||||
if(!tmp){
|
||||
free(ret);
|
||||
perror("Failed to realloc memory for ret");
|
||||
free(kvp2str);
|
||||
return NULL;
|
||||
}
|
||||
ret = tmp;
|
||||
strcat(ret, kvp2str);
|
||||
free(kvp2str);
|
||||
kvp_it = kvp_it->next;
|
||||
}
|
||||
}
|
||||
|
||||
if(!ret){
|
||||
perror("Could not extract key value pairs");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
free_key_value_pairs(head, tail);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
char *reduce(char *content)
|
||||
{
|
||||
|
||||
free_key_value_pairs();
|
||||
char* reduce(char *content){
|
||||
// free_key_value_pairs();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void rip()
|
||||
{
|
||||
free_key_value_pairs(); // nothing should be allocated
|
||||
// TODO: Return RIP on zmq sock;
|
||||
perror("---RIP---\n");
|
||||
exit(0);
|
||||
}
|
||||
Reference in New Issue
Block a user