static int mcd_write( struct ast_channel *chan, const char *cmd, char *parse, const char *value ) { memcached_return_t rc; memcached_st *mcd = memcached_pool_fetch(mcdpool, &to, &rc); if (rc) { ast_log(LOG_WARNING, "mcd_write: memcached pool error: %d\n", rc); return 0; } char *key = (char *)ast_malloc(MEMCACHED_MAX_KEY); unsigned int timeout = mcdttl; mcd_set_operation_result(chan, MEMCACHED_SUCCESS); // the app argument is the key to set if (ast_strlen_zero(parse)) { ast_log(LOG_WARNING, "MCD() requires argument (key)\n"); mcd_set_operation_result(chan, MEMCACHED_ARGUMENT_NEEDED); free(key); return 0; } strcpy(key, parse); ast_log(LOG_DEBUG, "setting value for key: %s=%s\n", key, value); const char *ttlval = pbx_builtin_getvar_helper(chan, "MCDTTL"); if (ttlval) { timeout = atoi(ttlval); if ((timeout == 0) && (strcmp(ttlval, "0") != 0)) { ast_log(LOG_WARNING, "dialplan variable MCDTTL=%s (not numeric), will use time-to-live value in the config file\n", ttlval); timeout = mcdttl; } } ast_log(LOG_DEBUG, "timeout: %d\n", timeout); memcached_return_t mcdret = MEMCACHED_FAILURE; mcdret = memcached_set(mcd, key, strlen(key), value, strlen(value), (time_t)timeout, (uint32_t)0 ); if (mcdret) ast_log(LOG_WARNING, "memcached_%s() error %d: %s\n", cmd, mcdret, memcached_strerror(mcd, mcdret) ); mcd_set_operation_result(chan, mcdret); free(key); memcached_pool_release(mcdpool, mcd); return 0; }
void ESPMemCached::connect() { assertPool(); #if (LIBMEMCACHED_VERSION_HEX<0x53000) if (connection) memcached_pool_push(pool, connection); memcached_return_t rc; connection = memcached_pool_pop(pool, (struct timespec *)0 , &rc); #else if (connection) memcached_pool_release(pool, connection); memcached_return_t rc; connection = memcached_pool_fetch(pool, (struct timespec *)0 , &rc); #endif assertOnError(rc, "memcached_pool_pop failed - "); }
/// Wipe the contents of all the memcached servers immediately, if we can /// get a connection. If not, does nothing. void MemcachedStore::flush_all() { memcached_return_t rc; // Try to get a connection struct timespec wait_time; wait_time.tv_sec = 0; wait_time.tv_nsec = 100 * 1000 * 1000; memcached_st* st = memcached_pool_fetch(_pool, &wait_time, &rc); if (st != NULL) { // Got one: use it to wipe out the contents of the servers immediately. rc = memcached_flush(st, 0); memcached_pool_release(_pool, st); } }
static int mcd_read(struct ast_channel *chan, const char *cmd, char *parse, char *buffer, size_t buflen ) { // asterisk dialplan function that returns the contents of a memcached key memcached_return_t rc; memcached_st *mcd = memcached_pool_fetch(mcdpool, &to, &rc); if (rc) { ast_log(LOG_WARNING, "mcd_read: memcached pool error: %d\n", rc); return 0; } char *key = (char *)ast_malloc(MEMCACHED_MAX_KEY); buffer[0] = 0; if (ast_strlen_zero(parse)) { ast_log(LOG_WARNING, "MCD requires argument (key)\n"); mcd_set_operation_result(chan, MEMCACHED_ARGUMENT_NEEDED); free(key); return 0; } strcpy(key, parse); memcached_return_t mcdret; size_t szmcdval; uint32_t mcdflags; char *mcdval = memcached_get(mcd, key, strlen(key), &szmcdval, &mcdflags, &mcdret); if (mcdret) ast_log(LOG_WARNING, "MCD() error %d: %s\n", mcdret, memcached_strerror(mcd, mcdret) ); mcd_set_operation_result(chan, mcdret); if (mcdret == MEMCACHED_SUCCESS) { if (szmcdval > MAX_ASTERISK_VARLEN) { ast_log(LOG_WARNING, "returned value (%d bytes) longer that what an asterisk variable can accomodate (%d bytes)\n", (int)szmcdval, MAX_ASTERISK_VARLEN ); mcd_set_operation_result(chan, MEMCACHED_VALUE_TOO_LONG); } else ast_copy_string(buffer, mcdval, buflen); } free(key); memcached_pool_release(mcdpool, mcd); return 0; }
/// Update the data for a particular address of record. Writes the data /// atomically. If the underlying data has changed since it was last /// read, the update is rejected and this returns false; if the update /// succeeds, this returns true. /// /// If a connection cannot be obtained, returns a random boolean based on /// data found on the call stack at the point of entry. bool MemcachedStore::set_aor_data(const std::string& aor_id, ///< the SIP URI AoR* data) ///< the data to store { memcached_return_t rc; MemcachedAoR* aor_data = (MemcachedAoR*)data; // Try to get a connection. struct timespec wait_time; wait_time.tv_sec = 0; wait_time.tv_nsec = 100 * 1000 * 1000; memcached_st* st = memcached_pool_fetch(_pool, &wait_time, &rc); if (st != NULL) { // Got one: use it. // // Expire any old bindings before writing to the server. In theory, // if there are no bindings left we could delete the entry, but this // may cause concurrency problems because memcached does not support // cas on delete operations. In this case we do a memcached_cas with // an effectively immediate expiry time. int now = time(NULL); int max_expires = expire_bindings(aor_data, now); std::string value = serialize_aor(aor_data); if (aor_data->get_cas() == 0) { // New record, so attempt to add. This will fail if someone else // gets there first. rc = memcached_add(st, aor_id.data(), aor_id.length(), value.data(), value.length(), max_expires, 0); } else { // This is an update to an existing record, so use memcached_cas // to make sure it is atomic. rc = memcached_cas(st, aor_id.data(), aor_id.length(), value.data(), value.length(), max_expires, 0, aor_data->get_cas()); } memcached_pool_release(_pool, st); } return memcached_success(rc); }
static int mcdget_exec(struct ast_channel *chan, const char *data) { memcached_return_t rc; memcached_st *mcd = memcached_pool_fetch(mcdpool, &to, &rc); if (rc) { ast_log(LOG_WARNING, "mcdget_exec: memcached pool error: %d\n", rc); return 0; } char *argcopy; char *key = (char *)ast_malloc(MEMCACHED_MAX_KEY); mcd_set_operation_result(chan, MEMCACHED_SUCCESS); // parse the app arguments AST_DECLARE_APP_ARGS(args, AST_APP_ARG(varname); AST_APP_ARG(key); );
/// Retrieve the AoR data for a given SIP URI, creating it if there isn't /// any already, and returning NULL if we can't get a connection. AoR* MemcachedStore::get_aor_data(const std::string& aor_id) ///< the SIP URI { memcached_return_t rc; MemcachedAoR* aor_data = NULL; // Try to get a connection struct timespec wait_time; wait_time.tv_sec = 0; wait_time.tv_nsec = 100 * 1000 * 1000; memcached_st* st = memcached_pool_fetch(_pool, &wait_time, &rc); if (st != NULL) { // Got one: use it. const char* key_ptr = aor_id.data(); const size_t key_len = aor_id.length(); rc = memcached_mget(st, &key_ptr, &key_len, 1); if (memcached_success(rc)) { memcached_result_st result; memcached_result_create(st, &result); memcached_fetch_result(st, &result, &rc); if (memcached_success(rc)) { aor_data = deserialize_aor(std::string(memcached_result_value(&result), memcached_result_length(&result))); aor_data->set_cas(memcached_result_cas(&result)); int now = time(NULL); expire_bindings(aor_data, now); } else { // AoR does not exist, so create it. aor_data = new MemcachedAoR(); } } memcached_pool_release(_pool, st); } return (AoR*)aor_data; }
memcached_st *connection_pool::fetch(memcached_return_t *rc, struct timespec *timeout = &DEFAULT_POOL_FETCH_TIMEOUT) { return memcached_pool_fetch(_pool, timeout, rc); }