static void reproduce_double_free_error(void) { libcouchbase_error_t err; struct rvbuf rv; const char *key = "test_compare_and_swap_async_", *val = "{\"bar\" => 1}"; libcouchbase_size_t nkey = strlen(key), nval = strlen(val); /* prefill the bucket */ (void)libcouchbase_set_storage_callback(session, store_callback1); err = libcouchbase_store(session, &rv, LIBCOUCHBASE_SET, key, nkey, val, nval, 0, 0, 0); assert(err == LIBCOUCHBASE_SUCCESS); io->run_event_loop(io); assert(rv.error == LIBCOUCHBASE_SUCCESS); /* run exercise * * 1. get the value and its cas * 2. atomic set new value using old cas */ (void)libcouchbase_set_storage_callback(session, store_callback2); (void)libcouchbase_set_get_callback(session, get_callback); err = libcouchbase_mget(session, &rv, 1, (const void * const *)&key, &nkey, NULL); assert(err == LIBCOUCHBASE_SUCCESS); rv.cas1 = rv.cas2 = 0; io->run_event_loop(io); assert(rv.error == LIBCOUCHBASE_SUCCESS); assert(rv.cas1 > 0); assert(rv.cas2 > 0); assert(rv.cas1 != rv.cas2); }
/** * \brief get content of given tile * * fills the mapcache_tile::data of the given tile with content stored on the couchbase server * \private \memberof mapcache_cache_couchbase * \sa mapcache_cache::tile_get() */ static int _mapcache_cache_couchbase_get(mapcache_context *ctx, mapcache_tile *tile) { char *key[1]; size_t keySize[1]; libcouchbase_t *instance; libcouchbase_error_t error; getStruct_t request; key[0] = mapcache_util_get_tile_key(ctx, tile, NULL, " \r\n\t\f\e\a\b", "#"); if(GC_HAS_ERROR(ctx)) { return MAPCACHE_FAILURE; } keySize[0] = strlen(key[0]); tile->encoded_data = mapcache_buffer_create(0, ctx->pool); libcouchbase_time_t expires = 86400; if(tile->tileset->auto_expire) expires = tile->tileset->auto_expire; instance = _couchbase_get_connection(ctx, tile); if (GC_HAS_ERROR(ctx)) { return MAPCACHE_FAILURE; } request.tileBuffer = tile->encoded_data; error = libcouchbase_mget(*instance, &request, 1, (const void * const*)key, keySize, &expires); if (error != LIBCOUCHBASE_SUCCESS) { ctx->set_error(ctx, 500, "couchbase cache returned error on mget %s", libcouchbase_strerror(*instance, error)); _couchbase_invalidate_connection(tile, instance); return MAPCACHE_FAILURE; } libcouchbase_wait(*instance); if(request.error != LIBCOUCHBASE_SUCCESS) { _couchbase_release_connection(tile, instance); return MAPCACHE_CACHE_MISS; } if (tile->encoded_data->size == 0) { _couchbase_release_connection(tile, instance); ctx->set_error(ctx, 500, "couchbase cache returned 0-length data for tile %d %d %d", tile->x, tile->y, tile->z); return MAPCACHE_FAILURE; } apr_time_t now = apr_time_now(); tile->mtime = now; _couchbase_release_connection(tile, instance); return MAPCACHE_SUCCESS; }
static int _mapcache_cache_couchbase_has_tile(mapcache_context *ctx, mapcache_tile *tile) { char *key[1]; libcouchbase_t *instance; libcouchbase_error_t error; size_t keySize[1]; getStruct_t request; key[0] = mapcache_util_get_tile_key(ctx, tile, NULL, " \r\n\t\f\e\a\b", "#"); if(GC_HAS_ERROR(ctx)) { return MAPCACHE_FALSE; } keySize[0] = strlen(key[0]); instance = _couchbase_get_connection(ctx, tile); request.tileBuffer = 0; request.error = LIBCOUCHBASE_KEY_ENOENT; error = libcouchbase_mget(*instance, &request, 1, (const void * const*)key, keySize, 0); if (error != LIBCOUCHBASE_SUCCESS) { ctx->set_error(ctx, 500, "couchbase: failed to get key %s: %s", key, libcouchbase_strerror(*instance, error)); _couchbase_invalidate_connection(tile, instance); return MAPCACHE_FALSE; } libcouchbase_wait(*instance); error = request.error; if (error != LIBCOUCHBASE_SUCCESS) { ctx->set_error(ctx, 500, "couchbase: failed to get key %s: %s", key, libcouchbase_strerror(*instance, error)); _couchbase_invalidate_connection(tile, instance); return MAPCACHE_FALSE; } _couchbase_release_connection(tile, instance); return MAPCACHE_TRUE; }