Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ set(THREADS_PREFER_PTHREAD_FLAG ON)
find_package(Threads REQUIRED)

if(APPLE)
add_executable(fkvs-server src/memory.c src/counter.c src/client.c src/core/list.c src/config.c src/networking/networking.c src/server.c src/core/hashtable.c src/commands/common/command_registry.c src/commands/server/server_command_handlers.c src/io/event_dispatcher_kqueue.c)
add_executable(fkvs-server src/memory.c src/counter.c src/client.c src/core/list.c src/config.c src/networking/networking.c src/server.c src/core/hashtable.c src/commands/common/command_registry.c src/commands/server/server_command_handlers.c src/io/event_dispatcher_kqueue.c src/ttl.c)
target_compile_definitions(fkvs-server PRIVATE SERVER)

add_executable(fkvs-benchmark src/string_utils.c src/fkvs-benchmark.c src/client.c src/core/list.c src/networking/networking.c src/commands/common/command_parser.c src/commands/client/client_command_handlers.c)
Expand All @@ -20,11 +20,11 @@ elseif(LINUX)
find_library(LIBURING liburing)

if(LIBURING)
add_executable(fkvs-server src/memory.c src/counter.c src/client.c src/core/list.c src/config.c src/networking/networking.c src/server.c src/core/hashtable.c src/commands/common/command_registry.c src/commands/server/server_command_handlers.c src/io/event_dispatcher_io_uring.c)
add_executable(fkvs-server src/memory.c src/counter.c src/client.c src/core/list.c src/config.c src/networking/networking.c src/server.c src/core/hashtable.c src/commands/common/command_registry.c src/commands/server/server_command_handlers.c src/io/event_dispatcher_io_uring.c src/ttl.c)
target_link_libraries(fkvs-server PRIVATE LIBURING)
target_compile_definitions(fkvs-server PRIVATE SERVER IO_URING_ENABLED)
else()
add_executable(fkvs-server src/memory.c src/counter.c src/client.c src/core/list.c src/config.c src/networking/networking.c src/server.c src/core/hashtable.c src/commands/common/command_registry.c src/commands/server/server_command_handlers.c src/io/event_dispatcher_epoll.c)
add_executable(fkvs-server src/memory.c src/counter.c src/client.c src/core/list.c src/config.c src/networking/networking.c src/server.c src/core/hashtable.c src/commands/common/command_registry.c src/commands/server/server_command_handlers.c src/io/event_dispatcher_epoll.c src/ttl.c)
target_compile_definitions(fkvs-server PRIVATE SERVER)
endif()

Expand All @@ -35,7 +35,7 @@ endif()
# Add test executable
add_executable(test_counter tests/test_counter.c src/counter.c)
add_executable(test_string_utils tests/test_string_utils.c src/string_utils.c)
add_executable(test_integration tests/test_integration.c src/core/hashtable.c src/commands/common/command_registry.c src/commands/common/command_parser.c src/commands/server/server_command_handlers.c src/counter.c)
add_executable(test_integration tests/test_integration.c src/core/hashtable.c src/commands/common/command_registry.c src/commands/common/command_parser.c src/commands/server/server_command_handlers.c src/counter.c src/ttl.c)
target_compile_definitions(test_integration PRIVATE SERVER)
target_link_libraries(test_counter)
target_link_libraries(test_string_utils)
Expand Down
34 changes: 26 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -90,14 +90,32 @@ $ ./fkvs-cli -h 127.0.0.1 -p 5995 --non-interactive

### Supported commands

- PING | PING "value"
- SET key value
- GET key
- INCR key
- INCRBY key value
- DECR key
- DECRBY key value
- INFO
#### Strings

| Command | Usage | Description |
|---|---|---|
| `SET` | `SET key value [EX seconds]` | Store a key-value pair, optionally setting a TTL atomically |
| `GET` | `GET key` | Retrieve the value of a key |
| `DEL` | `DEL key` | Delete a key |
| `INCR` | `INCR key` | Increment the integer value of a key by 1 |
| `INCRBY` | `INCRBY key amount` | Increment the integer value of a key by a given amount |
| `DECR` | `DECR key` | Decrement the integer value of a key by 1 |
| `DECRBY` | `DECRBY key amount` | Decrement the integer value of a key by a given amount |

#### Expiration (TTL)

| Command | Usage | Description |
|---|---|---|
| `EXPIRE` | `EXPIRE key seconds` | Set a timeout on a key (in seconds) |
| `TTL` | `TTL key` | Get the remaining time-to-live of a key (-1 = no TTL, -2 = key missing) |
| `PERSIST` | `PERSIST key` | Remove the timeout from a key |

#### Server

| Command | Usage | Description |
|---|---|---|
| `PING` | `PING` or `PING value` | Test connectivity; returns `PONG` or echoes the value |
| `INFO` | `INFO` | Display server statistics (uptime, memory, connected clients) |

## Documentation

Expand Down
142 changes: 135 additions & 7 deletions src/commands/client/client_command_handlers.c
Original file line number Diff line number Diff line change
Expand Up @@ -54,16 +54,25 @@ void cmd_set(const command_args_t args, void (*response_cb)(client_t *client))

char value[MAX_VALUE_LEN];
char key[MAX_KEY_LEN];
if (sscanf(args.cmd, "SET %511s %511s", key, value) == 2) {
char ex_keyword[4];
char seconds[MAX_VALUE_LEN];

size_t cmd_len;
unsigned char *binary_cmd = NULL;

int nfields = sscanf(args.cmd, "SET %511s %511s %3s %511s", key, value,
ex_keyword, seconds);

if (nfields == 4 && strcasecmp(ex_keyword, "EX") == 0) {
binary_cmd = construct_set_ex_command(key, value, seconds, &cmd_len);
} else if (nfields == 2) {
binary_cmd = construct_set_command(key, value, &cmd_len);
} else {
printf("(error) ERR wrong number of arguments for 'set' command\n");
printf("(info) Usage: SET <key> <value>\n");
printf("(error) ERR syntax error in 'set' command\n");
printf("(info) Usage: SET <key> <value> [EX seconds]\n");
return;
}

size_t cmd_len;
unsigned char *binary_cmd = construct_set_command(key, value, &cmd_len);
if (binary_cmd == NULL) {
fprintf(stderr, "Failed to construct SET command\n");
return;
Expand Down Expand Up @@ -263,6 +272,119 @@ void cmd_decr_by(const command_args_t args,
response_cb(args.client);
}

void cmd_del(const command_args_t args, void (*response_cb)(client_t *client))
{
if (strncasecmp(args.cmd, "DEL ", 4) != 0) {
return;
}

char key[MAX_KEY_LEN];
if (sscanf(args.cmd, "DEL %511s", key) != 1) {
printf("(error) ERR wrong number of arguments for 'del' command\n");
printf("(info) Usage: DEL <key>\n");
return;
}

size_t cmd_len;
unsigned char *binary_cmd = construct_del_command(key, &cmd_len);
if (binary_cmd == NULL) {
fprintf(stderr, "Failed to construct DEL command\n");
return;
}

assert(cmd_len > 0);
assert(args.client->fd > 0);

send(args.client->fd, binary_cmd, cmd_len, 0);
free(binary_cmd);
response_cb(args.client);
}

void cmd_expire(const command_args_t args, void (*response_cb)(client_t *client))
{
if (strncasecmp(args.cmd, "EXPIRE ", 7) != 0) {
return;
}

char key[MAX_KEY_LEN];
char seconds[MAX_VALUE_LEN];
if (sscanf(args.cmd, "EXPIRE %511s %511s", key, seconds) != 2) {
printf("(error) ERR wrong number of arguments for 'expire' command\n");
printf("(info) Usage: EXPIRE <key> <seconds>\n");
return;
}

size_t cmd_len;
unsigned char *binary_cmd = construct_expire_command(key, seconds, &cmd_len);
if (binary_cmd == NULL) {
fprintf(stderr, "Failed to construct EXPIRE command\n");
return;
}

assert(cmd_len > 0);
assert(args.client->fd > 0);

send(args.client->fd, binary_cmd, cmd_len, 0);
free(binary_cmd);
response_cb(args.client);
}

void cmd_ttl(const command_args_t args, void (*response_cb)(client_t *client))
{
if (strncasecmp(args.cmd, "TTL ", 4) != 0) {
return;
}

char key[MAX_KEY_LEN];
if (sscanf(args.cmd, "TTL %511s", key) != 1) {
printf("(error) ERR wrong number of arguments for 'ttl' command\n");
printf("(info) Usage: TTL <key>\n");
return;
}

size_t cmd_len;
unsigned char *binary_cmd = construct_ttl_command(key, &cmd_len);
if (binary_cmd == NULL) {
fprintf(stderr, "Failed to construct TTL command\n");
return;
}

assert(cmd_len > 0);
assert(args.client->fd > 0);

send(args.client->fd, binary_cmd, cmd_len, 0);
free(binary_cmd);
response_cb(args.client);
}

void cmd_persist(const command_args_t args, void (*response_cb)(client_t *client))
{
if (strncasecmp(args.cmd, "PERSIST ", 8) != 0) {
return;
}

char key[MAX_KEY_LEN];
if (sscanf(args.cmd, "PERSIST %511s", key) != 1) {
printf("(error) ERR wrong number of arguments for 'persist' command\n");
printf("(info) Usage: PERSIST <key>\n");
return;
}

size_t cmd_len;
unsigned char *binary_cmd = construct_persist_command(key, &cmd_len);
if (binary_cmd == NULL) {
fprintf(stderr, "Failed to construct PERSIST command\n");
return;
}

assert(cmd_len > 0);
assert(args.client->fd > 0);

send(args.client->fd, binary_cmd, cmd_len, 0);
free(binary_cmd);
response_cb(args.client);
}

/*
* TODO: This approach works but is cumbersome to maintain. For future
* reference, lets implement a solution that doesn't require us to have a
Expand All @@ -278,17 +400,23 @@ void cmd_unknown(const command_args_t args,
strncmp(args.cmd, "PING", 4) &&
strncmp(args.cmd, "PING ", 5) &&
strncmp(args.cmd, "DECR ", 5) &&
strncmp(args.cmd, "DECRBY ", 7) &&
strncmp(args.cmd, "DECRBY ", 7) &&
strncmp(args.cmd, "DEL ", 4) &&
strncmp(args.cmd, "EXPIRE ", 7) &&
strncmp(args.cmd, "TTL ", 4) &&
strncmp(args.cmd, "PERSIST ", 8) &&
strncmp(args.cmd, "INFO", 5)) {
printf("Unknown command \n");
}
}

const cmd_t command_table[] = {
{"cmd_set", cmd_set}, {"cmd_get", cmd_get},
{"cmd_decr", cmd_decr}, {"cmd_decr_by", cmd_decr_by},
{"cmd_decr", cmd_decr}, {"cmd_decr_by", cmd_decr_by},
{"cmd_incr", cmd_incr},
{"cmd_incr_by", cmd_incr_by}, {"cmd_ping", cmd_ping},
{"cmd_del", cmd_del}, {"cmd_expire", cmd_expire},
{"cmd_ttl", cmd_ttl}, {"cmd_persist", cmd_persist},
{"cmd_unknown", cmd_unknown},
{"cmd_info", cmd_info}};

Expand Down
8 changes: 8 additions & 0 deletions src/commands/client/client_command_handlers.h
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,14 @@ void cmd_info(command_args_t args, void (*response_cb)(client_t *client));

void cmd_unknown(command_args_t args, void (*response_cb)(client_t *client));

void cmd_del(command_args_t args, void (*response_cb)(client_t *client));

void cmd_expire(command_args_t args, void (*response_cb)(client_t *client));

void cmd_ttl(command_args_t args, void (*response_cb)(client_t *client));

void cmd_persist(command_args_t args, void (*response_cb)(client_t *client));

void command_response_handler(client_t *client);

#endif // CLIENT_COMMAND_HANDLERS
4 changes: 4 additions & 0 deletions src/commands/common/command_defs.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,5 +9,9 @@
#define CMD_DECR 0x06
#define CMD_INFO 0x07
#define CMD_DECR_BY 0x08
#define CMD_DEL 0x09
#define CMD_EXPIRE 0x0A
#define CMD_TTL 0x0B
#define CMD_PERSIST 0x0C

#endif // COMMAND_DEFS_H
Loading
Loading