Exemplo n.º 1
0
/**
 * Internal method to handle a command that relies
 * on a filter name and a single key, responses are handled using
 * handle_multi_response.
 */
static void handle_filt_cmd(bloom_conn_handler *handle, char *args, int args_len,
        int(*filtmgr_func)(bloom_filtmgr *, char*)) {
    // If we have no args, complain.
    if (!args) {
        handle_client_err(handle->conn, (char*)&FILT_NEEDED, FILT_NEEDED_LEN);
        return;
    }

    // Scan past the filter name
    char *key;
    int key_len;
    int after = buffer_after_terminator(args, args_len, ' ', &key, &key_len);
    if (after == 0) {
        handle_client_err(handle->conn, (char*)&UNEXPECTED_ARGS, UNEXPECTED_ARGS_LEN);
        return;
    }

    // Call into the filter manager
    int res = filtmgr_func(handle->mgr, args);
    switch (res) {
        case 0:
            handle_client_resp(handle->conn, (char*)DONE_RESP, DONE_RESP_LEN);
            break;
        case -1:
            handle_client_resp(handle->conn, (char*)FILT_NOT_EXIST, FILT_NOT_EXIST_LEN);
            break;
        case -2:
            handle_client_resp(handle->conn, (char*)FILT_NOT_PROXIED, FILT_NOT_PROXIED_LEN);
            break;
        default:
            INTERNAL_ERROR();
            break;
    }
}
Exemplo n.º 2
0
/**
 * Invoked by the networking layer when there is new
 * data to be handled. The connection handler should
 * consume all the input possible, and generate responses
 * to all requests.
 * @arg handle The connection related information
 * @return 0 on success.
 */
int handle_client_connect(bloom_conn_handler *handle) {
    // Look for the next command line
    char *buf, *arg_buf;
    int buf_len, arg_buf_len, should_free;
    int status;
    while (1) {
        status = extract_to_terminator(handle->conn, '\n', &buf, &buf_len, &should_free);
        if (status == -1) break; // Return if no command is available

        // Determine the command type
        conn_cmd_type type = determine_client_command(buf, buf_len, &arg_buf, &arg_buf_len);

        // Handle an error or unknown response
        switch(type) {
            case CHECK:
                handle_check_cmd(handle, arg_buf, arg_buf_len);
                break;
            case CHECK_MULTI:
                handle_check_multi_cmd(handle, arg_buf, arg_buf_len);
                break;
            case SET:
                handle_set_cmd(handle, arg_buf, arg_buf_len);
                break;
            case SET_MULTI:
                handle_set_multi_cmd(handle, arg_buf, arg_buf_len);
                break;
            case CREATE:
                handle_create_cmd(handle, arg_buf, arg_buf_len);
                break;
            case DROP:
                handle_drop_cmd(handle, arg_buf, arg_buf_len);
                break;
            case CLOSE:
                handle_close_cmd(handle, arg_buf, arg_buf_len);
                break;
            case CLEAR:
                handle_clear_cmd(handle, arg_buf, arg_buf_len);
                break;
            case LIST:
                handle_list_cmd(handle, arg_buf, arg_buf_len);
                break;
            case INFO:
                handle_info_cmd(handle, arg_buf, arg_buf_len);
                break;
            case FLUSH:
                handle_flush_cmd(handle, arg_buf, arg_buf_len);
                break;
            default:
                handle_client_err(handle->conn, (char*)&CMD_NOT_SUP, CMD_NOT_SUP_LEN);
                break;
        }

        // Make sure to free the command buffer if we need to
        if (should_free) free(buf);
    }

    return 0;
}
Exemplo n.º 3
0
static void handle_info_cmd(bloom_conn_handler *handle, char *args, int args_len) {
    // If we have no args, complain.
    if (!args) {
        handle_client_err(handle->conn, (char*)&FILT_NEEDED, FILT_NEEDED_LEN);
        return;
    }

    // Scan past the filter name
    char *key;
    int key_len;
    int after = buffer_after_terminator(args, args_len, ' ', &key, &key_len);
    if (after == 0) {
        handle_client_err(handle->conn, (char*)&UNEXPECTED_ARGS, UNEXPECTED_ARGS_LEN);
        return;
    }

    // Create output buffers
    char *output[] = {(char*)&START_RESP, NULL, (char*)&END_RESP};
    int lens[] = {START_RESP_LEN, 0, END_RESP_LEN};

    // Invoke the callback to get the filter stats
    int res = filtmgr_filter_cb(handle->mgr, args, info_filter_cb, &output[1]);

    // Check for no filter
    if (res != 0) {
        switch (res) {
            case -1:
                handle_client_resp(handle->conn, (char*)FILT_NOT_EXIST, FILT_NOT_EXIST_LEN);
                break;
            default:
                INTERNAL_ERROR();
                break;
        }
        return;
    }

    // Adjust the buffer size
    lens[1] = strlen(output[1]);

    // Write out the bufs
    send_client_response(handle->conn, (char**)&output, (int*)&lens, 3);
    free(output[1]);
}
Exemplo n.º 4
0
/**
 * Internal command used to handle filter creation.
 */
static void handle_create_cmd(bloom_conn_handler *handle, char *args, int args_len) {
    // If we have no args, complain.
    if (!args) {
        handle_client_err(handle->conn, (char*)&FILT_NEEDED, FILT_NEEDED_LEN);
        return;
    }

    // Scan for options after the filter name
    char *options;
    int options_len;
    int res = buffer_after_terminator(args, args_len, ' ', &options, &options_len);

    // Verify the filter name is valid
    char *filter_name = args;
    if (regexec(&VALID_FILTER_NAMES_RE, filter_name, 0, NULL, 0) != 0) {
        handle_client_err(handle->conn, (char*)&BAD_FILT_NAME, BAD_FILT_NAME_LEN);
        return;
    }

    // Parse the options
    bloom_config *config = NULL;
    int err = 0;
    if (res == 0) {
        // Make a new config store, copy the current
        config = malloc(sizeof(bloom_config));
        memcpy(config, handle->config, sizeof(bloom_config));

        // Parse any options
        char *param = options;
        while (param) {
            // Adds a zero terminator to the current param, scans forward
            buffer_after_terminator(options, options_len, ' ', &options, &options_len);

            // Check for the custom params
            int match = 0;
            match |= sscanf(param, "capacity=%llu", (unsigned long long*)&config->initial_capacity);
            match |= sscanf(param, "prob=%lf", &config->default_probability);
            match |= sscanf(param, "in_memory=%d", &config->in_memory);

            // Check if there was no match
            if (!match) {
                err = 1;
                handle_client_err(handle->conn, (char*)&BAD_ARGS, BAD_ARGS_LEN);
                break;
            }

            // Advance to the next param
            param = options;
        }

        // Validate the params
        int invalid_config = 0;
        invalid_config |= sane_initial_capacity(config->initial_capacity);
        invalid_config |= sane_default_probability(config->default_probability);
        invalid_config |= sane_in_memory(config->in_memory);

        // Barf if the configs are bad
        if (invalid_config) {
            err = 1;
            handle_client_err(handle->conn, (char*)&BAD_ARGS, BAD_ARGS_LEN);
        }
    }

    // Clean up an leave on errors
    if (err) {
        if (config) free(config);
        return;
    }

    // Create a new filter
    res = filtmgr_create_filter(handle->mgr, filter_name, config);
    switch (res) {
        case 0:
            handle_client_resp(handle->conn, (char*)DONE_RESP, DONE_RESP_LEN);
            break;
        case -1:
            handle_client_resp(handle->conn, (char*)EXISTS_RESP, EXISTS_RESP_LEN);
            if (config) free(config);
            break;
        case -3:
            handle_client_resp(handle->conn, (char*)DELETE_IN_PROGRESS, DELETE_IN_PROGRESS_LEN);
            if (config) free(config);
            break;
        default:
            INTERNAL_ERROR();
            if (config) free(config);
            break;
    }
}