Ejemplo n.º 1
0
int test() {
    pthread_t thread;
    importtmp_n("tests/functional/fixtures/add_event/0/data.json", 4);
    start_server(1, &thread);
    send_msg("tests/functional/fixtures/add_event/0/input");
    pthread_join(thread, NULL);

    mu_assert_msg("tests/functional/fixtures/add_event/0/output");

    void *data;
    size_t data_length;
    sky_table *table = sky_table_create();
    table->path = bfromcstr("tmp");
    sky_table_open(table);
    sky_tablet_get_path(table->tablets[2], 10, &data, &data_length);
    mu_assert_mem(data, 
        "\x03\xe8\x03\x00\x00\x00\x00\x00\x00\x05\x00\x1f\x00\x00\x00\xff"
        "\xa6\x7a\x7a\x7a\x7a\x7a\x7a\xfe\x0a\x01\xa3\x78\x79\x7a\x02\xd1"
        "\x00\xc8\x03\xcb\x40\x59\x0c\xcc\xcc\xcc\xcc\xcd\x04\xc3\x01\x00"
        "\x00\x10\x00\x00\x00\x00\x00\x01\x00\x01\x00\x00\x20\x00\x00\x00"
        "\x00\x00\x02\x00\x01\x00\x00\x30\x00\x00\x00\x00\x00\x03\x00",
        data_length
    );
    sky_table_free(table);
    free(data);
    return 0;
}
Ejemplo n.º 2
0
// Closes a table and detaches it from the server.
//
// server - The server.
// table  - The table to close.
//
// Returns 0 if successful, otherwise returns -1.
int sky_server_close_table(sky_server *server, sky_table *table)
{
    int rc;
    assert(server != NULL);
    assert(table != NULL);
    
    // Send shutdown message for servlets associated with this table.
    rc = sky_server_stop_servlets(server, table);
    check(rc == 0, "Unable to shutdown servlets related to table: %s", bdata(table->path));

    // Remove the server association.
    uint32_t i, j;
    for(i=0; i<server->table_count; i++) {
        if(server->tables[i] == table) {
            sky_table_free(table);
            table = NULL;
            
            for(j=i+1; j<server->table_count; j++) {
                server->tables[j-1] = server->tables[j];
            }
            server->tables[server->table_count-1] = NULL;
            server->table_count--;
            i--;
        }
    }
    
    return 0;

error:
    return -1;
}
Ejemplo n.º 3
0
int test_sky_table_open() {
    struct tagbstring lock_file_path = bsStatic("tmp/.skylock");
    struct tagbstring data_file_path = bsStatic("tmp/0/data");
    struct tagbstring header_file_path = bsStatic("tmp/0/header");
    cleantmp();
    
    int rc;
    sky_table *table = sky_table_create();
    table->path = bfromcstr("tmp");
    
    // Open table.
    rc = sky_table_open(table);
    mu_assert_int_equals(rc, 0);
    mu_assert(sky_file_exists(&lock_file_path), "");
    mu_assert(sky_file_exists(&data_file_path), "");
    mu_assert(sky_file_exists(&header_file_path), "");
    
    // Close table.
    rc = sky_table_close(table);
    mu_assert_int_equals(rc, 0);
    mu_assert(!sky_file_exists(&lock_file_path), "");
    mu_assert(sky_file_exists(&data_file_path), "");
    mu_assert(sky_file_exists(&header_file_path), "");

    sky_table_free(table);
    return 0;
}
Ejemplo n.º 4
0
int test_sky_lua_generate_header() {
    importtmp("tests/fixtures/sky_lua/0/data.json");
    sky_table *table = sky_table_create();
    table->path = bfromcstr("tmp");
    sky_table_open(table);

    struct tagbstring source = bsStatic(
        "function aggregate(event)\n"
        "  label = event:first_name() .. ' ' .. event:last_name()\n"
        "  return event.x + event.y\n"
        "end\n"
    );
    bstring event_decl = NULL;
    bstring event_metatype = NULL;
    bstring init_descriptor_func = NULL;
    int rc = sky_lua_generate_event_info(&source, table->property_file, &event_decl, &event_metatype, &init_descriptor_func);
    mu_assert_int_equals(rc, 0);
    mu_assert_bstring(event_decl,
        "typedef struct {\n"
        "  int64_t ts;\n"
        "  uint32_t timestamp;\n"
        "  uint16_t action_id;\n"
        "  sky_string_t _first_name;\n"
        "  sky_string_t _last_name;\n"
        "  int32_t x;\n"
        "  int32_t y;\n"
        "} sky_lua_event_t;"
    );
    mu_assert_bstring(event_metatype,
        "ffi.metatype('sky_lua_event_t', {\n"
        "  __index = {\n"
        "    first_name = function(event) return ffi.string(event._first_name.data, event._first_name.length) end,\n"
        "    last_name = function(event) return ffi.string(event._last_name.data, event._last_name.length) end,\n"
        "    x = function(event) return event.x end,\n"
        "    y = function(event) return event.y end,\n"
        "  }\n"
        "})\n"
    );
    mu_assert_bstring(init_descriptor_func,
        "function sky_init_descriptor(_descriptor)\n"
        "  descriptor = ffi.cast('sky_data_descriptor_t*', _descriptor)\n"
        "  descriptor:set_data_sz(ffi.sizeof('sky_lua_event_t'));\n"
        "  descriptor:set_ts_offset(ffi.offsetof('sky_lua_event_t', 'ts'));\n"
        "  descriptor:set_timestamp_offset(ffi.offsetof('sky_lua_event_t', 'timestamp'));\n"
        "  descriptor:set_action_id_offset(ffi.offsetof('sky_lua_event_t', 'action_id'));\n"
        "  descriptor:set_property(4, ffi.offsetof('sky_lua_event_t', '_first_name'), 1);\n"
        "  descriptor:set_property(5, ffi.offsetof('sky_lua_event_t', '_last_name'), 1);\n"
        "  descriptor:set_property(2, ffi.offsetof('sky_lua_event_t', 'x'), 2);\n"
        "  descriptor:set_property(3, ffi.offsetof('sky_lua_event_t', 'y'), 2);\n"
        "end\n"
    );
    bdestroy(event_decl);
    bdestroy(event_metatype);
    bdestroy(init_descriptor_func);
    sky_table_free(table);
    return 0;
}
Ejemplo n.º 5
0
// Creates a reference to an table.
//
// Returns a reference to the new table if successful. Otherwise returns
// null.
sky_table *sky_table_create()
{
    sky_table *table = calloc(sizeof(sky_table), 1);
    check_mem(table);
    return table;

error:
    sky_table_free(table);
    return NULL;
}
Ejemplo n.º 6
0
int test_sky_aggregate() {
    importtmp("tests/fixtures/sky_lua/1/data.json");
    sky_table *table = sky_table_create();
    table->path = bfromcstr("tmp");
    sky_table_open(table);
    sky_data_descriptor *descriptor = sky_data_descriptor_create();

    // Initialize the path iterator.
    sky_path_iterator iterator;
    sky_path_iterator_init(&iterator);
    iterator.cursor.data_descriptor = descriptor;
    sky_path_iterator_set_tablet(&iterator, table->tablets[0]);

    struct tagbstring source = bsStatic(
        "function aggregate(cursor, data)\n"
        "  data.path_count = (data.path_count or 0) + 1\n"
        "  while cursor:next() do\n"
        "    data.event_count = (data.event_count or 0) + 1\n"
        "    data.z = (data.z or 0) + cursor.event.x + cursor.event.y\n"
        "  end\n"
        "end\n"
    );
    lua_State *L = NULL;
    int rc = sky_lua_initscript_with_table(&source, table, descriptor, &L);
    mu_assert_int_equals(rc, 0);

    // Allocate data.
    mu_assert_int_equals(descriptor->data_sz, 24);
    iterator.cursor.data = calloc(1, descriptor->data_sz);

    // Start benchmark.
    struct timeval tv;
    gettimeofday(&tv, NULL);
    int64_t t0 = (tv.tv_sec*1000) + (tv.tv_usec/1000);

    // Call sky_aggregate() function.
    uint32_t i;
    for(i=0; i<1; i++) {
        //sky_path_iterator_set_tablet(&iterator, table->tablets[0]);
        lua_getglobal(L, "sky_aggregate");
        lua_pushlightuserdata(L, &iterator);
        lua_call(L, 1, 0);
    }

    // End benchmark.
    gettimeofday(&tv, NULL);
    int64_t t1 = (tv.tv_sec*1000) + (tv.tv_usec/1000);
    printf("[lua] t=%.3fs\n", ((float)(t1-t0))/1000);

    sky_path_iterator_uninit(&iterator);
    sky_table_free(table);
    free(iterator.cursor.data);
    return 0;
}
Ejemplo n.º 7
0
// Frees an importer.
//
// Returns nothing.
void sky_importer_free(sky_importer *importer)
{
    if(importer) {
        if(importer->path) bdestroy(importer->path);
        importer->path = NULL;

        sky_table_free(importer->table);
        importer->table = NULL;

        free(importer);
    }
}
Ejemplo n.º 8
0
int test_sky_create_table_message_unpack() {
    FILE *file = fopen("tests/fixtures/create_table_message/0/message", "r");
    sky_create_table_message *message = sky_create_table_message_create();
    message->data_path = bfromcstr("/tmp/data");
    message->table = sky_table_create();
    mu_assert_bool(sky_create_table_message_unpack(message, file) == 0);
    fclose(file);

    mu_assert_bstring(message->table->path, "/tmp/data/foo");
    sky_table_free(message->table);
    sky_create_table_message_free(message);
    return 0;
}
Ejemplo n.º 9
0
// Frees the tables on a server instance.
//
// server - The server.
//
// Returns nothing.
void sky_server_free_tables(sky_server *server)
{
    if(server) {
        uint32_t i;
        for(i=0; i<server->table_count; i++) {
            sky_table_free(server->tables[i]);
            server->tables[i] = NULL;
        }
        free(server->tables);
        server->tables = NULL;
        server->table_count = 0;
    }
}
Ejemplo n.º 10
0
int test_sky_create_table_message_pack() {
    cleantmp();
    sky_create_table_message *message = sky_create_table_message_create();
    message->data_path = bfromcstr("/tmp/data");
    message->table = sky_table_create();
    message->table->path = bfromcstr("/tmp/data/foo");
    message->table->default_tablet_count = 10;
    
    FILE *file = fopen("tmp/message", "w");
    mu_assert_bool(sky_create_table_message_pack(message, file) == 0);
    fclose(file);
    mu_assert_file("tmp/message", "tests/fixtures/create_table_message/0/message");
    sky_table_free(message->table);
    sky_create_table_message_free(message);
    return 0;
}
Ejemplo n.º 11
0
// Opens a table and attaches it to the server.
//
// server - The server.
// name   - The table name.
// path   - The table path.
// ret    - A pointer to where the table reference should be returned.
//
// Returns 0 if successful, otherwise returns -1.
int sky_server_open_table(sky_server *server, bstring name, bstring path,
                          sky_table **ret)
{
    int rc;
    sky_table *table = NULL;
    assert(server != NULL);
    assert(ret != NULL);
    check(blength(path) > 0, "Table path required");
    
    // Initialize return values.
    *ret = NULL;
    
    // Only open the table if it exists already.
    if(sky_file_exists(path)) {
        // Create the table.
        table = sky_table_create(); check_mem(table);
        table->name = bstrcpy(name); check_mem(table->name);
        rc = sky_table_set_path(table, path);
        check(rc == 0, "Unable to set table path");

        // Open the table.
        rc = sky_table_open(table);
        check(rc == 0, "Unable to open table");
    
        // Append the table to the list of open tables.
        server->table_count++;
        server->tables = realloc(server->tables, server->table_count * sizeof(*server->tables));
        check_mem(server->tables);
        server->tables[server->table_count-1] = table;

        // Open servlets for the table's tablets.
        rc = sky_server_create_servlets(server, table);
        check(rc == 0, "Unable to create servlets for table");

        // Return table.
        *ret = table;
    }

    return 0;

error:
    sky_table_free(table);
    if(ret) *ret = NULL;
    return -1;
}
Ejemplo n.º 12
0
int test_sky_get_property_message_process() {
    loadtmp("tests/fixtures/get_property_message/1/table");
    sky_server *server = sky_server_create(NULL);
    sky_message_header *header = sky_message_header_create();
    sky_table *table = sky_table_create();
    table->path = bfromcstr("tmp");
    sky_table_open(table);
    
    FILE *input = fopen("tests/fixtures/get_property_message/1/input", "r");
    FILE *output = fopen("tmp/output", "w");
    int rc = sky_get_property_message_process(server, header, table, input, output);
    mu_assert_int_equals(rc, 0);
    mu_assert_file("tmp/output", "tests/fixtures/get_property_message/1/output");

    sky_table_free(table);
    sky_message_header_free(header);
    sky_server_free(server);
    return 0;
}
Ejemplo n.º 13
0
int test_sky_add_event_message_worker_map() {
    importtmp("tests/fixtures/add_event_message/1/import.json");
    sky_table *table = sky_table_create();
    table->path = bfromcstr("tmp");
    table->default_tablet_count = 1;
    sky_table_open(table);

    struct tagbstring XYZ_STR = bsStatic("xyz");
    sky_add_event_message *message = sky_add_event_message_create();
    message->event = sky_event_create(10, 1000L, 20);
    message->event->data_count = 4;
    message->event->data = calloc(message->event->data_count, sizeof(*message->event->data));
    message->event->data[0] = sky_event_data_create_string(1, &XYZ_STR);
    message->event->data[1] = sky_event_data_create_int(2, 200);
    message->event->data[2] = sky_event_data_create_double(3, 100.2);
    message->event->data[3] = sky_event_data_create_boolean(4, true);
    sky_worker *worker = sky_worker_create();
    worker->data = (void*)message;

    void *null = NULL;
    int rc = sky_add_event_message_worker_map(worker, table->tablets[0], &null);
    mu_assert_int_equals(rc, 0);

    void *data;
    size_t data_length;
    sky_tablet_get_path(table->tablets[0], 10, &data, &data_length);
    mu_assert_int_equals(rc, 0);
    mu_assert_mem(
        data, 
        "\x03\xE8\x03\x00\x00\x00\x00\x00\x00\x14\x00\x15\x00\x00\x00\x01"
        "\xA3\x78\x79\x7A\x02\xD1\x00\xC8\x03\xCB\x40\x59\x0C\xCC\xCC\xCC"
        "\xCC\xCD\x04\xC3",
        data_length
    );

    free(data);
    sky_add_event_message_free(message);
    sky_worker_free(worker);
    sky_table_free(table);
    return 0;
}
Ejemplo n.º 14
0
// Retrieves a reference to a table by name. If the table is not found then
// it will be opened automatically.
//
// server - The server.
// name   - The table name.
// ret    - A pointer to where the table reference should be returned.
//
// Returns 0 if successful, otherwise returns -1.
int sky_server_get_table(sky_server *server, bstring name, sky_table **ret)
{
    int rc;
    sky_table *table = NULL;
    bstring path = NULL;
    assert(server != NULL);
    check(blength(name) > 0, "Table name required");
    
    // Initialize return values.
    *ret = NULL;
    
    // Determine the path to the table.
    path = bformat("%s/%s", bdata(server->path), bdata(name));
    check_mem(path);

    // Loop over tables to see if it's open yet.
    uint32_t i;
    for(i=0; i<server->table_count; i++) {
        if(biseq(server->tables[i]->path, path) == 1) {
            *ret = server->tables[i];
            break;
        }
    }

    // If the table is not yet opened then open it.
    if(*ret == NULL) {
        rc = sky_server_open_table(server, name, path, ret);
        check(rc == 0, "Unable to open table");
    }

    bdestroy(path);
    return 0;

error:
    bdestroy(path);
    sky_table_free(table);
    *ret = NULL;
    return -1;
}
Ejemplo n.º 15
0
int test_sky_lua_initscript_with_table() {
    int rc;
    importtmp("tests/fixtures/sky_lua/0/data.json");
    sky_table *table = sky_table_create();
    table->path = bfromcstr("tmp");
    sky_table_open(table);
    sky_data_descriptor *descriptor = sky_data_descriptor_create();

    sky_lua_event_0_t lua_event = {0, 0, 1, 20, 30};

    struct tagbstring source = bsStatic(
        "function aggregate(_event)\n"
        "  event = ffi.cast('sky_lua_event_t*', _event)\n"
        "  return event.x + event.y\n"
        "end\n"
    );
    lua_State *L = NULL;
    rc = sky_lua_initscript_with_table(&source, table, descriptor, &L);
    mu_assert_int_equals(rc, 0);
    mu_assert_int_equals(descriptor->timestamp_descriptor.ts_offset, 0);
    mu_assert_int_equals(descriptor->timestamp_descriptor.timestamp_offset, 8);
    mu_assert_int_equals(descriptor->action_descriptor.offset, 12);
    mu_assert_int_equals(descriptor->property_zero_descriptor[1].offset, 0);
    mu_assert_int_equals(descriptor->property_zero_descriptor[2].offset, (int)offsetof(sky_lua_event_0_t, x));
    mu_assert_int_equals(descriptor->property_zero_descriptor[3].offset, (int)offsetof(sky_lua_event_0_t, y));
    mu_assert_int_equals(descriptor->property_zero_descriptor[4].offset, 0);

    // Call aggregate() function with the event pointer.
    lua_getglobal(L, "aggregate");
    lua_pushlightuserdata(L, &lua_event);
    lua_call(L, 1, 1);
    mu_assert_int_equals(rc, 0);
    mu_assert_long_equals(lua_tointeger(L, -1), 50L);
    
    sky_table_free(table);
    return 0;
}
Ejemplo n.º 16
0
int test_sky_peach_message_process() {
    importtmp("tests/fixtures/peach_message/1/import.json");
    sky_table *table = sky_table_create();
    table->path = bfromcstr("tmp");
    sky_table_open(table);
    
    // NOTE: The table contains two properties: foo (String) and this_is_a_really...(Int)
    sky_peach_message *message = sky_peach_message_create();
    message->query = bfromcstr(
        "[Hashable(\"id\")]\n"
        "[Serializable]\n"
        "class Result {\n"
        "  public Int id;\n"
        "  public Int count;\n"
        "  public Int objectTotal;\n"
        "  public Int actionTotal;\n"
        "}\n"
        "Cursor cursor = path.events();\n"
        "for each (Event event in cursor) {\n"
        "  String dynamic_prop2 = event.this_is_a_really_long_property_name_woohoo;\n"
        "  Result item = data.get(event.actionId);\n"
        "  item.count = item.count + 1;\n"
        "  item.objectTotal = item.objectTotal + event.object_prop;\n"
        "  item.actionTotal = item.actionTotal + event.action_prop;\n"
        "}\n"
        "return;"
    );

    FILE *output = fopen("tmp/output", "w");
    mu_assert(sky_peach_message_process(message, table, output) == 0, "");
    fclose(output);
    mu_assert_file("tmp/output", "tests/fixtures/peach_message/1/output");

    sky_peach_message_free(message);
    sky_table_free(table);
    return 0;
}
Ejemplo n.º 17
0
// Executes the benchmark over the database to compute step counts in order to
// generate a directed acyclic graph (DAG).
//
// options - A list of options to use.
void benchmark_dag(Options *options)
{
    int rc;
    sky_event *event = NULL;
    uint32_t event_count = 0;
    int32_t action_count = 100;     // TODO: Retrieve action count from actions file.
    
    // Initialize table.
    sky_table *table = sky_table_create(); check_mem(table);
    rc = sky_table_set_path(table, options->path);
    check(rc == 0, "Unable to set path on table");
    
    // Open table
    rc = sky_table_open(table);
    check(rc == 0, "Unable to open table");

    // Loop for desired number of iterations.
    int i;
    for(i=0; i<options->iterations; i++) {
        sky_path_iterator iterator;
        sky_path_iterator_init(&iterator);
        
        // Attach data file.
        rc = sky_path_iterator_set_data_file(&iterator, table->data_file);
        check(rc == 0, "Unable to initialze path iterator");
        
        // Create a square matrix of structs.
        Step *steps = calloc(action_count*action_count, sizeof(Step));

        // Iterate over each path.
        while(!iterator.eof) {
            sky_action_id_t action_id, prev_action_id;

            // Retrieve the path pointer.
            void *path_ptr;
            rc = sky_path_iterator_get_ptr(&iterator, &path_ptr);
            check(rc == 0, "Unable to retrieve the path iterator pointer");
        
            // Initialize the cursor.
            sky_cursor cursor;
            sky_cursor_init(&cursor);
            rc = sky_cursor_set_path(&cursor, path_ptr);
            check(rc == 0, "Unable to set cursor path");

            // Increment total event count.
            event_count++;
            
            // Initialize the previous action.
            rc = sky_cursor_get_action_id(&cursor, &prev_action_id);
            check(rc == 0, "Unable to retrieve first action");

            // Find next event.
            rc = sky_cursor_next(&cursor);
            check(rc == 0, "Unable to find next event");

            // Loop over each event in the path.
            while(!cursor.eof) {
                // Increment total event count.
                event_count++;

                // Retrieve action.
                rc = sky_cursor_get_action_id(&cursor, &action_id);
                check(rc == 0, "Unable to retrieve first action");

                // Aggregate step information.
                int32_t index = ((prev_action_id-1)*action_count) + (action_id-1);
                steps[index].count++;

                // Assign current action as previous action.
                prev_action_id = action_id;

                // Find next event.
                rc = sky_cursor_next(&cursor);
                check(rc == 0, "Unable to find next event");
            }
            
            rc = sky_path_iterator_next(&iterator);
            check(rc == 0, "Unable to find next path");
        }
        
        // Show DAG data.
        //int x;
        //int total=0;
        //for(x=0; x<action_count*action_count; x++) {
        //    printf("%06d %d\n", x, steps[x].count);
        //    total += steps[x].count;
        //}
        //printf("total: %d\n", total);
    }
    
    // Clean up
    rc = sky_table_close(table);
    check(rc == 0, "Unable to close table");
    sky_table_free(table);

    // Show stats.
    printf("Total events processed: %d\n", event_count);
    
    return;
    
error:
    sky_event_free(event);
    sky_table_free(table);
}
Ejemplo n.º 18
0
// Executes the benchmark to count the number of times an action occurred
// using the QIP language.
//
// options - A list of options to use.
void benchmark_count_with_qip(Options *options)
{
    int rc;
    uint32_t path_count = 0;
    
    // Initialize the query.
    qip_ast_node *type_ref, *var_decl;
    uint32_t arg_count = 2;
    qip_ast_node *args[arg_count];
    
    // Path arg.
    struct tagbstring path_str = bsStatic("path");
    type_ref = qip_ast_type_ref_create_cstr("Path");
    var_decl = qip_ast_var_decl_create(type_ref, &path_str, NULL);
    args[0] = qip_ast_farg_create(var_decl);
    
    // Map arg.
    struct tagbstring data_str = bsStatic("data");
    type_ref = qip_ast_type_ref_create_cstr("Map");
    qip_ast_type_ref_add_subtype(type_ref, qip_ast_type_ref_create_cstr("Int"));
    qip_ast_type_ref_add_subtype(type_ref, qip_ast_type_ref_create_cstr("Result"));
    var_decl = qip_ast_var_decl_create(type_ref, &data_str, NULL);
    args[1] = qip_ast_farg_create(var_decl);

    // Initialize query.
    struct tagbstring query = bsStatic(
        "[Hashable(\"id\")]\n"
        "class Result {\n"
        "  public Int id;\n"
        "  public Int count;\n"
        "}\n"
        "Cursor cursor = path.events();\n"
        "for each (Event event in cursor) {\n"
        "  Result item = data.get(event.actionId);\n"
        "  item.count = item.count + 1;\n"
        "}\n"
        "return;"
    );
    struct tagbstring module_name = bsStatic("qip");
    struct tagbstring core_class_path = bsStatic("lib/core");
    struct tagbstring sky_class_path = bsStatic("lib/sky");
    qip_compiler *compiler = qip_compiler_create();
    qip_compiler_add_class_path(compiler, &core_class_path);
    qip_compiler_add_class_path(compiler, &sky_class_path);
    qip_module *module = qip_module_create(&module_name, compiler);
    rc = qip_compiler_compile(compiler, module, &query, args, arg_count);
    check(rc == 0, "Unable to compile");
    if(module->error_count > 0) fprintf(stderr, "Parse error [line %d] %s\n", module->errors[0]->line_no, bdata(module->errors[0]->message));
    check(module->error_count == 0, "Compile error");
    qip_compiler_free(compiler);

    // Retrieve pointer to function.
    sky_qip_path_map_func process_path = NULL;
    rc = qip_module_get_main_function(module, (void*)(&process_path));
    check(rc == 0, "Unable to retrieve main function");

    // Initialize table.
    sky_table *table = sky_table_create(); check_mem(table);
    rc = sky_table_set_path(table, options->path);
    check(rc == 0, "Unable to set path on table");
    
    // Open table
    rc = sky_table_open(table);
    check(rc == 0, "Unable to open table");

    // Loop for desired number of iterations.
    int i;
    for(i=0; i<options->iterations; i++) {
        sky_path_iterator iterator;
        sky_path_iterator_init(&iterator);

        // Attach data file.
        rc = sky_path_iterator_set_data_file(&iterator, table->data_file);
        check(rc == 0, "Unable to initialze path iterator");

        // Initialize QIP args.
        sky_qip_path *path = sky_qip_path_create();
        qip_map *map = qip_map_create();
        
        // Iterate over each path.
        while(!iterator.eof) {
            // Retrieve the path pointer.
            rc = sky_path_iterator_get_ptr(&iterator, &path->path_ptr);
            check(rc == 0, "Unable to retrieve the path iterator pointer");
        
            // Execute query.
            process_path(path, map);

            // Move to next path.
            rc = sky_path_iterator_next(&iterator);
            check(rc == 0, "Unable to find next path");

            path_count++;
        }
        
        // Clean up iteration.
        qip_map_free(map);
    }
    
    // Clean up
    rc = sky_table_close(table);
    check(rc == 0, "Unable to close table");
    sky_table_free(table);

    // Show stats.
    printf("Total paths processed: %d\n", path_count);
    
    return;
    
error:
    sky_table_free(table);
}