#ifndef FAST_CACHE_HANDLERS
|
|
#define FAST_CACHE_HANDLERS
|
|
#include <kclangc.h>
|
|
|
|
#include "common.c"
|
|
#include "queue.c"
|
|
|
|
void handle_stats(KCLIST* tokens, FILE* client){
|
|
char out[1024];
|
|
float hit_ratio = 0;
|
|
if(hits){
|
|
hit_ratio = (float)hits / (float)(hits + misses);
|
|
}
|
|
char* status = kcdbstatus(db);
|
|
KCLIST* stats = kclistnew();
|
|
tokenize(stats, status, "\n");
|
|
char status_buf[1024];
|
|
strcpy(status_buf, "");
|
|
int stat_count = kclistcount(stats);
|
|
int i;
|
|
for(i = 0; i < stat_count; ++i){
|
|
size_t part_size;
|
|
const char* part = kclistget(stats, i, &part_size);
|
|
KCLIST* parts = kclistnew();
|
|
tokenize(parts, (char*)part, "\t");
|
|
char buf[128];
|
|
if(kclistcount(parts) == 2){
|
|
sprintf(buf, "STAT %s %s\r\n", kclistget(parts, 0, &part_size), kclistget(parts, 1, &part_size));
|
|
}
|
|
kclistdel(parts);
|
|
strcat(status_buf, buf);
|
|
}
|
|
sprintf(out, STATS_FORMAT, connections, hits, misses, hit_ratio, status_buf);
|
|
fputs(out, client);
|
|
}
|
|
|
|
void handle_version(KCLIST* tokens, FILE* client){
|
|
char out[1024];
|
|
sprintf(out, "VERSION %s\r\n", VERSION);
|
|
fputs(out, client);
|
|
}
|
|
|
|
void handle_flush(KCLIST* tokens, FILE* client){
|
|
if(kcdbclear(db)){
|
|
fputs("OK\r\n", client);
|
|
}
|
|
}
|
|
|
|
void handle_delete(KCLIST* tokens, FILE* client){
|
|
if(kclistcount(tokens)){
|
|
char key[128];
|
|
list_shift(tokens, key);
|
|
if(kcdbremove(db, key, strlen(key))){
|
|
fputs("DELETED\r\n", client);
|
|
}
|
|
}
|
|
}
|
|
|
|
void handle_get(KCLIST* tokens, FILE* client){
|
|
if(kclistcount(tokens)){
|
|
char key[128];
|
|
list_shift(tokens, key);
|
|
char out[1024];
|
|
char* result_buffer;
|
|
size_t result_size;
|
|
result_buffer = kcdbget(db, key, strlen(key), &result_size);
|
|
if(result_buffer){
|
|
if(strcmp(result_buffer, "0") == 0){
|
|
++misses;
|
|
sprintf(out, "VALUE %s 0 2\r\n{}\r\nEND\r\n", key);
|
|
} else{
|
|
++hits;
|
|
sprintf(out, "VALUE %s 0 %d\r\n%s\r\nEND\r\n", key, (int)strlen(result_buffer), result_buffer);
|
|
}
|
|
kcfree(result_buffer);
|
|
} else{
|
|
++misses;
|
|
sprintf(out, "VALUE %s 0 2\r\n{}\r\nEND\r\n", key);
|
|
kcdbset(db, key, strlen(key), "0", 1);
|
|
queue_add(&requests, key);
|
|
}
|
|
fputs(out, client);
|
|
} else{
|
|
fputs("INVALID GET COMMAND: GET <KEY>\r\n", client);
|
|
return;
|
|
}
|
|
}
|
|
|
|
int handle_command(char* buffer, FILE* client){
|
|
int status = 0;
|
|
char command[1024];
|
|
KCLIST* tokens = kclistnew();
|
|
tokenize(tokens, buffer, " ");
|
|
list_shift(tokens, command);
|
|
if(command){
|
|
if(strcmp(command, "get") == 0){
|
|
handle_get(tokens, client);
|
|
} else if(strcmp(command, "stats") == 0){
|
|
handle_stats(tokens, client);
|
|
} else if(strcmp(command, "flush_all") == 0){
|
|
handle_flush(tokens, client);
|
|
} else if(strcmp(command, "delete") == 0){
|
|
handle_delete(tokens, client);
|
|
} else if(strcmp(command, "version") == 0){
|
|
handle_version(tokens, client);
|
|
} else if(strcmp(command, "quit") == 0){
|
|
status = -1;
|
|
} else{
|
|
char out[1024];
|
|
sprintf(out, "UNKNOWN COMMAND: %s\r\n", command);
|
|
fputs(out, client);
|
|
}
|
|
}
|
|
|
|
kclistdel(tokens);
|
|
|
|
return status;
|
|
}
|
|
#endif
|