Пример #1
0
    void connection_pool::release(memcached_st *handle, memcached_return_t *rc)
    {
        memcached_return_t unused;
        if (rc == NULL) {
            rc = &unused;
        }

        *rc = memcached_pool_release(_pool, handle);
    }
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;

}
Пример #3
0
ESPMemCached::~ESPMemCached()
{
    if (pool)
    {
        memcached_pool_release(pool, connection);
        connection = nullptr;//For safety (from changing this destructor) as not implicit in either the above or below.
        memcached_st *memc = memcached_pool_destroy(pool);
        if (memc)
            memcached_free(memc);
    }
    else if (connection)//This should never be needed but just in case.
    {
        memcached_free(connection);
    }
}
Пример #4
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 - ");
}
Пример #5
0
  /// 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;

}
Пример #7
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);
  }
Пример #8
0
  /// 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;
  }