--- memcache.c 2013-04-08 05:12:54.000000000 +0300 +++ memcache.c 2014-07-22 16:21:26.000000000 +0300 @@ -1656,35 +1656,56 @@ mmc_value_handler_multi, value_handler_param, mmc_value_failover_handler, failover_handler_param, NULL TSRMLS_CC); } + mmc_pool_run(pool TSRMLS_CC); } else { mmc_request_t *request; + mmc_t *mmc; + mmc_queue_t skip_servers = {0}; + unsigned int last_index = 0; /* return false if key isn't found */ ZVAL_FALSE(return_value); - /* allocate request */ - request = mmc_pool_request_get( - pool, MMC_PROTO_UDP, - mmc_value_handler_single, value_handler_param, - mmc_pool_failover_handler, NULL TSRMLS_CC); - - if (mmc_prepare_key(keys, request->key, &(request->key_len)) != MMC_OK) { - mmc_pool_release(pool, request); - php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid key"); - return; - } - - pool->protocol->get(request, cas != NULL ? MMC_OP_GETS : MMC_OP_GET, keys, request->key, request->key_len); - - /* schedule request */ - if (mmc_pool_schedule_key(pool, request->key, request->key_len, request, 1 TSRMLS_CC) != MMC_OK) { - return; - } + /* [DG]: loop all servers to find out data */ + do { + /* allocate request */ + request = mmc_pool_request_get( + pool, MMC_PROTO_UDP, + mmc_value_handler_single, value_handler_param, + mmc_pool_failover_handler, NULL TSRMLS_CC); + + if (mmc_prepare_key(keys, request->key, &(request->key_len)) != MMC_OK) { + mmc_pool_release(pool, request); + php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid key"); + return; + } + + pool->protocol->get(request, cas != NULL ? MMC_OP_GETS : MMC_OP_GET, keys, request->key, request->key_len); + + /* find next server in line */ + mmc = mmc_pool_find_next(pool, request->key, request->key_len, &skip_servers, &last_index TSRMLS_CC); + + /* schedule the requests */ + if (!mmc_server_valid(mmc TSRMLS_CC) || + mmc_pool_schedule(pool, mmc, request TSRMLS_CC) != MMC_OK) { + mmc_pool_release(pool, request); + mmc_queue_push(&skip_servers, mmc); + continue; + } + mmc_pool_run(pool TSRMLS_CC); + + if (Z_TYPE_P(return_value) != IS_BOOL) { // [DG]: nobody stores BOOL in memcache, yeah :) + mmc_queue_free(&skip_servers); + return; + } + + /* if missing value, skip this server and try next */ + zval_dtor(return_value); + mmc_queue_push(&skip_servers, mmc); + } while (skip_servers.len < MEMCACHE_G(redundancy) && skip_servers.len < pool->num_servers); } - /* execute all requests */ - mmc_pool_run(pool TSRMLS_CC); } /* }}} */