/** * \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; }
/* Not sure if we need this. */ static void _couchbase_error_callback(libcouchbase_t instance, libcouchbase_error_t error, const char *errinfo) { /* Ignore timeouts... */ if (error != LIBCOUCHBASE_ETIMEDOUT) { fprintf(stderr, "\nFATAL ERROR: %s\n", libcouchbase_strerror(instance, error)); if (errinfo && strlen(errinfo) != 0) { fprintf(stderr, "\t\"%s\"\n", errinfo); } } }
static void _mapcache_cache_couchbase_delete(mapcache_context *ctx, mapcache_tile *tile) { char *key; libcouchbase_t *instance; libcouchbase_error_t error; key = mapcache_util_get_tile_key(ctx, tile,NULL," \r\n\t\f\e\a\b","#"); GC_CHECK_ERROR(ctx); instance = _couchbase_get_connection(ctx, tile); error = libcouchbase_remove(*instance, 0, key, strlen(key), 0); if (error != LIBCOUCHBASE_SUCCESS) { ctx->set_error(ctx, 500, "couchbase: failed to delete key %s: %s", key, libcouchbase_strerror(*instance, error)); } libcouchbase_wait(*instance); error = libcouchbase_get_last_error(*instance); if (error != LIBCOUCHBASE_SUCCESS) { ctx->set_error(ctx, 500, "couchbase: failed to delete key %s: %s", key, libcouchbase_strerror(*instance, error)); } _couchbase_release_connection(tile, instance); }
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; }
void PLCBA_connect(SV *self) { libcouchbase_t instance; PLCBA_t *async; PLCB_t *base; libcouchbase_error_t err; _mk_common_vars(self, instance, base, async); if( (err = libcouchbase_connect(instance)) != LIBCOUCHBASE_SUCCESS) { die("Problem with initial connection: %s (%d)", libcouchbase_strerror(instance, err), err); } libcouchbase_wait(instance); }
static void error_callback(libcouchbase_t instance, libcouchbase_error_t err, const char *errinfo) { err_exit("Error %s: %s", libcouchbase_strerror(instance, err), errinfo); }
/** * \brief push tile data to couchbase * * writes the content of mapcache_tile::data to the configured couchbased instance(s) * \private \memberof mapcache_cache_couchbase * \sa mapcache_cache::tile_set() */ static void _mapcache_cache_couchbase_set(mapcache_context *ctx, mapcache_tile *tile) { char *key; libcouchbase_t *instance; libcouchbase_error_t error; const int max_retries = 3; int retries = max_retries; apr_interval_time_t delay; /* set expiration to one day if not configured */ libcouchbase_time_t expires = 86400; if(tile->tileset->auto_expire) expires = tile->tileset->auto_expire; mapcache_cache_couchbase *cache = (mapcache_cache_couchbase*)tile->tileset->cache; key = mapcache_util_get_tile_key(ctx, tile, NULL, " \r\n\t\f\e\a\b", "#"); GC_CHECK_ERROR(ctx); if(!tile->encoded_data) { tile->encoded_data = tile->tileset->format->write(ctx, tile->raw_image, tile->tileset->format); GC_CHECK_ERROR(ctx); } instance = _couchbase_get_connection(ctx, tile); GC_CHECK_ERROR(ctx); do { error = libcouchbase_store(*instance, &error, LIBCOUCHBASE_SET, key, strlen(key), tile->encoded_data->buf, tile->encoded_data->size, 0, expires, 0); if (error != LIBCOUCHBASE_SUCCESS) { _couchbase_release_connection(tile, instance); ctx->set_error(ctx, 500, "failed to store tile %d %d %d to couchbase cache %s due to eror %s.", tile->x, tile->y, tile->z, cache->cache.name, libcouchbase_strerror(*instance, error)); return; } libcouchbase_wait(*instance); if (error == LIBCOUCHBASE_ETMPFAIL) { if (retries > 0) { delay = 100000 * (1 << (max_retries - retries)); // Do an exponential back off of starting at 100 milliseconds apr_sleep(delay); } else { _couchbase_release_connection(tile, instance); ctx->set_error(ctx, 500, "failed to store tile %d %d %d to couchbase cache %s due to %s. Maximum number of retries used.", tile->x, tile->y, tile->z, cache->cache.name, libcouchbase_strerror(*instance, error)); return; } --retries; } else if (error != LIBCOUCHBASE_SUCCESS) { _couchbase_release_connection(tile, instance); ctx->set_error(ctx, 500, "failed to store tile %d %d %d to couchbase cache %s due to error %s.", tile->x, tile->y, tile->z, cache->cache.name, libcouchbase_strerror(*instance, error)); return; } } while (error == LIBCOUCHBASE_ETMPFAIL); _couchbase_release_connection(tile, instance); }