Example #1
0
/* raw request payload echoed in response */
void rpctest_rawecho_cb (flux_t *h, flux_msg_handler_t *w,
                         const flux_msg_t *msg, void *arg)
{
    int errnum = 0;
    void *d = NULL;
    int l = 0;

    if (flux_request_decode_raw (msg, NULL, &d, &l) < 0) {
        errnum = errno;
        goto done;
    }
done:
    (void)flux_respond_raw (h, msg, errnum, d, l);
}
void store_cb (flux_t *h, flux_msg_handler_t *mh,
               const flux_msg_t *msg, void *arg)
{
    sqlite_ctx_t *ctx = arg;
    const void *data;
    int size, hash_len;
    uint8_t hash[BLOBREF_MAX_DIGEST_SIZE];
    char blobref[BLOBREF_MAX_STRING_SIZE] = "-";
    int uncompressed_size = -1;
    int rc = -1;
    int old_state;
    //delay cancellation to ensure lock-correctness in sqlite
    pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &old_state);

    if (flux_request_decode_raw (msg, NULL, &data, &size) < 0) {
        flux_log_error (h, "store: request decode failed");
        goto done;
    }
    if (size > ctx->blob_size_limit) {
        errno = EFBIG;
        goto done;
    }
    if (blobref_hash (ctx->hashfun, (uint8_t *)data, size, blobref,
                      sizeof (blobref)) < 0)
        goto done;
    if ((hash_len = blobref_strtohash (blobref, hash, sizeof (hash))) < 0)
        goto done;
    if (size >= compression_threshold) {
        int r;
        int out_len = LZ4_compressBound(size);
        if (ctx->lzo_bufsize < out_len && grow_lzo_buf (ctx, out_len) < 0)
            goto done;
        r = LZ4_compress_default (data, ctx->lzo_buf, size, out_len);
        if (r == 0) {
            errno = EINVAL;
            goto done;
        }
        uncompressed_size = size;
        size = r;
        data = ctx->lzo_buf;
    }
    if (sqlite3_bind_text (ctx->store_stmt, 1, (char *)hash, hash_len,
                           SQLITE_STATIC) != SQLITE_OK) {
        log_sqlite_error (ctx, "store: binding key");
        set_errno_from_sqlite_error (ctx);
        goto done;
    }
    if (sqlite3_bind_int (ctx->store_stmt, 2, uncompressed_size) != SQLITE_OK) {
        log_sqlite_error (ctx, "store: binding size");
        set_errno_from_sqlite_error (ctx);
        goto done;
    }
    if (sqlite3_bind_blob (ctx->store_stmt, 3,
                           data, size, SQLITE_STATIC) != SQLITE_OK) {
        log_sqlite_error (ctx, "store: binding data");
        set_errno_from_sqlite_error (ctx);
        goto done;
    }
    if (sqlite3_step (ctx->store_stmt) != SQLITE_DONE
                    && sqlite3_errcode (ctx->db) != SQLITE_CONSTRAINT) {
        log_sqlite_error (ctx, "store: executing stmt");
        set_errno_from_sqlite_error (ctx);
        goto done;
    }
    rc = 0;
done:
    if (rc < 0) {
        if (flux_respond_error (h, msg, errno, NULL) < 0)
            flux_log_error (h, "store: flux_respond_error");
    }
    else {
        if (flux_respond_raw (h, msg, blobref, strlen (blobref) + 1) < 0)
            flux_log_error (h, "store: flux_respond_raw");
    }
    (void) sqlite3_reset (ctx->store_stmt);
    pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &old_state);
}
void load_cb (flux_t *h, flux_msg_handler_t *mh,
              const flux_msg_t *msg, void *arg)
{
    sqlite_ctx_t *ctx = arg;
    const char *blobref = "-";
    int blobref_size;
    uint8_t hash[BLOBREF_MAX_DIGEST_SIZE];
    int hash_len;
    const void *data = NULL;
    int size = 0;
    int uncompressed_size;
    int rc = -1;
    int old_state;
    //delay cancellation to ensure lock-correctness in sqlite
    pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &old_state);

    if (flux_request_decode_raw (msg, NULL, (const void **)&blobref,
                                 &blobref_size) < 0) {
        flux_log_error (h, "load: request decode failed");
        goto done;
    }
    if (!blobref || blobref[blobref_size - 1] != '\0') {
        errno = EPROTO;
        flux_log_error (h, "load: malformed blobref");
        goto done;
    }
    if ((hash_len = blobref_strtohash (blobref, hash, sizeof (hash))) < 0) {
        errno = ENOENT;
        flux_log_error (h, "load: unexpected foreign blobref");
        goto done;
    }
    if (sqlite3_bind_text (ctx->load_stmt, 1, (char *)hash, hash_len,
                                              SQLITE_STATIC) != SQLITE_OK) {
        log_sqlite_error (ctx, "load: binding key");
        set_errno_from_sqlite_error (ctx);
        goto done;
    }
    if (sqlite3_step (ctx->load_stmt) != SQLITE_ROW) {
        //log_sqlite_error (ctx, "load: executing stmt");
        errno = ENOENT;
        goto done;
    }
    size = sqlite3_column_bytes (ctx->load_stmt, 0);
    if (sqlite3_column_type (ctx->load_stmt, 0) != SQLITE_BLOB && size > 0) {
        flux_log (h, LOG_ERR, "load: selected value is not a blob");
        errno = EINVAL;
        goto done;
    }
    data = sqlite3_column_blob (ctx->load_stmt, 0);
    if (sqlite3_column_type (ctx->load_stmt, 1) != SQLITE_INTEGER) {
        flux_log (h, LOG_ERR, "load: selected value is not an integer");
        errno = EINVAL;
        goto done;
    }
    uncompressed_size = sqlite3_column_int (ctx->load_stmt, 1);
    if (uncompressed_size != -1) {
        if (ctx->lzo_bufsize < uncompressed_size
                                && grow_lzo_buf (ctx, uncompressed_size) < 0)
            goto done;
        int r = LZ4_decompress_safe (data, ctx->lzo_buf, size, uncompressed_size);
        if (r < 0) {
            errno = EINVAL;
            goto done;
        }
        if (r != uncompressed_size) {
            flux_log (h, LOG_ERR, "load: blob size mismatch");
            errno = EINVAL;
            goto done;
        }
        data = ctx->lzo_buf;
        size = uncompressed_size;
    }
    rc = 0;
done:
    if (rc < 0) {
        if (flux_respond_error (h, msg, errno, NULL) < 0)
            flux_log_error (h, "load: flux_respond_error");
    }
    else {
        if (flux_respond_raw (h, msg, data, size) < 0)
            flux_log_error (h, "load: flux_respond_raw");
    }
    (void )sqlite3_reset (ctx->load_stmt);
    pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &old_state);
}
Example #4
0
int main (int argc, char *argv[])
{
    flux_msg_t *msg;
    const char *topic, *s;
    const char *json_str = "{\"a\":42}";
    const void *d;
    const char data[] = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
    int i, l, len = strlen (data);

    plan (NO_PLAN);

    /* no topic is an error */
    errno = 0;
    ok ((msg = flux_request_encode (NULL, json_str)) == NULL
        && errno == EINVAL,
        "flux_request_encode returns EINVAL with no topic string");
    ok ((msg = flux_request_encode_raw (NULL, data, strlen (data))) == NULL
        && errno == EINVAL,
        "flux_request_encode_raw returns EINVAL with no topic string");

    /* without payload */
    ok ((msg = flux_request_encode ("foo.bar", NULL)) != NULL,
        "flux_request_encode works with NULL payload");
    topic = NULL;
    ok (flux_request_decode (msg, &topic, NULL) == 0
        && topic != NULL && !strcmp (topic, "foo.bar"),
        "flux_request_decode returns encoded topic");
    ok (flux_request_decode (msg, NULL, NULL) == 0,
        "flux_request_decode topic is optional");
    errno = 0;
    ok (flux_request_decode (msg, NULL, &s) == 0 && s == NULL,
        "flux_request_decode returns s = NULL when expected payload is missing");
    flux_msg_destroy(msg);

    /* with JSON payload */
    ok ((msg = flux_request_encode ("foo.bar", json_str)) != NULL,
        "flux_request_encode works with payload");

    s = NULL;
    ok (flux_request_decode (msg, NULL, &s) == 0
        && s != NULL && !strcmp (s, json_str),
        "flux_request_decode returns encoded payload");
    topic = NULL;
    i = 0;
    ok (flux_request_unpack (msg, &topic, "{s:i}", "a", &i) == 0
        && i == 42 && topic != NULL && !strcmp (topic, "foo.bar"),
        "flux_request_unpack returns encoded payload");

    errno = 0;
    ok (flux_request_decode (msg, NULL, NULL) == 0,
        "flux_request_decode works with payload but don't want the payload");
    flux_msg_destroy(msg);

    /* without payload (raw) */
    ok ((msg = flux_request_encode_raw ("foo.bar", NULL, 0)) != NULL,
        "flux_request_encode_raw works with NULL payload");
    topic = NULL;
    ok (flux_request_decode_raw (msg, &topic, &d, &l) == 0
        && topic != NULL && !strcmp (topic, "foo.bar"),
        "flux_request_decode_raw returns encoded topic");
    ok (flux_request_decode_raw (msg, NULL, &d, &l) == 0,
        "flux_request_decode_raw topic is optional");
    d = (char *)&d;
    l = 1;
    ok (flux_request_decode_raw (msg, NULL, &d, &l) == 0 && l == 0 && d == NULL,
        "flux_request_decode_raw returned NULL payload");
    flux_msg_destroy(msg);

    /* with raw payload */
    ok ((msg = flux_request_encode_raw ("foo.bar", data, len)) != NULL,
        "flux_request_encode_raw works with payload");

    d = NULL;
    l = 0;
    ok (flux_request_decode_raw (msg, NULL, &d, &l) == 0
        && d != NULL && l == len && memcmp (d, data, len) == 0,
        "flux_request_decode_raw returns encoded payload");
    flux_msg_destroy(msg);

    done_testing();
    return (0);
}