예제 #1
0
// Delegates processing of the 'Multi' message to a worker.
//
// server - The server.
// header - The message header.
// table  - The table the message is working against
// input  - The input file stream.
// output - The output file stream.
//
// Returns 0 if successful, otherwise returns -1.
int sky_multi_message_process(sky_server *server,
                              sky_message_header *header,
                              sky_table *table,
                              FILE *input, FILE *output)
{
    int rc = 0;
    size_t sz;
    sky_multi_message *message = NULL;
    assert(header != NULL);
    assert(table == NULL);
    assert(input != NULL);
    assert(output != NULL);

    // Parse message.
    message = sky_multi_message_create();
    check_mem(message);
    rc = sky_multi_message_unpack(message, input);
    check(rc == 0, "Unable to unpack 'multi' message");

    // Send back an array header with the number of responses so the client
    // will know how many to expect.
    minipack_fwrite_array(output, message->message_count, &sz);
    check(sz > 0, "Unable to write multi message array");

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

    // Loop over child messages and process.
    uint32_t i;
    for(i=0; i<message->message_count; i++) {
        rc = sky_server_process_message(server, true, input, output);
        check(rc == 0, "Unable to process child message");

        // HACK: ZeroMQ is not releasing file handles soon enough so the sleep
        // is used to wait for some to close. This needs to be changed so that
        // all workers share the same ZeroMQ sockets.
        if(i % 1000 == 0) sleep(1);
    }

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

    // Close streams.
    fclose(input);
    fclose(output);

    sky_multi_message_free(message);

    return 0;

error:
    sky_multi_message_free(message);
    fclose(input);
    fclose(output);
    return -1;
}
예제 #2
0
// Retrieves a list of properties from the server for a table. This function is
// synchronous and does not use a worker.
//
// server - The server.
// header - The message header.
// table  - The table the message is working against
// input  - The input file stream.
// output - The output file stream.
//
// Returns 0 if successful, otherwise returns -1.
int sky_get_properties_message_process(sky_server *server,
                                       sky_message_header *header,
                                       sky_table *table, FILE *input, FILE *output)
{
    int rc = 0;
    size_t sz;
    sky_get_properties_message *message = NULL;
    check(server != NULL, "Server required");
    check(header != NULL, "Message header required");
    check(table != NULL, "Table required");
    check(input != NULL, "Input stream required");
    check(output != NULL, "Output stream required");
    
    struct tagbstring status_str = bsStatic("status");
    struct tagbstring ok_str = bsStatic("ok");
    struct tagbstring properties_str = bsStatic("properties");

    // Parse message.
    message = sky_get_properties_message_create(); check_mem(message);
    rc = sky_get_properties_message_unpack(message, input);
    check(rc == 0, "Unable to parse 'get_properties' message");

    // Return.
    //   {status:"OK", properties:[{...}]}
    minipack_fwrite_map(output, 2, &sz);
    check(sz > 0, "Unable to write output");
    check(sky_minipack_fwrite_bstring(output, &status_str) == 0, "Unable to write status key");
    check(sky_minipack_fwrite_bstring(output, &ok_str) == 0, "Unable to write status value");
    check(sky_minipack_fwrite_bstring(output, &properties_str) == 0, "Unable to write properties key");

    // Loop over properties and serialize them.
    minipack_fwrite_array(output, table->property_file->property_count, &sz);
    check(sz > 0, "Unable to write properties array");
    
    uint32_t i;
    for(i=0; i<table->property_file->property_count; i++) {
        sky_property *property = table->property_file->properties[i];
        check(sky_property_pack(property, output) == 0, "Unable to write property");
    }

    // Clean up.
    sky_get_properties_message_free(message);
    fclose(input);
    fclose(output);

    return 0;

error:
    sky_get_properties_message_free(message);
    if(input) fclose(input);
    if(output) fclose(output);
    return -1;
}
예제 #3
0
// Saves actions to file.
//
// action_file - The action file to save.
//
// Returns 0 if successful, otherwise returns -1.
int sky_action_file_save(sky_action_file *action_file)
{
    int rc;
    size_t sz;
    FILE *file = NULL;
    assert(action_file != NULL);
    check(action_file->path != NULL, "Action file path required");

    // Open file.
    file = fopen(bdata(action_file->path), "w");
    check(file, "Failed to open action file: %s", bdata(action_file->path));

    // Write action count.
    rc = minipack_fwrite_array(file, action_file->action_count, &sz);
    check(rc == 0, "Unable to write actions array at byte: %ld", ftell(file));

    // Write actions.
    uint32_t i;
    for(i=0; i<action_file->action_count; i++) {
        sky_action *action = action_file->actions[i];

        // Write action id.
        minipack_fwrite_uint(file, action->id, &sz);
        check(sz != 0, "Unable to write action identifier at byte: %ld", ftell(file));

        // Write action name.
        rc = sky_minipack_fwrite_bstring(file, action->name);
        check(rc == 0, "Unable to write action name at byte: %ld", ftell(file));
    }

    // Close the file.
    fclose(file);

    return 0;

error:
    if(file) fclose(file);
    return -1;
}