From 422e7f92d043ccee7397cb8f733859260eba26e4 Mon Sep 17 00:00:00 2001 From: SMonaghan Date: Tue, 21 Apr 2015 13:39:44 -0400 Subject: [PATCH 1/8] testing cpp-coveralls --- .travis.yml | 4 +++- lib/hashtable/test/Makefile | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index 4f963dd..a949e2e 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,5 +1,7 @@ language: c compiler: gcc -script: make && make test +before_install: sudo pip install cpp-coveralls +script: ./configure --enable-gcov && make && make test +after_success: coveralls --exclude lib --exclude tests --gcov-options '\-lp' notifications: email: false diff --git a/lib/hashtable/test/Makefile b/lib/hashtable/test/Makefile index 3b17dde..492d9d5 100644 --- a/lib/hashtable/test/Makefile +++ b/lib/hashtable/test/Makefile @@ -1,5 +1,5 @@ CC = gcc -CFLAGS = -std=c99 -Wall -pedantic +CFLAGS = -std=c99 -Wall -pedantic -fprofile-arcs -ftest-coverage DEPS = ../hashtable.o ../../linkedlist/linkedlist.o OBJ = test-hashtable From 6d92a5007867f93332dd6cc463939dda48f849fa Mon Sep 17 00:00:00 2001 From: SMonaghan Date: Tue, 21 Apr 2015 14:03:23 -0400 Subject: [PATCH 2/8] working on travis --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index a949e2e..6781147 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,7 +1,7 @@ language: c compiler: gcc before_install: sudo pip install cpp-coveralls -script: ./configure --enable-gcov && make && make test +script: make && make test after_success: coveralls --exclude lib --exclude tests --gcov-options '\-lp' notifications: email: false From a18d8b363a14652406a98af5e935cc9a949b0dc5 Mon Sep 17 00:00:00 2001 From: SMonaghan Date: Tue, 21 Apr 2015 14:29:29 -0400 Subject: [PATCH 3/8] Added coveralls badge --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 7452efd..f7a9ab8 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,7 @@ # GW Key-Value Store [![Build Status](https://travis-ci.org/gwAdvNet2015/gw-kv-store.svg)](https://travis-ci.org/gwAdvNet2015/gw-kv-store) +[![Coverage Status](https://coveralls.io/repos/gwAdvNet2015/gw-kv-store/badge.svg)](https://coveralls.io/r/gwAdvNet2015/gw-kv-store) A key value store developed by the students of CSCI 6907.11 Advanced Network Systems Programming at George Washington University. From 78645eace4a2ccc1b203983f7fdb7bfdd81e93ad Mon Sep 17 00:00:00 2001 From: SMonaghan Date: Tue, 21 Apr 2015 14:34:24 -0400 Subject: [PATCH 4/8] more testing --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 6781147..73e5c17 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,7 +1,7 @@ language: c compiler: gcc before_install: sudo pip install cpp-coveralls -script: make && make test +script: --enable-gcov && make && make test after_success: coveralls --exclude lib --exclude tests --gcov-options '\-lp' notifications: email: false From 30c8858e7c831417db412f11f2a60c87e855dc81 Mon Sep 17 00:00:00 2001 From: Stephen Monaghan Date: Mon, 20 Apr 2015 14:48:39 -0400 Subject: [PATCH 5/8] Update .travis.yml --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 73e5c17..6781147 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,7 +1,7 @@ language: c compiler: gcc before_install: sudo pip install cpp-coveralls -script: --enable-gcov && make && make test +script: make && make test after_success: coveralls --exclude lib --exclude tests --gcov-options '\-lp' notifications: email: false From 1231ba232623554c30e2ffa4098983b396e5fb41 Mon Sep 17 00:00:00 2001 From: SMonaghan Date: Mon, 27 Apr 2015 13:33:58 -0400 Subject: [PATCH 6/8] Merge remote-tracking branch 'upstream/server-dev' # Please enter a commit message to explain why this merge is necessary, # especially if it merges an updated upstream into a topic branch. # # Lines starting with '#' will be ignored, and an empty message aborts # the commit. --- lib/Makefile | 10 +- lib/hashtable/Makefile | 4 + lib/hashtable/test/Makefile | 6 + lib/linkedlist/Makefile | 4 + lib/linkedlist/test/.gitignore | 1 + lib/linkedlist/test/Makefile | 5 + lib/linkedlist/test/test-linkedlist | Bin 14013 -> 0 bytes lib/marshal.c | 64 ----- lib/marshal/Makefile | 25 ++ lib/marshal/marshal.c | 387 ++++++++++++++++++++++++++++ lib/{ => marshal}/marshal.h | 12 +- lib/marshal/test/.gitignore | 1 + lib/marshal/test/Makefile | 16 ++ lib/marshal/test/test-marshal.c | 194 ++++++++++++++ server/.gitignore | 1 + server/Makefile | 19 +- server/gwkv_ht_wrapper.h | 22 +- server/handle_operation.c | 94 +++++++ server/handle_operation.h | 63 +++++ server/server-kv-run.c | 67 +++++ server/server-kv.c | 108 ++++++++ server/server-kv.h | 13 + server/test/Makefile | 2 +- server/test/client-kv-test.c | 78 ++++++ server/test/server-kv-test.c | 78 ++++++ 25 files changed, 1174 insertions(+), 100 deletions(-) create mode 100644 lib/linkedlist/test/.gitignore delete mode 100755 lib/linkedlist/test/test-linkedlist delete mode 100644 lib/marshal.c create mode 100644 lib/marshal/Makefile create mode 100644 lib/marshal/marshal.c rename lib/{ => marshal}/marshal.h (79%) create mode 100644 lib/marshal/test/.gitignore create mode 100644 lib/marshal/test/Makefile create mode 100644 lib/marshal/test/test-marshal.c create mode 100644 server/.gitignore create mode 100644 server/handle_operation.c create mode 100644 server/handle_operation.h create mode 100644 server/server-kv-run.c create mode 100644 server/server-kv.c create mode 100644 server/server-kv.h create mode 100644 server/test/client-kv-test.c create mode 100644 server/test/server-kv-test.c diff --git a/lib/Makefile b/lib/Makefile index 58ea37c..b6b79cf 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -1,5 +1,5 @@ -DEPS= linkedlist hashtable murmurhash -TEST_DEPS= test_linkedlist test_hashtable test_murmurhash +DEPS= linkedlist hashtable murmurhash marshal +TEST_DEPS= test_linkedlist test_hashtable test_murmurhash test_marshal .PHONY: all test $(DEPS) $(TEST_DEPS) @@ -16,6 +16,9 @@ hashtable: murmurhash: cd murmurhash && make +marshal: + cd marshal && make + test_linkedlist: cd linkedlist && make test @@ -25,6 +28,9 @@ test_hashtable: test_murmurhash: cd murmurhash && make test +test_marshal: + cd marshal && make test + clean: cd linkedlist && make clean cd hashtable && make clean diff --git a/lib/hashtable/Makefile b/lib/hashtable/Makefile index 1bca049..af8519c 100644 --- a/lib/hashtable/Makefile +++ b/lib/hashtable/Makefile @@ -6,6 +6,7 @@ DEPS = hashtable.c LDFLAGS = OBJS = hashtable tests +.PHONY: test all: $(OBJS) rebuild: clean all @@ -16,6 +17,9 @@ hashtable: tests: cd test && make +test: + cd test && make test + clean: rm -f hashtable.o cd test && make clean diff --git a/lib/hashtable/test/Makefile b/lib/hashtable/test/Makefile index 492d9d5..b5f9235 100644 --- a/lib/hashtable/test/Makefile +++ b/lib/hashtable/test/Makefile @@ -5,9 +5,15 @@ OBJ = test-hashtable all: hashtable_test +.PHONY: test + rebuild: clean all hashtable_test: $(CC) $(CFLAGS) test-hashtable.c -o $(OBJ) $(DEPS) + +test: + ./test-hashtable + clean: rm -f $(OBJ) diff --git a/lib/linkedlist/Makefile b/lib/linkedlist/Makefile index b95174f..905fd04 100644 --- a/lib/linkedlist/Makefile +++ b/lib/linkedlist/Makefile @@ -6,6 +6,7 @@ DEPS = linkedlist.c LDFLAGS = OBJS = linkedlist tests +.PHONY: test all: $(OBJS) rebuild: clean all @@ -16,6 +17,9 @@ linkedlist: tests: cd test && make +test: + cd test && make test + clean: rm -f linkedlist.o cd test && make clean diff --git a/lib/linkedlist/test/.gitignore b/lib/linkedlist/test/.gitignore new file mode 100644 index 0000000..f098987 --- /dev/null +++ b/lib/linkedlist/test/.gitignore @@ -0,0 +1 @@ +test-linkedlist diff --git a/lib/linkedlist/test/Makefile b/lib/linkedlist/test/Makefile index 542649c..4cbcf3c 100644 --- a/lib/linkedlist/test/Makefile +++ b/lib/linkedlist/test/Makefile @@ -3,11 +3,16 @@ CFLAGS = -std=c99 -Wall -pedantic DEPS = ../linkedlist.o OBJ = test-linkedlist +.PHONY: test all: linkedlist_test rebuild: clean all linkedlist_test: $(CC) $(CFLAGS) test-ll.c -o $(OBJ) $(DEPS) + +test: + ./test-linkedlist + clean: rm -f $(OBJ) diff --git a/lib/linkedlist/test/test-linkedlist b/lib/linkedlist/test/test-linkedlist deleted file mode 100755 index 18e6f60edb46b19febc96b6c6b66a8d2504322cb..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 14013 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%0AHFfgS|ihFiGfp!-0_ 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 diff --git a/lib/marshal.c b/lib/marshal.c deleted file mode 100644 index fd5272c..0000000 --- a/lib/marshal.c +++ /dev/null @@ -1,64 +0,0 @@ - -/* - * @desc: The function does the marshing. Function does all the allocation. - * It is caller's responsibility to free the memory allocated. - * @data: Input, the function expecting this structure. - * @ascii: Function returns this char. - */ - -int -gwkv_marshal_server(struct operation* data, int status, char** ascii) -{ - switch(data->method) { - case SET: - //Convert the status into a string like this: - // - break; - case GET: - //convert the struct value to like this: - //VALUE \r\n - // \r\n - //END \r\n - break; - default: assert(0); - } -} - -int -gwkv_marshal_client(structu operation* data, char** ascii) -{ - switch(data->method) { - case SET: - //convert data to this format: - // ... - break; - case GET: - //convert data to this format - // get * \r\n - break; - } -} - -int -gwkv_demarshal_server(char* ascii, struct** op) -{ - switch(data->method) { - case SET: - //convert ascii to operation - case GET: - //convert ascii to operation - } -} - -int -gwkv_demarshal_client(char* ascii, struct** op, int* status) -{ - switch(data->method) { - case SET: - //convert ascii to operation - case GET: - //convert ascii to status - default: - break; - } -} diff --git a/lib/marshal/Makefile b/lib/marshal/Makefile new file mode 100644 index 0000000..5850a80 --- /dev/null +++ b/lib/marshal/Makefile @@ -0,0 +1,25 @@ +#Use the gcc compiler +CC = gcc +CFLAGS = -g -std=c99 -pedantic -Wall -g +#List of dependency files needed for compilation +DEPS = marshal.c +LDFLAGS = +OBJS = marshal tests + +.PHONY: test +all: $(OBJS) + +rebuild: clean all + +marshal: + $(CC) $(CFLAGS) -c $(DEPS) + +tests: + cd test && make + +test: + cd test && make test + +clean: + rm -f marshal.o + cd test && make clean diff --git a/lib/marshal/marshal.c b/lib/marshal/marshal.c new file mode 100644 index 0000000..90f6af1 --- /dev/null +++ b/lib/marshal/marshal.c @@ -0,0 +1,387 @@ + +/* + * @desc: The function does the marshing. Function does all the allocation. + * It is caller's responsibility to free the memory allocated. + * @data: Input, the function expecting this structure. + * @ascii: Function returns this char. + */ +#include +#include +#include +#include +#include "marshal.h" + +int +gwkv_marshal_server(struct operation* data, int status, char** ascii) +{ + char* val = (char*)malloc(1000*sizeof(char)); + char comm_name[]="set "; + char flag_exp[]=" 0 0 "; + char v_len[20]; + char space[] = " "; + char r_n[]="\r\n"; + char b1[] = "get "; + char b2[] = "\r\n"; + switch(data->method_type) { + case SET: + strcat(val,comm_name); + strcat(val,data->key); + strcat(val,flag_exp); + sprintf(v_len,"%d",(int)data->value_length); + strcat(val,v_len); + strcat(val,space); + strcat(val,r_n); + strcat(val,data->value); + strcat(val,r_n); + + //Convert the status into a string like this: + // + break; + case GET: + //convert the struct value to like this: + //VALUE \r\n + // \r\n + //END \r\n + strcat(val,b1); + strcat(val,data->key); + strcat(val,b2); + break; + } + *ascii = val; + return 0; +} + + + +#define COMMAND_LENGTH 3 +#define FLAG_LENGTH 1 //right now 0 +#define EXP_TIME_LENGTH 1 //unix time format. Right now 0. +#define SPACE_LENGTH 1 +#define NEWLINE_LENGTH 2 + +int +gwkv_marshal_client(struct operation* data, char** ascii) +{ + char* final_marshed_value = NULL; + char space = ' '; + char zero = '0'; + size_t size = 0; + char value_length[32] = {0}; + char* marshaled_value = 0; + + switch(data->method_type) { + case SET: + sprintf(value_length, "%d", data->value_length); + + size = COMMAND_LENGTH + 5*SPACE_LENGTH + + FLAG_LENGTH + EXP_TIME_LENGTH + + 2* NEWLINE_LENGTH + + data->key_length + + strlen(value_length) + data->value_length; + + //convert data to this format: + // ... + marshaled_value = calloc(1, size); + final_marshed_value = marshaled_value; + + snprintf(marshaled_value, COMMAND_LENGTH + 1,"%s", "set"); + marshaled_value += COMMAND_LENGTH; + snprintf(marshaled_value, SPACE_LENGTH + 1,"%c", space); + marshaled_value += SPACE_LENGTH; + snprintf(marshaled_value, data->key_length +1 ,"%s", data->key); + marshaled_value += data->key_length; + snprintf(marshaled_value, SPACE_LENGTH + 1,"%c", space); + marshaled_value += SPACE_LENGTH; + snprintf(marshaled_value, FLAG_LENGTH + 1 ,"%c", zero); + marshaled_value += FLAG_LENGTH; + snprintf(marshaled_value, SPACE_LENGTH + 1, "%c", space); + marshaled_value += SPACE_LENGTH; + snprintf(marshaled_value, EXP_TIME_LENGTH + 1 ,"%c", zero); + marshaled_value += EXP_TIME_LENGTH; + snprintf(marshaled_value, SPACE_LENGTH +1 ,"%c", space); + marshaled_value += SPACE_LENGTH; + + + snprintf(marshaled_value, strlen(value_length) + 1 ,"%s", value_length); + marshaled_value += strlen(value_length); + snprintf(marshaled_value, SPACE_LENGTH + 1,"%c", space); + marshaled_value += SPACE_LENGTH; + snprintf(marshaled_value, NEWLINE_LENGTH + 1 ,"%s", "\r\n"); + marshaled_value += NEWLINE_LENGTH; + //snprintf(marshaled_value, SPACE_LENGTH ,"%s", space); + //marshaled_value += SPACE_LENGTH; + snprintf(marshaled_value, data->value_length + 1 ,"%s", data->value); + marshaled_value += data->value_length; + snprintf(marshaled_value, NEWLINE_LENGTH ,"%c", '\r'); + marshaled_value += 1; + snprintf(marshaled_value, NEWLINE_LENGTH ,"%c", '\n'); + + break; + + case GET: + //convert data to this format + // get * \r\n + size = COMMAND_LENGTH + SPACE_LENGTH + NEWLINE_LENGTH + + data->key_length ; + + marshaled_value = calloc(1, size); + final_marshed_value = marshaled_value; + //fwrite("get", sizeof(char), COMMAND_LENGTH, marshaled_value); + //marshaled_value += COMMAND_LENGTH; + //fwrite(marshaled_value, SPACE_LENGTH ,"%s", space); + snprintf(marshaled_value, COMMAND_LENGTH + 1,"%s", "get"); + marshaled_value += COMMAND_LENGTH; + snprintf(marshaled_value, SPACE_LENGTH + 1,"%c", space); + marshaled_value += SPACE_LENGTH; + snprintf(marshaled_value, data->key_length + 1,"%s", data->key); + marshaled_value += data->key_length; + snprintf(marshaled_value, NEWLINE_LENGTH ,"%c", '\r'); + marshaled_value += 1; + snprintf(marshaled_value, NEWLINE_LENGTH ,"%c", '\n'); + + + break; + default: + assert(0); + } + *ascii = final_marshed_value; + return 0; +} + +int +gwkv_demarshal_server(char* ascii, struct operation** op) +{ + /*switch(data->method_type) { + case SET: + //convert ascii to operation + case GET: + //convert ascii to operation + }*/ + //char s0[] = "VALUE"; + char* traverse = ascii; + struct operation *data = (struct operation*)malloc(sizeof(struct operation)); + char s1[] = "set"; + char s2[] = "get"; + + /*if (strcmp(ascii, s0) >= strlen(s0)) { + + } else*/ + if ( 0 == strncmp(ascii, s1, strlen(s1))) { + data->method_type = SET; + traverse += strlen(s1) + 1; + + //next charcater is space; + assert(traverse[-1] == ' '); + + + char* temp = strchr(traverse, ' '); + if ( NULL != temp) { + data->key_length = temp - traverse; + data->key = malloc(data->key_length + 1); + strncpy(data->key, traverse, data->key_length); + //data->key[data->key_length] = '\0'; + } else { + assert(0); + } + + traverse = temp + 1; + assert(traverse[0] == '0');//flags + assert(traverse[1] == ' '); + assert(traverse[2] == '0');//exp time + assert(traverse[3] == ' '); + + traverse += 4;//pointing to i.e. length. + + temp = strchr(traverse, ' '); + if( NULL != temp) { + sscanf(traverse, "%d", &data->value_length); + } else { + assert(0); + } + + traverse = temp + 1;//pointing to \r\n. + + /*temp = strchr(traverse, ' '); + if (NULL != temp) { + traverse = temp + 1; + assert(traverse[0] == '\r'); + assert(traverse[1] == '\n'); + } else { + assert(0); + }*/ + assert(traverse[0] == '\r'); + assert(traverse[1] == '\n'); + + traverse += 2; // pointing to data + + temp = strchr(traverse, '\r'); + if ( NULL != temp) { + //verify the length + assert(data->value_length == temp - traverse); + data->value = malloc(data->value_length + 1); + strncpy(data->value, traverse, data->value_length); + + } else { + assert(0); + } + traverse = temp; + assert(traverse[1] == '\n'); + + + + } else if (0 == strncmp(ascii, s2, strlen(s2))) { + data->method_type = GET; + traverse += strlen(s2) + 1;//pointing key + char* temp = strchr(traverse, '\r'); + + //Found the newline + if (NULL != temp) { + data->key_length = temp - traverse; + data->key = malloc(data->key_length + 1); + strncpy(data->key, traverse, data->key_length); + } else { + assert(0); + return -1; + } + } else { + assert(0); + } + + *op = data; + return 0; +} + +int +gwkv_demarshal_client(char* ascii, struct operation** op, int* status) +{ + struct operation *data = (struct operation*)malloc(sizeof(struct operation)); + *op = data; + char s0[]="STORED\r\n"; + char s1[]="NOT_STORED\r\n"; + char s2[]="EXISTS\r\n"; + char s3[]="NOT_FOUND\r\n"; + if(strcmp(ascii,s0)==0){ + data->method_type=SET; + *status=0; + return 0; + } + else if(strcmp(ascii,s1)==0){ + data->method_type=SET; + *status=1; + return 0; + } + else if(strcmp(ascii,s2)==0){ + data->method_type=SET; + *status=2; + return 0; + } + else if(strcmp(ascii,s3)==0){ + data->method_type=SET; + *status=3; + return 0; + } + + char *value = "VALUE"; + char* traverse = ascii; + if( 0 != strncmp(traverse, value, strlen(value))) { + assert(0); + } + + data->method_type = GET; + traverse += strlen(value) + 1; // points to key now. + + char* temp = strchr(traverse, ' '); + if ( NULL != temp) { + data->key_length = temp - traverse; + data->key = malloc(data->key_length + 1); + strncpy(data->key, traverse, data->key_length); + } else { + assert(0); + } + + assert(temp[1] == '0'); //flags + assert(temp[2] == ' '); + traverse = temp + 3; //pointing to now + + temp = strchr(traverse, ' '); + if (NULL != temp) { + sscanf(traverse, "%d", &data->value_length); + data->value = malloc(data->value_length); + } + + assert(temp[1] == '\r'); + assert(temp[2] == '\n'); + + traverse = temp + 3;//pointing to value now. + temp = strchr(traverse, '\r'); + if( temp != NULL) { + //verify the length + assert(data->value_length == temp - traverse); + strncpy(data->value, traverse, data->value_length); + } + return 0; + +/* + int i=0; + int offset = 0; + char *a=ascii; + i=0; + char b[50]; + while(a[i]!=' ' && a[i]!='\0'){ + b[i]=a[i]; + i++; + } + b[i]='\0'; + + offset += i+1; + char c1[]="VALUE"; + if(strcmp(b,c1)!=0){ + return -1; + } + data->method_type = GET; + + //key + a = ascii + offset; + i=0; + + while(a[i]!=' '&& a[i]!='\0'){ + b[i]=a[i]; + i++; + } + b[i]='\0'; + offset += i+1; + data->key_length = i + 1; + data->key = malloc(data->key_length); + strcpy(data->key, b); + + //flag + i=0; + while(b[i]!=' '&&b[i]!='\0'){ + b[i]=a[i]; + i++; + } + b[i]='\0'; + offset += i+1; + //length + i=0; + while(b[i]!=' '&&b[i]!='\0'){ + b[i]=a[i]; + i++; + } + b[i]='\0'; + offset += i+1; + data->value_length = atoi(b); + //\r\n + offset += 2; + //data_value + i=0; + while(b[i]!='\r'&&b[i]!='\0'){ + b[i]=a[i]; + i++; + } + b[i]='\0'; + offset += i+1; + char *b2 = (char*)malloc(50*sizeof(char)); + strcat(b2,b); + data->value = b1;*/ +} diff --git a/lib/marshal.h b/lib/marshal/marshal.h similarity index 79% rename from lib/marshal.h rename to lib/marshal/marshal.h index 02cb8d8..11bf0bb 100644 --- a/lib/marshal.h +++ b/lib/marshal/marshal.h @@ -1,6 +1,8 @@ #ifndef __MARSHAL_H__ #define __MARSHAL_H__ +#include + /* Defines for returned status */ #define STORED 0 #define NOT_STORED 1 @@ -8,17 +10,17 @@ #define NOT_FOUND 3 /* Support KV Store opperations */ -typedef enum { +typedef enum method { GET, SET -} method; +}method; /* Operation struct used for gwkv opperations */ struct operation { method method_type; - const char* key; + char* key; size_t key_length; - const char* value; + char* value; size_t value_length; }; @@ -32,5 +34,5 @@ int gwkv_demarshal_server(char* ascii, struct operation** op); int -gwkv_demarshal_client(char* ascii, struct** op, int* status); +gwkv_demarshal_client(char* ascii, struct operation** op, int* status); #endif//__MARSHAL_H__ diff --git a/lib/marshal/test/.gitignore b/lib/marshal/test/.gitignore new file mode 100644 index 0000000..b1538b0 --- /dev/null +++ b/lib/marshal/test/.gitignore @@ -0,0 +1 @@ +test-marshal diff --git a/lib/marshal/test/Makefile b/lib/marshal/test/Makefile new file mode 100644 index 0000000..4d60d45 --- /dev/null +++ b/lib/marshal/test/Makefile @@ -0,0 +1,16 @@ +CC = gcc +CFLAGS = -g -std=c99 -Wall -pedantic +DEPS = ../marshal.o +OBJ = test-marshal + +all: marshal_test + +rebuild: clean all + +marshal_test: + $(CC) $(CFLAGS) test-marshal.c -o $(OBJ) $(DEPS) + +test: + ./test-marshal +clean: + rm -f $(OBJ) diff --git a/lib/marshal/test/test-marshal.c b/lib/marshal/test/test-marshal.c new file mode 100644 index 0000000..9a12718 --- /dev/null +++ b/lib/marshal/test/test-marshal.c @@ -0,0 +1,194 @@ +#include +#include +#include +#include +#include "../marshal.h" +#define MAX_KEY_SIZE 250 +#define MAX_VALUE_SIZE 1024 +struct operation *create_request(method op, char *key, char *value); + +void +print_request(struct operation *op) +{ + printf("Method: %d\n", op->method_type); + printf("Key: %s\n", op->key); + printf("key_length: %d\n", op->key_length); + printf("Value: %s\n", op->value); + printf("value_length: %d\n\n", op->value_length); +} + + +struct operation * +create_request(method op, char *key, char *value) +{ + struct operation *query; + query = malloc(sizeof(struct operation)); + query->method_type = op; + query->key = key; + query->key_length = strlen(query->key); + query->value = value; + query->value_length = 0; + if (NULL != value) { + query->value_length = strlen(query->value); + } + return query; +} + +struct operation * +create_response(method op, char *key, char *value) +{ + struct operation *query; + query = malloc(sizeof(struct operation)); + query->method_type = op; + query->key = key; + query->key_length = strlen(query->key); + query->value = value; + query->value_length = 0; + if (NULL != value) { + query->value_length = strlen(query->value); + } + return query; +} + + +int +cmp_request(struct operation *op1, struct operation *op2) +{ + if (op1->method_type == op2->method_type && + strcmp(op1->key, op2->key) == 0 && + op1->key_length == op2->key_length && + (op1->value != NULL ? strcmp(op1->value, op2->value) : 0) == 0 && + op1->value_length == op2->value_length + ) + return 0; + else + return -1; +} + +int +test_demarshal_get(char *get_str, struct operation *get_request) +{ + struct operation *get_op; + int get_status; + assert(gwkv_demarshal_client(get_str, &get_op, &get_status) == 0); + //int ret = gwkv_demarshal_client(get_str, &get_op, &get_status); + //print_request(get_op); + //assert(ret == 0); + assert(cmp_request(get_op, get_request) == 0); + return 0; +} + +int +test_demarshal_set(int status) +{ + struct operation *set_op; + int set_status; + char *stored = "STORED\r\n"; + char *not_stored = "NOT_STORED\r\n"; + char *exits = "EXISTS\r\n"; + char *not_found = "NOT_FOUND\r\n"; + + switch(status) { + case STORED: + assert(gwkv_demarshal_client(stored, &set_op, &set_status) == 0); + assert(set_status == STORED); + break; + case NOT_STORED: + assert(gwkv_demarshal_client(not_stored, &set_op, &set_status) == 0); + assert(set_status == NOT_STORED); + break; + case EXISTS: + assert(gwkv_demarshal_client(exits, &set_op, &set_status) == 0); + assert(set_status == EXISTS); + break; + case NOT_FOUND: + assert(gwkv_demarshal_client(not_found, &set_op, &set_status) == 0); + assert(set_status == NOT_FOUND); + break; + } + return 0; +} + + + +int +main() +{ + //used as verifier and an input parameter. Not to be modified. + struct operation *get_request, *set_request, *get_response;//set_response is status; + + //used as ooutput parameter for apis. + struct operation *get_op, *set_op; + char *ascii; + char *key = "test_key"; + char *value = "test_value"; + char *set_cmd = "set test_key 0 0 10 \r\ntest_value\r\n"; + char *get_cmd = "get test_key\r\n"; + char *get_str = "VALUE test_key 0 10 \r\ntest_value\r\nEND\r\n"; + int status = 0; + + printf("Create get and set request with key %s and value %s\n", key, value); + get_request = create_request(GET, key, NULL); + set_request = create_request(SET, key, value); + get_response = create_response(GET, key, value); + + + printf("Test gwkv_marshal_server...\n"); + assert(gwkv_marshal_server(get_request, status, &ascii) == 0); + printf("- Get Result:\n%s\n", ascii); + assert(ascii != NULL); + assert(strcmp(ascii, get_cmd) == 0); + ascii = 0; + free(ascii); + printf("- PASS\n"); + assert(gwkv_marshal_server(set_request, status, &ascii) == 0); + printf("- Set Result:\n%s\n", ascii); + assert(ascii != NULL); + assert(strcmp(ascii, set_cmd) == 0); + ascii = 0; + free(ascii); + printf("- PASS\n"); + + printf("Test gwkv_marshal_client...\n"); + assert(gwkv_marshal_client(get_request, &ascii) == 0); + printf("- Get Result:\n%s\n", ascii); + assert(ascii != NULL); + assert(strcmp(ascii, get_cmd) == 0); + ascii = 0; + free(ascii); + assert(gwkv_marshal_client(set_request, &ascii) == 0); + printf("- PASS\n"); + printf("- Set Result:\n"); + assert(ascii != NULL); + assert(strcmp(ascii, set_cmd) == 0); + ascii = 0; + free(ascii); + printf("- PASS\n\n"); + + printf("Test gwkv_demarshal_server...\n"); + gwkv_demarshal_server(get_cmd, &get_op); + assert(cmp_request(get_op, get_request) == 0); + printf("- Get Result: PASS\n"); + gwkv_demarshal_server(set_cmd, &set_op); + assert(cmp_request(set_op, set_request) == 0); + printf("- Set Result: PASS\n"); + + printf("Test gwkv_demarshal_client...\n"); + assert(test_demarshal_get(get_str, get_response) == 0); + printf("- Get Result: PASS\n"); + assert(test_demarshal_set(STORED) == 0); + printf("- Set STORED: PASS\n"); + assert(test_demarshal_set(NOT_STORED) == 0); + printf("- Set NOT_STORED: PASS\n"); + assert(test_demarshal_set(EXISTS) == 0); + printf("- Set EXISTS: PASS\n"); + assert(test_demarshal_set(NOT_STORED) == 0); + printf("- Set NOT_FOUND: PASS\n"); + printf("- Set Result: PASS\n"); + + printf("All marshal tests passed\n\n"); + return 0; +} + + + diff --git a/server/.gitignore b/server/.gitignore new file mode 100644 index 0000000..4816003 --- /dev/null +++ b/server/.gitignore @@ -0,0 +1 @@ +server-kv diff --git a/server/Makefile b/server/Makefile index 66e9f84..0d12d15 100644 --- a/server/Makefile +++ b/server/Makefile @@ -1,9 +1,11 @@ #Use the gcc compiler CC = gcc -CFLAGS = -g -DEPS = gwkv_ht_wrapper +CFLAGS = -pthread LDFLAGS = -OBJS = ht-wrapper #server-kv +TARGET = server-kv +DEPS = ../lib/linkedlist/linkedlist.o ../lib/hashtable/hashtable.o ../lib/murmurhash/murmurhash.o gwkv_ht_wrapper.o +OBJS = server-kv.o server-kv-run.o handle_operation.o ../lib/marshal/marshal.o +SRCS = server-kv.c server-kv-run.c handle_operation.c WRAPPER_DEPS = gwkv_ht_wrapper.c WRAPPER_OBJ = ht-wrapper murmurhash @@ -11,12 +13,15 @@ WRAPPER_OBJ = ht-wrapper murmurhash %.o: %.c $(DEPS) $(CC) $(CFLAGS) -c -o $@ $< -all: $(OBJS) +all: $(TARGET) rebuild: clean all -# server-kv: ht-wrapper server-kv.c -# $(CC) $(CFLAGS) -o $@ $^ +$(TARGET): ht-wrapper build-srcs + $(CC) $(CFLAGS) -o $(TARGET) $(OBJS) $(DEPS) + +build-srcs: + $(CC) $(CFLAGS) -c $(SRCS) ht-wrapper: gwkv_ht_wrapper.c cd ../lib/ && make @@ -26,5 +31,5 @@ test: cd test && make test clean: - @rm -f $(OBJS) + @rm -f *.o $(OBJS) .PHONY: all test diff --git a/server/gwkv_ht_wrapper.h b/server/gwkv_ht_wrapper.h index 18a0888..c33204d 100644 --- a/server/gwkv_ht_wrapper.h +++ b/server/gwkv_ht_wrapper.h @@ -3,6 +3,7 @@ #include #include +#include "../lib/marshal/marshal.h" #include "../lib/hashtable/hashtable.h" #include "../lib/murmurhash/murmurhash.h" @@ -18,27 +19,6 @@ struct gwkv_server { pthread_mutex_t lock; }; -/* Operations the table supports */ -typedef enum { - GET, - SET -} method; - -/* Defines for result codes */ -#define STORED 0 -#define NOT_STORED 1 -#define EXISTS 2 -#define NOT_FOUND 3 - -/* Datatype for wrapping datastore values */ -struct operation { - method method_type; - const char* key; - size_t key_length; - const char* value; - size_t value_length; -}; - /* Defines for hashtable params */ #define HT_SIZE 10 // number of buckets #define HT_BUCKET_LENGTH 10 // max entry/bucket (only if rebalancing) diff --git a/server/handle_operation.c b/server/handle_operation.c new file mode 100644 index 0000000..a593e78 --- /dev/null +++ b/server/handle_operation.c @@ -0,0 +1,94 @@ + +#include "../lib/marshal/marshal.h" +#include "handle_operation.h" + +char* +gwkv_handle_operation(struct gwkv_server *ht, char *cmd) +{ + struct operation *op = malloc( sizeof(struct operation) ); + int status; + char *ht_set, *ht_get; + + status = gwkv_demarshal_server(cmd, &op); + if (status == -1) { + perror("Error on demarshal server"); + exit(-1); + } + + switch(op->method_type) { + case GET: + ht_get = gwkv_handle_get(ht, op); + if (ht_get == NULL) { + perror("Something failed in gwkv_handle_get"); + exit(-1); + } + return ht_get; + case SET: + ht_set = gwkv_handle_set(ht, op); + if (ht_set == NULL) { + perror("Something failed in gwkv_handle_set"); + exit(-1); + } + return ht_set; + default: + perror("Wrong command, switch dying"); + exit(-1); + } + + return NULL; +} + +char* +gwkv_handle_get(struct gwkv_server *ht, struct operation *op) +{ + char *ht_get; // returns the value from the hashtable + char *msg; // this is the message that gwkv_marshal_server will craft + + ht_get = gwkv_server_get(ht, op->key, op->key_length, op->value_length); + if (ht_get == NULL) { + gwkv_craft_message(op, NOT_FOUND, &msg); + } else { + op->value = ht_get; + gwkv_craft_message(op, EXISTS, &msg); + } + + return msg; +} + +char* +gwkv_handle_set(struct gwkv_server *ht, struct operation *op) +{ + int ht_set; // returns STORED or NOT_STORED from hashtable + char *msg; // this is the message that gwkv_marshal_server will craft + + ht_set = gwkv_server_set(ht, op->key, op->key_length, op->value, op->value_length); + + switch(ht_set) { + case STORED: + gwkv_craft_message(op, STORED, &msg); + break; + case NOT_STORED: + gwkv_craft_message(op, NOT_STORED, &msg); + break; + default: + perror("gwkv_server_set failed, dying"); + exit(-1); + } + + return msg; +} + +int +gwkv_craft_message(struct operation *op, int status, char **msg) +{ + int res; + + res = gwkv_marshal_server(op, status, msg); + + if (res != 0) { + return -1; + } else { + return 0; + } +} + diff --git a/server/handle_operation.h b/server/handle_operation.h new file mode 100644 index 0000000..5628521 --- /dev/null +++ b/server/handle_operation.h @@ -0,0 +1,63 @@ +#ifndef __HANDLE_OP_H__ +#define __HANDLE_OP_H__ + +#include +#include +#include +#include + +#include "./gwkv_ht_wrapper.h" +#include "../lib/marshal/marshal.h" + +/* + * handle_operation takes string received from socket + * and processes it for the GET or SET command. + * + * @param char *msg - the command received from the socket + * + * @return char* - returns the crafted message + */ +char* +gwkv_handle_operation(struct gwkv_server *ht, char *cmd); + +/* + * handle_get gets the value from the server using the gwkv_server_get + * function. If the data is found, it will craft a message using + * the marshall function and send it along its way. If the message is not + * found, it will send NOT_FOUND along its way. + * + * @param struct gwkv_server *ht - struct containing hashtable and other server info + * @param struct operation *op - struct containing info about the gwkv operations + * + * @return char* - returns the crafted message + */ +char* +gwkv_handle_get(struct gwkv_server *ht, struct operation *op); + +/* + * handle_set takes the value out of the operation struct and then calls + * gwkv_server_set to put it in the hashtable. Then, it will craft a message + * using gwkv_marshal_server and send it over the socket. + * + * @param struct gwkv_server *ht - struct containing hashtable and other server info + * @param struct operation *op - struct containing info about the gwkv operations + * + * @return char* - returns the crafted message + */ +char* +gwkv_handle_set(struct gwkv_server *ht, struct operation *op); + +/* + * This function calls gwkv_marshal_server. The point of it is a tampolene + * to make setting up the variables easier. + * + * @param struct operation *op - the gwkv operations struct + * @param int status - the status of the hashtable operation + * @param char **msg - the place where the crafted message will be stored + * + * @return - status + */ +int +gwkv_craft_message(struct operation *op, int status, char **msg); + +#endif diff --git a/server/server-kv-run.c b/server/server-kv-run.c new file mode 100644 index 0000000..20110c7 --- /dev/null +++ b/server/server-kv-run.c @@ -0,0 +1,67 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "../lib/socket_helper.h" /* Provides sh_* funcs */ +#include "server-kv.h" +#include "gwkv_ht_wrapper.h" +#include "../lib/hashtable/hashtable.h" + +/**************************************** + Author: Tim Wood + with a little help from + http://beej.us/guide/bgnet/ +****************************************/ + +int +main(int argc, char ** argv) +{ + char* server_port = "1234"; + char* thread_number = "2"; + int sockfd; + int o; + + /* Command line args: + -p port + -n thread number + */ + while ((o = getopt (argc, argv, "p:n:")) != -1) { + switch(o){ + case 'p': + server_port = optarg; + break; + case 'n': + thread_number = optarg; + break; + case '?': + if(optopt == 'p') { + fprintf (stderr, "Option %c requires an argument.\n", optopt); + } + else { + fprintf (stderr, "Unknown argument: %c.\n", optopt); + } + break; + } + } + + printf("listening on port: %s, thread number %s\n", server_port, thread_number); + + sockfd = sh_server(server_port); + + /* Loop forever accepting new connections. */ + server_main(sockfd, thread_number); + + out: + close(sockfd); + + printf("Done.\n"); + return 0; +} + diff --git a/server/server-kv.c b/server/server-kv.c new file mode 100644 index 0000000..752037d --- /dev/null +++ b/server/server-kv.c @@ -0,0 +1,108 @@ +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include "server-kv.h" +#include "gwkv_ht_wrapper.h" +#include "handle_operation.h" +#include "../lib/hashtable/hashtable.h" + +/**************************************** + Author: Tim Wood + with a little help from + http://beej.us/guide/bgnet/ +****************************************/ + +struct pool_list *list_head = NULL, *list_tail = NULL; + +pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; +pthread_cond_t cond = PTHREAD_COND_INITIALIZER; +pthread_t threads[MAX_CONCURRENCY]; + +/* Handle a request from a client */ +void * +handle_request(void *ptr) +{ + int bytes_read, bytes_write; + char message[256]; + struct operation operation; + struct pool_list *node; + int clientfd; + + while (1) { + pthread_mutex_lock(&mutex); + while (list_head == NULL) { + pthread_cond_wait(&cond, &mutex); + } + node = list_head; + list_head = node->next; + pthread_mutex_unlock(&mutex); + clientfd = node->fd; + + //for test + bytes_read = read(clientfd, message, 256); + if(bytes_read < 0) { + perror("ERROR reading socket"); + } + else if (bytes_read == 0){ + printf("Client disconnected"); + } + else { + strcpy(message, gwkv_handle_operation(ht, message)); + bytes_write = strlen(message)+1; + write(clientfd, message, bytes_write); + printf("thread: %d, received:%s\n", pthread_self(), message); + } + // + + close(clientfd); + free(node); + } +} + +/* Main server logic */ +void +server_main(int sockfd, char* thread_number) +{ + int i, tnum; + struct pool_list *node; + + ht = gwkv_server_init(MURMUR); + + tnum = atoi(thread_number); + for(i = 0; i < tnum; i++) { + pthread_create(&threads[i], NULL, handle_request, NULL); + } + + while(1) { + struct sockaddr_storage client_addr; + socklen_t addr_size; + int clientfd; + + addr_size = sizeof client_addr; + clientfd = accept(sockfd, (struct sockaddr *)&client_addr, &addr_size); + //sh_print_client_ip(client_addr); + node = (struct pool_list *)malloc(sizeof(struct pool_list)); + node->fd = clientfd; + node->next = NULL; + + pthread_mutex_lock(&mutex); + if (list_head == NULL) { + list_head = node; + } + else { + list_tail->next = node; + } + list_tail = node; + pthread_cond_signal(&cond); + pthread_mutex_unlock(&mutex); + } +} + diff --git a/server/server-kv.h b/server/server-kv.h new file mode 100644 index 0000000..3cb9a93 --- /dev/null +++ b/server/server-kv.h @@ -0,0 +1,13 @@ +#define MAX_CONCURRENCY 1000 + +struct pool_list { + int fd; + struct pool_list *next; +}; + +// This is the hashtable on the server +struct gwkv_server *ht; + +void *handle_request(void *ptr); +void server_main(int sockfd, char* thread_number); + diff --git a/server/test/Makefile b/server/test/Makefile index c45154f..252752a 100644 --- a/server/test/Makefile +++ b/server/test/Makefile @@ -1,6 +1,6 @@ CC = gcc CFLAGS = -std=c99 -Wall -pedantic -g -DEPS = ../../lib/linkedlist/linkedlist.o ../../lib/hashtable/hashtable.o ../../lib/murmurhash/murmurhash.o ../gwkv_ht_wrapper.o +DEPS = ../../lib/linkedlist/linkedlist.o ../../lib/hashtable/hashtable.o ../../lib/murmurhash/murmurhash.o ../../lib/marshal/marshal.o ../gwkv_ht_wrapper.o ../handle_operation.o OBJ = test-ht-wrapper .PHONY: all test diff --git a/server/test/client-kv-test.c b/server/test/client-kv-test.c new file mode 100644 index 0000000..be4d412 --- /dev/null +++ b/server/test/client-kv-test.c @@ -0,0 +1,78 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "../lib/socket_helper.h" /* Provides sh_* funcs */ + +/**************************************** + Author: Tim Wood + with a little help from + http://beej.us/guide/bgnet/ +****************************************/ + +int client_request(int sockfd, char* message) { + int rc; + int temp_f; + float temp_c; + /* Send the message, plus the \0 string ending. Use 0 flags. */ + + rc = send(sockfd, message, strlen(message)+1, 0); + if(rc < 0) { + perror("ERROR on send"); + exit(-1); + } + + return rc; + +} + +int main(int argc, char ** argv) +{ + int o; + char* server_port = "1234"; + char* server_ip = "127.0.0.1"; + char *message = "Hello World"; + int sockfd; + + /* Command line args: + -p port + -h host name or IP + */ + while ((o = getopt (argc, argv, "p:h:m:")) != -1) { + switch(o){ + case 'p': + server_port = optarg; + break; + case 'h': + server_ip = optarg; + break; + case 'm': + message = optarg; + break; + case '?': + if(optopt == 'p' || optopt == 'h' ) { + fprintf (stderr, "Option %c requires an argument.\n", optopt); + } + else { + fprintf (stderr, "Unknown argument: %c.\n", optopt); + } + break; + } + } + printf("server_ip: %s port: %s\n", server_ip, server_port); + + sockfd = sh_client(server_ip, server_port); + + client_request(sockfd, message); + + out: + close(sockfd); + + printf("Done.\n"); + return 0; +} diff --git a/server/test/server-kv-test.c b/server/test/server-kv-test.c new file mode 100644 index 0000000..a35c454 --- /dev/null +++ b/server/test/server-kv-test.c @@ -0,0 +1,78 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "../lib/socket_helper.h" /* Provides sh_* funcs */ +#include "server-kv.h" + + +/**************************************** + Author: Tim Wood + with a little help from + http://beej.us/guide/bgnet/ +****************************************/ + +void +parse_message(char *message, int len, struct operation *operation) +{ + return; +} + +void +process_operation(struct operation *operation, char *message, int *len) +{ + return; +} + +int +main(int argc, char ** argv) +{ + char* server_port = "1234"; + char* thread_number = "2"; + int sockfd; + int o; + + /* Command line args: + -p port + -n thread number + */ + while ((o = getopt (argc, argv, "p:n:")) != -1) { + switch(o){ + case 'p': + server_port = optarg; + break; + case 'n': + thread_number = optarg; + break; + case '?': + if(optopt == 'p') { + fprintf (stderr, "Option %c requires an argument.\n", optopt); + } + else { + fprintf (stderr, "Unknown argument: %c.\n", optopt); + } + break; + } + } + + printf("listening on port: %s, thread number %s\n", server_port, thread_number); + + sockfd = sh_server(server_port); + + /* Loop forever accepting new connections. */ + server_main(sockfd, thread_number); + + out: + close(sockfd); + + printf("Done.\n"); + return 0; +} + From f5692f2c1cebdf2480a55c93814ed66e9dcb6d28 Mon Sep 17 00:00:00 2001 From: SMonaghan Date: Wed, 29 Apr 2015 14:15:13 -0400 Subject: [PATCH 7/8] added author headers to files --- server/Makefile | 13 ++++++++++++- server/gwkv_ht_wrapper.c | 17 ++++++++++++----- server/gwkv_ht_wrapper.h | 13 +++++++++++++ server/handle_operation.c | 11 +++++++++++ server/handle_operation.h | 12 ++++++++++++ server/server-kv-run.c | 11 +++++++++++ server/server-kv.c | 12 ++++++++++++ server/server-kv.h | 12 ++++++++++++ 8 files changed, 95 insertions(+), 6 deletions(-) diff --git a/server/Makefile b/server/Makefile index 0d12d15..2ffa6d3 100644 --- a/server/Makefile +++ b/server/Makefile @@ -1,3 +1,14 @@ +#/************************************************ +#* GW KV +#* https://github.com/gwAdvNet2015/gw-kv-store +#* +#* Copyright 2015 Phil Lopreiato +#* +#* This program is licensed under the MIT license. +#* +#* Makefile - Compiles the hashtable wrapper +#*************************************************/ + #Use the gcc compiler CC = gcc CFLAGS = -pthread @@ -32,4 +43,4 @@ test: clean: @rm -f *.o $(OBJS) -.PHONY: all test + .PHONY: all test diff --git a/server/gwkv_ht_wrapper.c b/server/gwkv_ht_wrapper.c index dfa9bff..54eee0d 100644 --- a/server/gwkv_ht_wrapper.c +++ b/server/gwkv_ht_wrapper.c @@ -1,3 +1,15 @@ +/************************************************ + * GW KV + * https://github.com/gwAdvNet2015/gw-kv-store + * + * Copyright 2015 Phil Lopreiato + * + * This program is licensed under the MIT license. + * + * gwkv_ht_wrapper.c - Implements wrappers for + * the hash table using murmur hash + *************************************************/ + #include #include #include @@ -74,11 +86,6 @@ gwkv_server_set(struct gwkv_server* server, expected_size++; } - /* TODO if we want to support auto-rebalancing the hastable, do so here - if(ht_check_rebalance(server->hashtable)){ - ht_rebalance(&server->hashtable); - } - */ pthread_mutex_unlock(&server->lock); /* Now, sanity check to ensure the node was actually entered */ diff --git a/server/gwkv_ht_wrapper.h b/server/gwkv_ht_wrapper.h index c33204d..9b5fe17 100644 --- a/server/gwkv_ht_wrapper.h +++ b/server/gwkv_ht_wrapper.h @@ -1,3 +1,16 @@ +/************************************************ +* GW KV +* https://github.com/gwAdvNet2015/gw-kv-store +* +* Copyright 2015 Phil Lopreiato, Stephen Monaghan, +* Jongmin Bae +* +* This program is licensed under the MIT license. +* +* gwkv_ht_wrapper.h - Declares the functions +* for the gwkv_ht_wrapper.c file +*************************************************/ + #ifndef GWKV_HT_WRAPPER #define GWKV_HT_WRAPPER diff --git a/server/handle_operation.c b/server/handle_operation.c index d869732..d006155 100644 --- a/server/handle_operation.c +++ b/server/handle_operation.c @@ -1,3 +1,14 @@ +/************************************************ + * GW KV + * https://github.com/gwAdvNet2015/gw-kv-store + * + * Copyright 2015 Phil Lopreiato + * + * This program is licensed under the MIT license. + * + * handle_operation.c - Determines GET vs SET + * operations + *************************************************/ #include "../lib/marshal/marshal.h" #include "handle_operation.h" diff --git a/server/handle_operation.h b/server/handle_operation.h index 5628521..1238eaa 100644 --- a/server/handle_operation.h +++ b/server/handle_operation.h @@ -1,3 +1,15 @@ +/************************************************ + * GW KV + * https://github.com/gwAdvNet2015/gw-kv-store + * + * Copyright 2015 Phil Lopreiato + * + * This program is licensed under the MIT license. + * + * handle_operation.h - Declares the functions + * for handle_operation.c + *************************************************/ + #ifndef __HANDLE_OP_H__ #define __HANDLE_OP_H__ diff --git a/server/server-kv-run.c b/server/server-kv-run.c index 20110c7..6e5e220 100644 --- a/server/server-kv-run.c +++ b/server/server-kv-run.c @@ -1,3 +1,14 @@ +/************************************************ + * GW KV + * https://github.com/gwAdvNet2015/gw-kv-store + * + * Copyright 2015 Tim Wood, Phil Lopreiato + * + * This program is licensed under the MIT license. + * + * server_kv_run.c - Starts the server + *************************************************/ + #include #include #include diff --git a/server/server-kv.c b/server/server-kv.c index 752037d..9bff238 100644 --- a/server/server-kv.c +++ b/server/server-kv.c @@ -1,3 +1,15 @@ +/************************************************ + * GW KV + * https://github.com/gwAdvNet2015/gw-kv-store + * + * Copyright 2015 Tim Wood, Phil Lopreiato + * + * This program is licensed under the MIT license. + * + * server_kv.c - Starts the server and handles + * requests. + *************************************************/ + #include #include #include diff --git a/server/server-kv.h b/server/server-kv.h index 3cb9a93..b3da390 100644 --- a/server/server-kv.h +++ b/server/server-kv.h @@ -1,3 +1,15 @@ +/************************************************ + * GW KV + * https://github.com/gwAdvNet2015/gw-kv-store + * + * Copyright 2015 Tim Wood, Phil Lopreiato + * + * This program is licensed under the MIT license. + * + * server_kv.h - Declares the functions for + * server_kv.c and declares the hash table + *************************************************/ + #define MAX_CONCURRENCY 1000 struct pool_list { From 82ab934cb37b71245de887ab4f187ab7c6c88a9d Mon Sep 17 00:00:00 2001 From: SMonaghan Date: Wed, 29 Apr 2015 14:23:35 -0400 Subject: [PATCH 8/8] Fixed the tab --- server/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server/Makefile b/server/Makefile index 2ffa6d3..c76653e 100644 --- a/server/Makefile +++ b/server/Makefile @@ -43,4 +43,4 @@ test: clean: @rm -f *.o $(OBJS) - .PHONY: all test +.PHONY: all test