Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Refactoring command parsing into a separate source file. Adding a pro…

…per .gitignore file. Misc code cleanup and organization.
  • Loading branch information...
commit ff442b1ea4138fef4fb3bc23d971367746126c2d 1 parent 94afbfb
@ngerakines authored
View
40 .gitignore
@@ -0,0 +1,40 @@
+.DS_Store
+Makefile
+autom4te.cache/output.2
+autom4te.cache/traces.2
+*.snapshot
+clients/php/Makefile.global
+clients/php/acinclude.m4
+clients/php/aclocal.m4
+clients/php/autom4te.cache/
+clients/php/build/
+clients/php/config.guess
+clients/php/config.h
+clients/php/config.h.in
+clients/php/config.nice
+clients/php/config.sub
+clients/php/configure
+clients/php/configure.in
+clients/php/install-sh
+clients/php/ltmain.sh
+clients/php/missing
+clients/php/mkinstalldirs
+clients/php/run-tests.php
+clients/php/tests/basic.diff
+clients/php/tests/basic.exp
+clients/php/tests/basic.log
+clients/php/tests/basic.out
+clients/php/tests/basic.php
+config.h
+config.log
+config.status
+libtool
+src/.deps/
+Makefile
+src/barbershop
+src/benchmark
+src/client
+src/*.o
+stamp-h1
+tests/.deps/
+tests/Makefile
View
58 autom4te.cache/requests
@@ -75,11 +75,11 @@
'_AM_AUTOCONF_VERSION' => 1,
'AM_DISABLE_SHARED' => 1,
'_LTDL_SETUP' => 1,
- 'AM_PROG_LIBTOOL' => 1,
'_LT_AC_LANG_CXX' => 1,
- 'AM_PROG_LD' => 1,
- '_LT_AC_FILE_LTDLL_C' => 1,
+ 'AM_PROG_LIBTOOL' => 1,
'AC_LIB_LTDL' => 1,
+ '_LT_AC_FILE_LTDLL_C' => 1,
+ 'AM_PROG_LD' => 1,
'AU_DEFUN' => 1,
'AC_PROG_NM' => 1,
'AC_LIBTOOL_DLOPEN' => 1,
@@ -103,29 +103,29 @@
'AC_LTDL_OBJDIR' => 1,
'_LT_PATH_TOOL_PREFIX' => 1,
'AC_LIBTOOL_RC' => 1,
- '_LT_AC_PROG_ECHO_BACKSLASH' => 1,
'AC_DISABLE_FAST_INSTALL' => 1,
- 'include' => 1,
- '_LT_AC_TRY_DLOPEN_SELF' => 1,
+ '_LT_AC_PROG_ECHO_BACKSLASH' => 1,
'_LT_AC_SYS_LIBPATH_AIX' => 1,
+ '_LT_AC_TRY_DLOPEN_SELF' => 1,
+ 'include' => 1,
'LT_AC_PROG_SED' => 1,
'AM_ENABLE_SHARED' => 1,
'LTDL_INSTALLABLE' => 1,
'_LT_AC_LANG_GCJ_CONFIG' => 1,
'AC_ENABLE_SHARED' => 1,
- 'AC_LIBTOOL_SYS_HARD_LINK_LOCKS' => 1,
'AC_ENABLE_STATIC' => 1,
+ 'AC_LIBTOOL_SYS_HARD_LINK_LOCKS' => 1,
'_LT_AC_TAGVAR' => 1,
'AC_LIBTOOL_LANG_F77_CONFIG' => 1,
'AM_CONDITIONAL' => 1,
'LT_LIB_DLLOAD' => 1,
- 'LTVERSION_VERSION' => 1,
'LTDL_INIT' => 1,
- 'm4_include' => 1,
+ 'LTVERSION_VERSION' => 1,
'AM_PROG_INSTALL_SH' => 1,
+ 'm4_include' => 1,
'AC_PROG_EGREP' => 1,
- 'AC_PATH_MAGIC' => 1,
'_AC_AM_CONFIG_HEADER_HOOK' => 1,
+ 'AC_PATH_MAGIC' => 1,
'AC_LTDL_SYSSEARCHPATH' => 1,
'AM_MAKE_INCLUDE' => 1,
'LT_CMD_MAX_LEN' => 1,
@@ -170,11 +170,11 @@
'AM_PROG_NM' => 1,
'AC_LIBLTDL_CONVENIENCE' => 1,
'AC_DEPLIBS_CHECK_METHOD' => 1,
- 'AC_LIBLTDL_INSTALLABLE' => 1,
'AM_SET_CURRENT_AUTOMAKE_VERSION' => 1,
+ 'AC_LIBLTDL_INSTALLABLE' => 1,
'AC_LTDL_ENABLE_INSTALL' => 1,
- 'LT_PROG_GCJ' => 1,
'AC_LIBTOOL_SYS_DYNAMIC_LINKER' => 1,
+ 'LT_PROG_GCJ' => 1,
'AM_INIT_AUTOMAKE' => 1,
'AC_DISABLE_STATIC' => 1,
'LT_PATH_NM' => 1,
@@ -182,28 +182,28 @@
'_LT_AC_LOCK' => 1,
'_LT_AC_LANG_RC_CONFIG' => 1,
'LT_SYS_MODULE_PATH' => 1,
- 'LT_WITH_LTDL' => 1,
'AC_LIBTOOL_POSTDEP_PREDEP' => 1,
+ 'LT_WITH_LTDL' => 1,
'AC_LTDL_SHLIBPATH' => 1,
'AM_AUX_DIR_EXPAND' => 1,
- 'AC_LIBTOOL_PROG_COMPILER_NO_RTTI' => 1,
'_LT_AC_LANG_F77_CONFIG' => 1,
- '_LT_COMPILER_OPTION' => 1,
+ 'AC_LIBTOOL_PROG_COMPILER_NO_RTTI' => 1,
'_AM_SET_OPTIONS' => 1,
- 'AM_RUN_LOG' => 1,
+ '_LT_COMPILER_OPTION' => 1,
'_AM_OUTPUT_DEPENDENCY_COMMANDS' => 1,
- 'AC_LTDL_SYS_DLOPEN_DEPLIBS' => 1,
- 'AC_LIBTOOL_SYS_OLD_ARCHIVE' => 1,
+ 'AM_RUN_LOG' => 1,
'AC_LIBTOOL_PICMODE' => 1,
- 'AC_CHECK_LIBM' => 1,
+ 'AC_LIBTOOL_SYS_OLD_ARCHIVE' => 1,
+ 'AC_LTDL_SYS_DLOPEN_DEPLIBS' => 1,
'LT_PATH_LD' => 1,
+ 'AC_CHECK_LIBM' => 1,
'AC_LIBTOOL_SYS_LIB_STRIP' => 1,
'_AM_MANGLE_OPTION' => 1,
- 'AC_LIBTOOL_SYS_MAX_CMD_LEN' => 1,
'AC_LTDL_SYMBOL_USCORE' => 1,
+ 'AC_LIBTOOL_SYS_MAX_CMD_LEN' => 1,
'AM_SET_DEPDIR' => 1,
- '_LT_LIBSOURCES' => 1,
'_LT_CC_BASENAME' => 1,
+ '_LT_LIBSOURCES' => 1,
'_LT_LIBOBJ' => 1
}
], 'Autom4te::Request' ),
@@ -219,15 +219,15 @@
'configure.ac'
],
{
- '_LT_AC_TAGCONFIG' => 1,
'AM_PROG_F77_C_O' => 1,
- 'AC_INIT' => 1,
+ '_LT_AC_TAGCONFIG' => 1,
'm4_pattern_forbid' => 1,
+ 'AC_INIT' => 1,
'AC_CANONICAL_TARGET' => 1,
- 'AC_CONFIG_LIBOBJ_DIR' => 1,
'AC_SUBST' => 1,
- 'AC_CANONICAL_HOST' => 1,
+ 'AC_CONFIG_LIBOBJ_DIR' => 1,
'AC_FC_SRCEXT' => 1,
+ 'AC_CANONICAL_HOST' => 1,
'AC_PROG_LIBTOOL' => 1,
'AM_INIT_AUTOMAKE' => 1,
'AC_CONFIG_SUBDIRS' => 1,
@@ -235,8 +235,8 @@
'LT_CONFIG_LTDL_DIR' => 1,
'AC_CONFIG_LINKS' => 1,
'AC_REQUIRE_AUX_FILE' => 1,
- 'LT_SUPPORTED_TAG' => 1,
'm4_sinclude' => 1,
+ 'LT_SUPPORTED_TAG' => 1,
'AM_MAINTAINER_MODE' => 1,
'AM_GNU_GETTEXT_INTL_SUBDIR' => 1,
'_m4_warn' => 1,
@@ -253,11 +253,11 @@
'AH_OUTPUT' => 1,
'_AM_SUBST_NOTMAKE' => 1,
'AC_CONFIG_AUX_DIR' => 1,
- 'm4_pattern_allow' => 1,
- 'AM_PROG_CC_C_O' => 1,
'sinclude' => 1,
- 'AM_CONDITIONAL' => 1,
+ 'AM_PROG_CC_C_O' => 1,
+ 'm4_pattern_allow' => 1,
'AC_CANONICAL_SYSTEM' => 1,
+ 'AM_CONDITIONAL' => 1,
'AC_CONFIG_HEADERS' => 1,
'AC_DEFINE_TRACE_LITERAL' => 1,
'm4_include' => 1,
View
2  src/Makefile.am
@@ -1,7 +1,7 @@
## Process this file with automake to produce Makefile.in
bin_PROGRAMS = barbershop client benchmark
-barbershop_SOURCES = barbershop.c barbershop.h bst.c bst.h scores.c scores.h stats.h
+barbershop_SOURCES = barbershop.c barbershop.h bst.c bst.h scores.c scores.h stats.h commands.c commands.h
barbershop_CFLAGS = $(OPTIMIZATION) -Wall $(ARCH) $(PROF)
client_SOURCES = client.c
View
20 src/Makefile.in
@@ -46,7 +46,8 @@ am__installdirs = "$(DESTDIR)$(bindir)"
binPROGRAMS_INSTALL = $(INSTALL_PROGRAM)
PROGRAMS = $(bin_PROGRAMS)
am_barbershop_OBJECTS = barbershop-barbershop.$(OBJEXT) \
- barbershop-bst.$(OBJEXT) barbershop-scores.$(OBJEXT)
+ barbershop-bst.$(OBJEXT) barbershop-scores.$(OBJEXT) \
+ barbershop-commands.$(OBJEXT)
barbershop_OBJECTS = $(am_barbershop_OBJECTS)
barbershop_LDADD = $(LDADD)
barbershop_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \
@@ -192,7 +193,7 @@ sysconfdir = @sysconfdir@
target_alias = @target_alias@
top_builddir = @top_builddir@
top_srcdir = @top_srcdir@
-barbershop_SOURCES = barbershop.c barbershop.h bst.c bst.h scores.c scores.h stats.h
+barbershop_SOURCES = barbershop.c barbershop.h bst.c bst.h scores.c scores.h stats.h commands.c commands.h
barbershop_CFLAGS = $(OPTIMIZATION) -Wall $(ARCH) $(PROF)
client_SOURCES = client.c
client_CFLAGS = $(OPTIMIZATION) -Wall $(ARCH) $(PROF)
@@ -277,6 +278,7 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/barbershop-barbershop.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/barbershop-bst.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/barbershop-commands.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/barbershop-scores.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/benchmark-benchmark.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/client-client.Po@am__quote@
@@ -344,6 +346,20 @@ barbershop-scores.obj: scores.c
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(barbershop_CFLAGS) $(CFLAGS) -c -o barbershop-scores.obj `if test -f 'scores.c'; then $(CYGPATH_W) 'scores.c'; else $(CYGPATH_W) '$(srcdir)/scores.c'; fi`
+barbershop-commands.o: commands.c
+@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(barbershop_CFLAGS) $(CFLAGS) -MT barbershop-commands.o -MD -MP -MF $(DEPDIR)/barbershop-commands.Tpo -c -o barbershop-commands.o `test -f 'commands.c' || echo '$(srcdir)/'`commands.c
+@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/barbershop-commands.Tpo $(DEPDIR)/barbershop-commands.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='commands.c' object='barbershop-commands.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(barbershop_CFLAGS) $(CFLAGS) -c -o barbershop-commands.o `test -f 'commands.c' || echo '$(srcdir)/'`commands.c
+
+barbershop-commands.obj: commands.c
+@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(barbershop_CFLAGS) $(CFLAGS) -MT barbershop-commands.obj -MD -MP -MF $(DEPDIR)/barbershop-commands.Tpo -c -o barbershop-commands.obj `if test -f 'commands.c'; then $(CYGPATH_W) 'commands.c'; else $(CYGPATH_W) '$(srcdir)/commands.c'; fi`
+@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/barbershop-commands.Tpo $(DEPDIR)/barbershop-commands.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='commands.c' object='barbershop-commands.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(barbershop_CFLAGS) $(CFLAGS) -c -o barbershop-commands.obj `if test -f 'commands.c'; then $(CYGPATH_W) 'commands.c'; else $(CYGPATH_W) '$(srcdir)/commands.c'; fi`
+
benchmark-benchmark.o: benchmark.c
@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(benchmark_CFLAGS) $(CFLAGS) -MT benchmark-benchmark.o -MD -MP -MF $(DEPDIR)/benchmark-benchmark.Tpo -c -o benchmark-benchmark.o `test -f 'benchmark.c' || echo '$(srcdir)/'`benchmark.c
@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/benchmark-benchmark.Tpo $(DEPDIR)/benchmark-benchmark.Po
View
151 src/barbershop.c
@@ -44,33 +44,7 @@ THE SOFTWARE.
#include "barbershop.h"
#include "stats.h"
#include <event.h>
-
-static size_t tokenize_command(char *command, token_t *tokens, const size_t max_tokens) {
- char *s, *e;
- size_t ntokens = 0;
- for (s = e = command; ntokens < max_tokens - 1; ++e) {
- if (*e == ' ') {
- if (s != e) {
- tokens[ntokens].value = s;
- tokens[ntokens].length = e - s;
- ntokens++;
- *e = '\0';
- }
- s = e + 1;
- } else if (*e == '\0') {
- if (s != e) {
- tokens[ntokens].value = s;
- tokens[ntokens].length = e - s;
- ntokens++;
- }
- break;
- }
- }
- tokens[ntokens].value = *e == '\0' ? NULL : e;
- tokens[ntokens].length = 0;
- ntokens++;
- return ntokens;
-}
+#include "commands.h"
void on_read(int fd, short ev, void *arg) {
struct client *client = (struct client *)arg;
@@ -88,100 +62,7 @@ void on_read(int fd, short ev, void *arg) {
free(client);
return;
}
- // TOOD: Find a better way to do this {
- char* nl;
- nl = strrchr(buf, '\r');
- if (nl) { *nl = '\0'; }
- nl = strrchr(buf, '\n');
- if (nl) { *nl = '\0'; }
- // }
- token_t tokens[MAX_TOKENS];
- size_t ntokens = tokenize_command((char*)buf, tokens, MAX_TOKENS);
- // TODO: Add support for the 'quit' command.
- if (ntokens == 4 && strcmp(tokens[COMMAND_TOKEN].value, "UPDATE") == 0) {
- int item_id = atoi(tokens[KEY_TOKEN].value);
- int score = atoi(tokens[VALUE_TOKEN].value);
-
- if (item_id == 0) {
- reply(fd, "-ERROR INVALID ITEM ID\r\n");
- return;
- }
-
- if (score < 1) {
- reply(fd, "-ERROR INVALID SCORE\r\n");
- return;
- }
-
- Position lookup = Find(item_id, items);
- if (lookup == NULL) {
- items = Insert(item_id, score, items);
- pthread_mutex_lock(&scores_mutex);
- scores = promoteItem(scores, score, item_id, -1);
- pthread_mutex_unlock(&scores_mutex);
- app_stats.items += 1;
- } else {
- int old_score = lookup->score;
- if (old_score == -1) {
- lookup->score = 1;
- } else {
- lookup->score += score;
- }
- assert(lookup->score > old_score);
- pthread_mutex_lock(&scores_mutex);
- scores = promoteItem(scores, lookup->score, item_id, old_score);
- pthread_mutex_unlock(&scores_mutex);
- }
- app_stats.updates += 1;
- reply(fd, "+OK\r\n");
- } else if (ntokens == 2 && strcmp(tokens[COMMAND_TOKEN].value, "PEEK") == 0) {
- int next;
- pthread_mutex_lock(&scores_mutex);
- PeekNext(scores, &next);
- pthread_mutex_unlock(&scores_mutex);
- char msg[32];
- sprintf(msg, "+%d\r\n", next);
- reply(fd, msg);
- } else if (ntokens == 2 && strcmp(tokens[COMMAND_TOKEN].value, "NEXT") == 0) {
- int next;
- pthread_mutex_lock(&scores_mutex);
- scores = NextItem(scores, &next);
- pthread_mutex_unlock(&scores_mutex);
- if (next != -1) {
- Position lookup = Find( next, items );
- if (lookup != NULL) {
- lookup->score = -1;
- }
- app_stats.items -= 1;
- }
- char msg[32];
- sprintf(msg, "+%d\r\n", next);
- reply(fd, msg);
- } else if (ntokens == 3 && strcmp(tokens[COMMAND_TOKEN].value, "SCORE") == 0) {
- int item_id = atoi(tokens[KEY_TOKEN].value);
- if (item_id == 0) {
- reply(fd, "-ERROR INVALID ITEM ID\r\n");
- return;
- }
- Position lookup = Find(item_id, items);
- if (lookup == NULL) {
- reply(fd, "+-1\r\n");
- } else {
- char msg[32];
- sprintf(msg, "+%d\r\n", lookup->score);
- reply(fd, msg);
- }
- } else if (ntokens == 2 && strcmp(tokens[COMMAND_TOKEN].value, "INFO") == 0) {
- char out[128];
- time_t current_time;
- time(&current_time);
- sprintf(out, "uptime:%d\r\n", (int)(current_time - app_stats.started_at)); reply(fd, out);
- sprintf(out, "version:%s\r\n", app_stats.version); reply(fd, out);
- sprintf(out, "updates:%u\r\n", app_stats.updates); reply(fd, out);
- sprintf(out, "items:%u\r\n", app_stats.items); reply(fd, out);
- sprintf(out, "pools:%u\r\n", app_stats.pools); reply(fd, out);
- } else {
- reply(fd, "-ERROR\r\n");
- }
+ process_request(fd, buf);
}
void on_accept(int fd, short ev, void *arg) {
@@ -301,13 +182,6 @@ int setnonblock(int fd) {
return 0;
}
-void reply(int fd, char *buffer) {
- int n = write(fd, buffer, strlen(buffer));
- if (n < 0 || n < strlen(buffer)) {
- printf("ERROR writing to socket");
- }
-}
-
void gc_thread() {
while (1) {
sleep(timeout);
@@ -320,12 +194,10 @@ void gc_thread() {
void load_snapshot(char *filename) {
FILE *file_in;
-
file_in = fopen(filename, "r");
if (file_in == NULL) {
return;
}
-
char line[80];
int item_id, score;
pthread_mutex_lock(&scores_mutex);
@@ -339,23 +211,18 @@ void load_snapshot(char *filename) {
fclose(file_in);
}
-// TODO: Make these writes atomic (write to tmp, move tmp to file).
void sync_to_disk(PoolNode *head, char *filename) {
FILE *out_file;
-
time_t now;
time(&now);
char tmp_file[32];
sprintf(tmp_file, "barbershop.%d.tmp", (int)now);
-
remove(tmp_file);
-
out_file = fopen(tmp_file, "w");
if (out_file == NULL) {
fprintf(stderr, "Can not open output file\n");
exit (8);
}
-
MemberNode *member;
while (head) {
member = head->members;
@@ -365,32 +232,25 @@ void sync_to_disk(PoolNode *head, char *filename) {
}
head = head->next;
}
-
fclose(out_file);
-
rename(tmp_file, filename);
-
return;
}
void daemonize() {
int i,lfp;
char str[10];
-
/* already a daemon */
if (getppid() == 1) {
return;
}
-
i = fork();
if (i < 0) { /* fork error */
exit(1);
}
-
if (i > 0) { /* parent exits */
exit(0);
}
-
setsid();
for (i = getdtablesize(); i >= 0; --i) { /* close all descriptors */
close(i);
@@ -400,7 +260,6 @@ void daemonize() {
dup(i);
umask(027);
chdir(RUNNING_DIR);
-
lfp = open(LOCK_FILE,O_RDWR|O_CREAT,0640);
if (lfp < 0) {
exit(1);
@@ -408,10 +267,8 @@ void daemonize() {
if (lockf(lfp, F_TLOCK, 0) < 0) {
exit(0);
}
-
sprintf(str, "%d\n", getpid());
write(lfp, str, strlen(str));
-
signal(SIGCHLD, SIG_IGN);
signal(SIGTSTP, SIG_IGN);
signal(SIGTTOU, SIG_IGN);
@@ -420,13 +277,13 @@ void daemonize() {
signal(SIGTERM, signal_handler); /* catch kill signal */
}
+// TODO: on SIGHUP import data from snapshot.
+// TODO: on SIGTERM exit.
void signal_handler(int sig) {
switch(sig) {
case SIGHUP:
- // Log this somewhere ...
break;
case SIGTERM:
- // Log this somewhere ...
exit(0);
break;
}
View
24 src/barbershop.h
@@ -20,13 +20,11 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
+#ifndef __BARBERSHOP_H__
+#define __BARBERSHOP_H__
+
#include <event.h>
-#define COMMAND_TOKEN 0
-#define SUBCOMMAND_TOKEN 1
-#define KEY_TOKEN 1
-#define VALUE_TOKEN 2
-#define MAX_TOKENS 8
#define SERVER_PORT 8002
#define RUNNING_DIR "/tmp"
#define LOCK_FILE "barbershop.lock"
@@ -36,18 +34,6 @@ struct client {
struct event ev_read;
};
-struct TreeNode {
- int item;
- int score;
- SearchTree left;
- SearchTree right;
-};
-
-typedef struct token_s {
- char *value;
- size_t length;
-} token_t;
-
SearchTree items;
PoolNode *scores;
@@ -57,14 +43,14 @@ char *sync_file;
int main(int argc, char **argv);
-static size_t tokenize_command(char *command, token_t *tokens, const size_t max_tokens);
void on_read(int fd, short ev, void *arg);
void on_accept(int fd, short ev, void *arg);
int setnonblock(int fd);
-void reply(int fd, char *buffer);
void gc_thread();
void load_snapshot(char *filename);
void sync_to_disk(PoolNode *head, char *filename);
void daemonize();
void signal_handler(int sig);
+
+#endif
View
163 src/bst.c
@@ -20,117 +20,110 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
-#include "bst.h"
-#include "stats.h"
#include <stdlib.h>
#include <stdio.h>
-
-struct TreeNode {
- int item;
- int score;
- SearchTree left;
- SearchTree right;
-};
+#include "bst.h"
+#include "stats.h"
SearchTree MakeEmpty(SearchTree tree) {
- if (tree != NULL) {
- MakeEmpty(tree->left);
- MakeEmpty(tree->right);
- free(tree);
- }
- return NULL;
+ if (tree != NULL) {
+ MakeEmpty(tree->left);
+ MakeEmpty(tree->right);
+ free(tree);
+ }
+ return NULL;
}
Position Find(int key, SearchTree tree) {
- if (tree == NULL) {
- return NULL;
- }
- if (key < tree->item) {
- return Find(key, tree->left);
- } else if (key > tree->item) {
- return Find(key, tree->right);
- }
- return tree;
+ if (tree == NULL) {
+ return NULL;
+ }
+ if (key < tree->item) {
+ return Find(key, tree->left);
+ } else if (key > tree->item) {
+ return Find(key, tree->right);
+ }
+ return tree;
}
Position FindMin(SearchTree tree) {
- if (tree == NULL) {
- return NULL;
- } else if (tree->left == NULL) {
- return tree;
- }
- return FindMin(tree->left);
+ if (tree == NULL) {
+ return NULL;
+ } else if (tree->left == NULL) {
+ return tree;
+ }
+ return FindMin(tree->left);
}
Position FindMax(SearchTree tree) {
- if (tree != NULL) {
- while (tree->right != NULL) {
- tree = tree->right;
- }
- }
- return tree;
+ if (tree != NULL) {
+ while (tree->right != NULL) {
+ tree = tree->right;
+ }
+ }
+ return tree;
}
void DumpItems(SearchTree tree) {
- if (tree == NULL) { return; }
- DumpItems(tree->left);
- printf("%d (%d) - %d - %d\n", tree->item, tree->score,
- tree->left ? tree->left->item : -1,
- tree->right ? tree->right->item : -1);
- DumpItems(tree->right);
+ if (tree == NULL) { return; }
+ DumpItems(tree->left);
+ printf("%d (%d) - %d - %d\n", tree->item, tree->score,
+ tree->left ? tree->left->item : -1,
+ tree->right ? tree->right->item : -1);
+ DumpItems(tree->right);
}
SearchTree Insert(int key, int score, SearchTree tree ) {
- if ( tree == NULL) {
- tree = malloc( sizeof( struct TreeNode ) );
- if (tree == NULL ) {
- // FatalError( "Out of space!!!" );
- } else {
- tree->item = key;
- tree->score = score;
- tree->left = tree->right = NULL;
- }
- } else {
- if ( key < tree->item ) {
- tree->left = Insert(key, score, tree->left );
- } else if( key > tree->item ) {
- tree->right = Insert(key, score, tree->right );
- }
- }
- return tree;
+ if ( tree == NULL) {
+ tree = malloc( sizeof( struct TreeNode ) );
+ if (tree == NULL ) {
+ // FatalError( "Out of space!!!" );
+ } else {
+ tree->item = key;
+ tree->score = score;
+ tree->left = tree->right = NULL;
+ }
+ } else {
+ if ( key < tree->item ) {
+ tree->left = Insert(key, score, tree->left );
+ } else if( key > tree->item ) {
+ tree->right = Insert(key, score, tree->right );
+ }
+ }
+ return tree;
}
SearchTree Delete(int key, SearchTree tree) {
- Position TmpCell;
- if (tree == NULL) {
- // Error( "Element not found" );
- } else {
- if (key < tree->item) { /* Go left */
- tree->left = Delete(key, tree->left );
- } else if ( key > tree->item) { /* Go right */
- tree->right = Delete(key, tree->right );
- } else if (tree->left && tree->right) { /* Two children */
- /* Replace with smallest in right subtree */
- TmpCell = FindMin(tree->right);
- tree->item = TmpCell->item;
- tree->right = Delete(tree->item, tree->right );
- } else { /* One or zero children */
- TmpCell = tree;
- if (tree->left == NULL) { /* Also handles 0 children */
- tree = tree->right;
- } else if (tree->right == NULL) {
- tree = tree->left;
- }
- free( TmpCell );
- }
- }
- return tree;
+ Position TmpCell;
+ if (tree == NULL) {
+ // Error( "Element not found" );
+ } else {
+ if (key < tree->item) { /* Go left */
+ tree->left = Delete(key, tree->left );
+ } else if ( key > tree->item) { /* Go right */
+ tree->right = Delete(key, tree->right );
+ } else if (tree->left && tree->right) { /* Two children */
+ /* Replace with smallest in right subtree */
+ TmpCell = FindMin(tree->right);
+ tree->item = TmpCell->item;
+ tree->right = Delete(tree->item, tree->right );
+ } else { /* One or zero children */
+ TmpCell = tree;
+ if (tree->left == NULL) { /* Also handles 0 children */
+ tree = tree->right;
+ } else if (tree->right == NULL) {
+ tree = tree->left;
+ }
+ free( TmpCell );
+ }
+ }
+ return tree;
}
int RetrieveItem(Position P) {
- return P->item;
+ return P->item;
}
int RetrieveScore(Position P) {
- return P->item;
+ return P->item;
}
View
7 src/bst.h
@@ -27,6 +27,13 @@ struct TreeNode;
typedef struct TreeNode *Position;
typedef struct TreeNode *SearchTree;
+struct TreeNode {
+ int item;
+ int score;
+ SearchTree left;
+ SearchTree right;
+};
+
SearchTree MakeEmpty(SearchTree tree);
Position Find(int key, SearchTree tree);
Position FindMin(SearchTree tree);
View
173 src/commands.c
@@ -0,0 +1,173 @@
+
+#include <arpa/inet.h>
+#include <assert.h>
+#include <err.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <getopt.h>
+#include <netinet/in.h>
+#include <pthread.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/socket.h>
+#include <sys/time.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <time.h>
+#include <unistd.h>
+
+#include "commands.h"
+#include "scores.h"
+#include "bst.h"
+#include "stats.h"
+#include "barbershop.h"
+
+void command_update(int fd, token_t *tokens) {
+ int item_id = atoi(tokens[KEY_TOKEN].value);
+ int score = atoi(tokens[VALUE_TOKEN].value);
+ if (item_id == 0) {
+ reply(fd, "-ERROR INVALID ITEM ID\r\n");
+ return;
+ }
+ if (score < 1) {
+ reply(fd, "-ERROR INVALID SCORE\r\n");
+ return;
+ }
+ Position lookup = Find(item_id, items);
+ if (lookup == NULL) {
+ items = Insert(item_id, score, items);
+ pthread_mutex_lock(&scores_mutex);
+ scores = promoteItem(scores, score, item_id, -1);
+ pthread_mutex_unlock(&scores_mutex);
+ app_stats.items += 1;
+ } else {
+ int old_score = lookup->score;
+ if (old_score == -1) {
+ lookup->score = 1;
+ } else {
+ lookup->score += score;
+ }
+ assert(lookup->score > old_score);
+ pthread_mutex_lock(&scores_mutex);
+ scores = promoteItem(scores, lookup->score, item_id, old_score);
+ pthread_mutex_unlock(&scores_mutex);
+ }
+ app_stats.updates += 1;
+ reply(fd, "+OK\r\n");
+}
+
+void command_next(int fd, token_t *tokens) {
+ int next;
+ pthread_mutex_lock(&scores_mutex);
+ scores = NextItem(scores, &next);
+ pthread_mutex_unlock(&scores_mutex);
+ if (next != -1) {
+ Position lookup = Find( next, items );
+ if (lookup != NULL) {
+ lookup->score = -1;
+ }
+ app_stats.items -= 1;
+ }
+ char msg[32];
+ sprintf(msg, "+%d\r\n", next);
+ reply(fd, msg);
+
+}
+
+void command_peek(int fd, token_t *tokens) {
+ int next;
+ pthread_mutex_lock(&scores_mutex);
+ PeekNext(scores, &next);
+ pthread_mutex_unlock(&scores_mutex);
+ char msg[32];
+ sprintf(msg, "+%d\r\n", next);
+ reply(fd, msg);
+}
+
+void command_score(int fd, token_t *tokens) {
+ int item_id = atoi(tokens[KEY_TOKEN].value);
+ if (item_id == 0) {
+ reply(fd, "-ERROR INVALID ITEM ID\r\n");
+ return;
+ }
+ Position lookup = Find(item_id, items);
+ if (lookup == NULL) {
+ reply(fd, "+-1\r\n");
+ } else {
+ char msg[32];
+ sprintf(msg, "+%d\r\n", lookup->score);
+ reply(fd, msg);
+ }
+}
+
+void command_info(int fd, token_t *tokens) {
+ char out[128];
+ time_t current_time;
+ time(&current_time);
+ sprintf(out, "uptime:%d\r\n", (int)(current_time - app_stats.started_at)); reply(fd, out);
+ sprintf(out, "version:%s\r\n", app_stats.version); reply(fd, out);
+ sprintf(out, "updates:%u\r\n", app_stats.updates); reply(fd, out);
+ sprintf(out, "items:%u\r\n", app_stats.items); reply(fd, out);
+ sprintf(out, "pools:%u\r\n", app_stats.pools); reply(fd, out);
+}
+
+// TODO: Clean the '\r\n' scrub code.
+// TODO: Add support for the 'quit' command.
+void process_request(int fd, char *input) {
+ char* nl;
+ nl = strrchr(input, '\r');
+ if (nl) { *nl = '\0'; }
+ nl = strrchr(input, '\n');
+ if (nl) { *nl = '\0'; }
+ token_t tokens[MAX_TOKENS];
+ size_t ntokens = tokenize_command(input, tokens, MAX_TOKENS);
+ if (ntokens == 4 && strcmp(tokens[COMMAND_TOKEN].value, "UPDATE") == 0) {
+ command_update(fd, tokens);
+ } else if (ntokens == 2 && strcmp(tokens[COMMAND_TOKEN].value, "PEEK") == 0) {
+ command_peek(fd, tokens);
+ } else if (ntokens == 2 && strcmp(tokens[COMMAND_TOKEN].value, "NEXT") == 0) {
+ command_next(fd, tokens);
+ } else if (ntokens == 3 && strcmp(tokens[COMMAND_TOKEN].value, "SCORE") == 0) {
+ command_score(fd, tokens);
+ } else if (ntokens == 2 && strcmp(tokens[COMMAND_TOKEN].value, "INFO") == 0) {
+ command_info(fd, tokens);
+ } else {
+ reply(fd, "-ERROR\r\n");
+ }
+}
+
+size_t tokenize_command(char *command, token_t *tokens, const size_t max_tokens) {
+ char *s, *e;
+ size_t ntokens = 0;
+ for (s = e = command; ntokens < max_tokens - 1; ++e) {
+ if (*e == ' ') {
+ if (s != e) {
+ tokens[ntokens].value = s;
+ tokens[ntokens].length = e - s;
+ ntokens++;
+ *e = '\0';
+ }
+ s = e + 1;
+ } else if (*e == '\0') {
+ if (s != e) {
+ tokens[ntokens].value = s;
+ tokens[ntokens].length = e - s;
+ ntokens++;
+ }
+ break;
+ }
+ }
+ tokens[ntokens].value = *e == '\0' ? NULL : e;
+ tokens[ntokens].length = 0;
+ ntokens++;
+ return ntokens;
+}
+
+void reply(int fd, char *buffer) {
+ int n = write(fd, buffer, strlen(buffer));
+ if (n < 0 || n < strlen(buffer)) {
+ printf("ERROR writing to socket");
+ }
+}
View
46 src/commands.h
@@ -0,0 +1,46 @@
+/*
+Copyright (c) 2010 Nick Gerakines <nick at gerakines dot net>
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+*/
+
+#ifndef __COMMANDS_H__
+#define __COMMANDS_H__
+
+#define COMMAND_TOKEN 0
+#define SUBCOMMAND_TOKEN 1
+#define KEY_TOKEN 1
+#define VALUE_TOKEN 2
+#define MAX_TOKENS 8
+
+typedef struct token_s {
+ char *value;
+ size_t length;
+} token_t;
+
+void command_update(int fd, token_t *tokens);
+void command_next(int fd, token_t *tokens);
+void command_peek(int fd, token_t *tokens);
+void command_score(int fd, token_t *tokens);
+void command_info(int fd, token_t *tokens);
+void process_request(int fd, char *input);
+size_t tokenize_command(char *command, token_t *tokens, const size_t max_tokens);
+void reply(int fd, char *buffer);
+
+#endif
View
8 src/scores.c
@@ -229,12 +229,13 @@ PoolNode *promoteItem(PoolNode *list, int score, int item, int old_score) {
newPool->next = list;
return newPool;
} else if (list->next == NULL && list->score > score) {
- // There is only one member in the head and the head is larger than score, set head->next to newPool and return head
+ // There is only one member in the head and the head is larger
+ // than score, set head->next to newPool and return head.
list->next = newPool;
return list;
} else {
- // There are more than two items in the list, find where to inject
- // the new pool ... shit
+ // There are more than two items in the list, find where to
+ // create the new pool
PoolNode *head = list;
while (head) {
if (score < head->score) {
@@ -291,4 +292,3 @@ PoolNode *NextItem(PoolNode *head, int *next_item) {
return head;
}
}
-
Please sign in to comment.
Something went wrong with that request. Please try again.