static int php_memc_sess_lock(memcached_st *memc, const char *key)
{
	char *lock_key = NULL;
	int lock_key_len = 0;
	unsigned long attempts;
	long write_retry_attempts = 0;
	long lock_maxwait = MEMC_G(sess_lock_max_wait);
	long lock_wait = MEMC_G(sess_lock_wait);
	long lock_expire = MEMC_G(sess_lock_expire);
	time_t expiration;
	memcached_return status;
	/* set max timeout for session_start = max_execution_time.  (c) Andrei Darashenka, Richter & Poweleit GmbH */
	if (lock_maxwait <= 0) {
		lock_maxwait = zend_ini_long(ZEND_STRS("max_execution_time"), 0);
		if (lock_maxwait <= 0) {
			lock_maxwait = MEMC_SESS_LOCK_EXPIRATION;
		}
	}
	if (lock_wait == 0) {
		lock_wait = MEMC_SESS_DEFAULT_LOCK_WAIT;
	}
	if (lock_expire <= 0) {
		lock_expire = lock_maxwait;
	}
	expiration  = lock_expire + 1;
	attempts = (unsigned long)((1000000.0 / lock_wait) * lock_maxwait);

	/* Set the number of write retry attempts to the number of replicas times the number of attempts to remove a server */
	if (MEMC_G(sess_remove_failed_enabled)) {
		write_retry_attempts = MEMC_G(sess_number_of_replicas) * ( memcached_behavior_get(memc, MEMCACHED_BEHAVIOR_SERVER_FAILURE_LIMIT) + 1);
	}

	lock_key_len = spprintf(&lock_key, 0, "lock.%s", key);
	do {
		status = memcached_add(memc, lock_key, lock_key_len, "1", sizeof("1")-1, expiration, 0);
		if (status == MEMCACHED_SUCCESS) {
			MEMC_G(sess_locked) = 1;
			MEMC_G(sess_lock_key) = lock_key;
			MEMC_G(sess_lock_key_len) = lock_key_len;
			return 0;
		} else if (status != MEMCACHED_NOTSTORED && status != MEMCACHED_DATA_EXISTS) {
			if (write_retry_attempts > 0) {
				write_retry_attempts--;
				continue;
			}
			php_error_docref(NULL, E_WARNING, "Write of lock failed");
			break;
		}

		if (lock_wait > 0) {
			usleep(lock_wait);
		}
	} while(--attempts > 0);

	efree(lock_key);
	return -1;
}
static
time_t s_lock_expiration()
{
	if (MEMC_SESS_INI(lock_expiration) > 0) {
		return s_adjust_expiration(MEMC_SESS_INI(lock_expiration));
	}
	else {
		zend_long max_execution_time = zend_ini_long(ZEND_STRL("max_execution_time"), 0);
		if (max_execution_time > 0) {
			return s_adjust_expiration(max_execution_time);
		}
	}
	return 0;
}
ps_module ps_mod_memcached = {
	PS_MOD(memcached)
};

static int php_memc_sess_lock(memcached_st *memc, const char *key TSRMLS_DC)
{
	char *lock_key = NULL;
	int lock_key_len = 0;
	long attempts;
	long lock_maxwait;
	long lock_wait = MEMC_G(sess_lock_wait);
	time_t expiration;
	memcached_return status;
	/* set max timeout for session_start = max_execution_time.  (c) Andrei Darashenka, Richter & Poweleit GmbH */

	lock_maxwait = zend_ini_long(ZEND_STRS("max_execution_time"), 0);
	if (lock_maxwait <= 0) {
		lock_maxwait = MEMC_SESS_LOCK_EXPIRATION;
	}
	if (lock_wait == 0) {
		lock_wait = MEMC_SESS_DEFAULT_LOCK_WAIT;
	}
	expiration  = time(NULL) + lock_maxwait + 1;
	attempts = lock_maxwait * 1000000 / lock_wait;

	lock_key_len = spprintf(&lock_key, 0, "lock.%s", key);
	do {
		status = memcached_add(memc, lock_key, lock_key_len, "1", sizeof("1")-1, expiration, 0);
		if (status == MEMCACHED_SUCCESS) {
			MEMC_G(sess_locked) = 1;
			MEMC_G(sess_lock_key) = lock_key;