Skip to content
This repository
Browse code

Add 'get_tables' command.

  • Loading branch information...
commit 10252d701e5f48dcdff34f9f28fb9504f80029a7 1 parent a895142
Ben Johnson authored January 23, 2013
221  src/get_tables_message.c
... ...
@@ -0,0 +1,221 @@
  1
+#include <stdlib.h>
  2
+#include <stdio.h>
  3
+#include <arpa/inet.h>
  4
+#include <dirent.h>
  5
+
  6
+#include "types.h"
  7
+#include "get_tables_message.h"
  8
+#include "table.h"
  9
+#include "minipack.h"
  10
+#include "mem.h"
  11
+#include "dbg.h"
  12
+
  13
+
  14
+//==============================================================================
  15
+//
  16
+// Functions
  17
+//
  18
+//==============================================================================
  19
+
  20
+//--------------------------------------
  21
+// Lifecycle
  22
+//--------------------------------------
  23
+
  24
+// Creates an 'get_tables' message object.
  25
+//
  26
+// Returns a new message.
  27
+sky_get_tables_message *sky_get_tables_message_create()
  28
+{
  29
+    sky_get_tables_message *message = NULL;
  30
+    message = calloc(1, sizeof(sky_get_tables_message)); check_mem(message);
  31
+    return message;
  32
+
  33
+error:
  34
+    sky_get_tables_message_free(message);
  35
+    return NULL;
  36
+}
  37
+
  38
+// Frees a 'get_tables' message object from memory.
  39
+//
  40
+// message - The message object to be freed.
  41
+//
  42
+// Returns nothing.
  43
+void sky_get_tables_message_free(sky_get_tables_message *message)
  44
+{
  45
+    if(message) {
  46
+        free(message);
  47
+    }
  48
+}
  49
+
  50
+
  51
+
  52
+//--------------------------------------
  53
+// Message Handler
  54
+//--------------------------------------
  55
+
  56
+// Creates a message handler for the message.
  57
+//
  58
+// Returns a message handler.
  59
+sky_message_handler *sky_get_tables_message_handler_create()
  60
+{
  61
+    sky_message_handler *handler = sky_message_handler_create(); check_mem(handler);
  62
+    handler->scope = SKY_MESSAGE_HANDLER_SCOPE_SERVER;
  63
+    handler->name = bfromcstr("get_tables");
  64
+    handler->process = sky_get_tables_message_process;
  65
+    return handler;
  66
+
  67
+error:
  68
+    sky_message_handler_free(handler);
  69
+    return NULL;
  70
+}
  71
+
  72
+// Retrieves a table to the server. This function is synchronous and does not use
  73
+// a worker.
  74
+//
  75
+// server - The server.
  76
+// header - The message header.
  77
+// table  - The table the message is working against
  78
+// input  - The input file stream.
  79
+// output - The output file stream.
  80
+//
  81
+// Returns 0 if successful, otherwise returns -1.
  82
+int sky_get_tables_message_process(sky_server *server,
  83
+                                   sky_message_header *header,
  84
+                                   sky_table *_table, FILE *input, FILE *output)
  85
+{
  86
+    int rc = 0;
  87
+    size_t sz;
  88
+    uint32_t i;
  89
+    sky_get_tables_message *message = NULL;
  90
+    bstring path = NULL;
  91
+    bstring *table_names = NULL;
  92
+    uint32_t table_name_count = 0;
  93
+    DIR *dir = NULL;
  94
+    check(server != NULL, "Server required");
  95
+    check(header != NULL, "Message header required");
  96
+    check(input != NULL, "Input stream required");
  97
+    check(output != NULL, "Output stream required");
  98
+    (void)_table;
  99
+    
  100
+    struct tagbstring status_str = bsStatic("status");
  101
+    struct tagbstring ok_str = bsStatic("ok");
  102
+    struct tagbstring tables_str = bsStatic("tables");
  103
+    struct tagbstring name_str = bsStatic("name");
  104
+
  105
+    // Parse message.
  106
+    message = sky_get_tables_message_create(); check_mem(message);
  107
+    rc = sky_get_tables_message_unpack(message, input);
  108
+    check(rc == 0, "Unable to parse 'get_tables' message");
  109
+
  110
+    // Retrieve a list of directories from the server data path.
  111
+    // Open directory.
  112
+    dir = opendir(bdatae(server->path, ""));
  113
+    check(dir != NULL, "Unable to open server data directory: %s", bdatae(server->path, ""));
  114
+    
  115
+    // Copy over contents of directory.
  116
+    struct dirent *ent = NULL;
  117
+    while((ent = readdir(dir))) {
  118
+        if(strcmp(ent->d_name, ".") != 0 && strcmp(ent->d_name, "..") != 0) {
  119
+            path = bformat("%s/%s", bdata(server->path), ent->d_name); check_mem(path);
  120
+            if(sky_file_is_dir(path)) {
  121
+                // Resize table name array.
  122
+                table_names = realloc(table_names, sizeof(*table_names) * (table_name_count+1));
  123
+                check_mem(table_names);
  124
+                table_name_count++;
  125
+
  126
+                // Append table name.
  127
+                table_names[table_name_count-1] = bfromcstr(ent->d_name);
  128
+                check_mem(table_names[table_name_count-1]);
  129
+            }
  130
+            bdestroy(path);
  131
+            path = NULL;
  132
+        }
  133
+    }
  134
+    closedir(dir);
  135
+    dir = NULL;
  136
+    
  137
+    // Return.
  138
+    //   {status:"OK"}
  139
+    minipack_fwrite_map(output, 2, &sz);
  140
+    check(sz > 0, "Unable to write output");
  141
+    check(sky_minipack_fwrite_bstring(output, &status_str) == 0, "Unable to write status key");
  142
+    check(sky_minipack_fwrite_bstring(output, &ok_str) == 0, "Unable to write status value");
  143
+    check(sky_minipack_fwrite_bstring(output, &tables_str) == 0, "Unable to write tables key");
  144
+
  145
+    // Write all table names.
  146
+    minipack_fwrite_array(output, table_name_count, &sz);
  147
+    check(sz > 0, "Unable to write tables array");
  148
+
  149
+    for(i=0; i<table_name_count; i++) {
  150
+        minipack_fwrite_map(output, 1, &sz);
  151
+        check(sz > 0, "Unable to write map");
  152
+        check(sky_minipack_fwrite_bstring(output, &name_str) == 0, "Unable to write table name key");
  153
+        check(sky_minipack_fwrite_bstring(output, table_names[i]) == 0, "Unable to write table name: %s", bdata(table_names[i]));
  154
+    }
  155
+    
  156
+    for(i=0; i<table_name_count; i++) {
  157
+        bdestroy(table_names[i]);
  158
+        table_names[i] = NULL;
  159
+    }
  160
+    free(table_names);
  161
+    
  162
+    fclose(input);
  163
+    fclose(output);
  164
+    bdestroy(path);
  165
+    sky_get_tables_message_free(message);
  166
+
  167
+    return 0;
  168
+
  169
+error:
  170
+    if(dir != NULL) closedir(dir);
  171
+    for(i=0; i<table_name_count; i++) {
  172
+        bdestroy(table_names[i]);
  173
+        table_names[i] = NULL;
  174
+    }
  175
+    free(table_names);
  176
+
  177
+    if(input) fclose(input);
  178
+    if(output) fclose(output);
  179
+    bdestroy(path);
  180
+    sky_get_tables_message_free(message);
  181
+    return -1;
  182
+}
  183
+
  184
+
  185
+//--------------------------------------
  186
+// Serialization
  187
+//--------------------------------------
  188
+
  189
+// Serializes an 'get_tables' message to a file stream.
  190
+//
  191
+// message - The message.
  192
+// file    - The file stream to write to.
  193
+//
  194
+// Returns 0 if successful, otherwise returns -1.
  195
+int sky_get_tables_message_pack(sky_get_tables_message *message, FILE *file)
  196
+{
  197
+    check(message != NULL, "Message required");
  198
+    check(file != NULL, "File stream required");
  199
+
  200
+    return 0;
  201
+
  202
+error:
  203
+    return -1;
  204
+}
  205
+
  206
+// Deserializes an 'get_tables' message from a file stream.
  207
+//
  208
+// message - The message.
  209
+// file    - The file stream to read from.
  210
+//
  211
+// Returns 0 if successful, otherwise returns -1.
  212
+int sky_get_tables_message_unpack(sky_get_tables_message *message, FILE *file)
  213
+{
  214
+    check(message != NULL, "Message required");
  215
+    check(file != NULL, "File stream required");
  216
+
  217
+    return 0;
  218
+
  219
+error:
  220
+    return -1;
  221
+}
58  src/get_tables_message.h
... ...
@@ -0,0 +1,58 @@
  1
+#ifndef _sky_get_tables_message_h
  2
+#define _sky_get_tables_message_h
  3
+
  4
+#include <inttypes.h>
  5
+#include <stdbool.h>
  6
+#include <netinet/in.h>
  7
+
  8
+#include "bstring.h"
  9
+#include "message_handler.h"
  10
+#include "table.h"
  11
+#include "event.h"
  12
+
  13
+
  14
+//==============================================================================
  15
+//
  16
+// Typedefs
  17
+//
  18
+//==============================================================================
  19
+
  20
+// A message for retrieving a table on the server.
  21
+typedef struct {
  22
+    bstring data_path;
  23
+    bstring name;
  24
+} sky_get_tables_message;
  25
+
  26
+
  27
+//==============================================================================
  28
+//
  29
+// Functions
  30
+//
  31
+//==============================================================================
  32
+
  33
+//--------------------------------------
  34
+// Lifecycle
  35
+//--------------------------------------
  36
+
  37
+sky_get_tables_message *sky_get_tables_message_create();
  38
+
  39
+void sky_get_tables_message_free(sky_get_tables_message *message);
  40
+
  41
+//--------------------------------------
  42
+// Message Handler
  43
+//--------------------------------------
  44
+
  45
+sky_message_handler *sky_get_tables_message_handler_create();
  46
+
  47
+int sky_get_tables_message_process(sky_server *server,
  48
+    sky_message_header *header, sky_table *table, FILE *input, FILE *output);
  49
+
  50
+//--------------------------------------
  51
+// Serialization
  52
+//--------------------------------------
  53
+
  54
+int sky_get_tables_message_pack(sky_get_tables_message *message, FILE *file);
  55
+
  56
+int sky_get_tables_message_unpack(sky_get_tables_message *message, FILE *file);
  57
+
  58
+#endif
6  src/server.c
@@ -21,6 +21,7 @@
21 21
 #include "create_table_message.h"
22 22
 #include "delete_table_message.h"
23 23
 #include "get_table_message.h"
  24
+#include "get_tables_message.h"
24 25
 #include "ping_message.h"
25 26
 #include "lua_aggregate_message.h"
26 27
 #include "multi_message.h"
@@ -602,6 +603,11 @@ int sky_server_add_default_message_handlers(sky_server *server)
602 603
     rc = sky_server_add_message_handler(server, handler);
603 604
     check(rc == 0, "Unable to add message handler");
604 605
 
  606
+    // 'Get Tables' message.
  607
+    handler = sky_get_tables_message_handler_create(); check_mem(handler);
  608
+    rc = sky_server_add_message_handler(server, handler);
  609
+    check(rc == 0, "Unable to add message handler");
  610
+
605 611
     // 'Ping' message.
606 612
     handler = sky_ping_message_handler_create(); check_mem(handler);
607 613
     rc = sky_server_add_message_handler(server, handler);
2  src/version.h
... ...
@@ -1,7 +1,7 @@
1 1
 #ifndef _version_h
2 2
 #define _version_h
3 3
 
4  
-#define SKY_VERSION "0.2.1"
  4
+#define SKY_VERSION "0.2.2"
5 5
 
6 6
 #endif
7 7
 
0  tests/fixtures/get_tables_message/0/message
No changes.
1  tests/fixtures/get_tables_message/1/input
... ...
@@ -0,0 +1 @@
  1
+¤name£foo
1  tests/fixtures/get_tables_message/1/output
... ...
@@ -0,0 +1 @@
  1
+‚¦status¢ok¦tables’¤name£bar¤name£foo
1  tests/fixtures/get_tables_message/2/input
... ...
@@ -0,0 +1 @@
  1
+¤name£foo
1  tests/fixtures/get_tables_message/2/output
... ...
@@ -0,0 +1 @@
  1
+‚¦status¢ok¦tables
113  tests/unit/get_tables_message_tests.c
... ...
@@ -0,0 +1,113 @@
  1
+#include <stdio.h>
  2
+#include <stdlib.h>
  3
+
  4
+#include <get_tables_message.h>
  5
+#include <mem.h>
  6
+#include <dbg.h>
  7
+
  8
+#include "../minunit.h"
  9
+
  10
+
  11
+//==============================================================================
  12
+//
  13
+// Test Cases
  14
+//
  15
+//==============================================================================
  16
+
  17
+//--------------------------------------
  18
+// Serialization
  19
+//--------------------------------------
  20
+
  21
+int test_sky_get_tables_message_pack() {
  22
+    cleantmp();
  23
+    sky_get_tables_message *message = sky_get_tables_message_create();
  24
+    
  25
+    FILE *file = fopen("tmp/message", "w");
  26
+    mu_assert_bool(sky_get_tables_message_pack(message, file) == 0);
  27
+    fclose(file);
  28
+    mu_assert_file("tmp/message", "tests/fixtures/get_tables_message/0/message");
  29
+    sky_get_tables_message_free(message);
  30
+    return 0;
  31
+}
  32
+
  33
+int test_sky_get_tables_message_unpack() {
  34
+    FILE *file = fopen("tests/fixtures/get_tables_message/0/message", "r");
  35
+    sky_get_tables_message *message = sky_get_tables_message_create();
  36
+    mu_assert_bool(sky_get_tables_message_unpack(message, file) == 0);
  37
+    fclose(file);
  38
+
  39
+    sky_get_tables_message_free(message);
  40
+    return 0;
  41
+}
  42
+
  43
+
  44
+//--------------------------------------
  45
+// Processing
  46
+//--------------------------------------
  47
+
  48
+int test_sky_get_tables_message_process() {
  49
+    cleantmp();
  50
+    sky_server *server = sky_server_create(NULL);
  51
+    sky_table *table = NULL;
  52
+    server->path = bfromcstr("tmp");
  53
+    sky_message_header *header = sky_message_header_create();
  54
+
  55
+    // Create, open & close table.
  56
+    table = sky_table_create();
  57
+    table->path = bfromcstr("tmp/foo");
  58
+    sky_table_open(table);
  59
+    sky_table_free(table);
  60
+
  61
+    // Create, open & close another table.
  62
+    table = sky_table_create();
  63
+    table->path = bfromcstr("tmp/bar");
  64
+    sky_table_open(table);
  65
+    sky_table_free(table);
  66
+
  67
+    FILE *input = fopen("tests/fixtures/get_tables_message/1/input", "r");
  68
+    FILE *output = fopen("tmp/output", "w");
  69
+    int rc = sky_get_tables_message_process(server, header, NULL, input, output);
  70
+    mu_assert_int_equals(rc, 0);
  71
+    
  72
+    mu_assert_file("tmp/output", "tests/fixtures/get_tables_message/1/output");
  73
+
  74
+    sky_message_header_free(header);
  75
+    sky_server_stop(server);
  76
+    sky_server_free(server);
  77
+    return 0;
  78
+}
  79
+
  80
+int test_sky_get_tables_message_process_with_no_tables() {
  81
+    cleantmp();
  82
+    sky_server *server = sky_server_create(NULL);
  83
+    server->path = bfromcstr("tmp");
  84
+    sky_message_header *header = sky_message_header_create();
  85
+
  86
+    FILE *input = fopen("tests/fixtures/get_tables_message/2/input", "r");
  87
+    FILE *output = fopen("tmp/output", "w");
  88
+    int rc = sky_get_tables_message_process(server, header, NULL, input, output);
  89
+    mu_assert_int_equals(rc, 0);
  90
+    
  91
+    mu_assert_file("tmp/output", "tests/fixtures/get_tables_message/2/output");
  92
+
  93
+    sky_message_header_free(header);
  94
+    sky_server_free(server);
  95
+    return 0;
  96
+}
  97
+
  98
+
  99
+//==============================================================================
  100
+//
  101
+// Setup
  102
+//
  103
+//==============================================================================
  104
+
  105
+int all_tests() {
  106
+    mu_run_test(test_sky_get_tables_message_pack);
  107
+    mu_run_test(test_sky_get_tables_message_unpack);
  108
+    mu_run_test(test_sky_get_tables_message_process);
  109
+    mu_run_test(test_sky_get_tables_message_process_with_no_tables);
  110
+    return 0;
  111
+}
  112
+
  113
+RUN_TESTS()

0 notes on commit 10252d7

Please sign in to comment.
Something went wrong with that request. Please try again.