Supress SIGPIPE when calling send() and connection has died

Improved socket error reporting
Improved performance by setting PHP_STREAM_BUFFER_NONE
Fixed PECL bug #14642 (3.0.x breaks BC with 2.2.x)
This commit is contained in:
Mikael Johansson
2009-01-16 15:38:46 +00:00
parent fa6fa47955
commit 79f5f95070
14 changed files with 211 additions and 118 deletions

3
README
View File

@@ -113,6 +113,9 @@ class MemcachePool() {
* The new defval (default value) and exptime (expiration time) are used
* if the key doesn't already exist. They must be supplied (even if 0) for
* this to be enabled.
*
* Returns an integer with the new value if key is a string
* Returns an array of integers if the key is an array
*/
mixed increment(mixed key, int value = 1, int defval = 0, int exptime = 0)
mixed decrement(mixed key, int value = 1, int defval = 0, int exptime = 0)

View File

@@ -374,9 +374,11 @@ static int mmc_get_pool(zval *id, mmc_pool_t **pool TSRMLS_DC) /* {{{ */
int mmc_stored_handler(mmc_t *mmc, mmc_request_t *request, int response, const char *message, unsigned int message_len, void *param TSRMLS_DC) /*
handles SET/ADD/REPLACE response, param is a zval pointer to store result into {{{ */
{
zval *result = (zval *)param;
if (response == MMC_OK) {
if (param != NULL && Z_TYPE_P((zval *)param) == IS_NULL) {
ZVAL_TRUE((zval *)param);
if (Z_TYPE_P(result) == IS_NULL) {
ZVAL_TRUE(result);
}
return MMC_REQUEST_DONE;
@@ -384,11 +386,10 @@ int mmc_stored_handler(mmc_t *mmc, mmc_request_t *request, int response, const c
/* return FALSE or catch memory errors without failover */
if (response == MMC_RESPONSE_EXISTS || response == MMC_RESPONSE_OUT_OF_MEMORY || response == MMC_RESPONSE_TOO_LARGE) {
if (param != NULL) {
ZVAL_FALSE((zval *)param);
}
ZVAL_FALSE(result);
if (response != MMC_RESPONSE_EXISTS) {
/* trigger notice but no need for failover */
php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Server %s (tcp %d, udp %d) failed with: %s (%d)",
mmc->host, mmc->tcp.port, mmc->udp.port, message, response);
}
@@ -455,14 +456,8 @@ static void php_mmc_store(INTERNAL_FUNCTION_PARAMETERS, int op) /* {{{ */
}
/* allocate request */
if (return_value_used) {
request = mmc_pool_request(pool, MMC_PROTO_TCP,
mmc_stored_handler, return_value, mmc_pool_failover_handler, NULL TSRMLS_CC);
}
else {
request = mmc_pool_request(pool, MMC_PROTO_TCP,
mmc_stored_handler, NULL, mmc_pool_failover_handler, NULL TSRMLS_CC);
}
request = mmc_pool_request(pool, MMC_PROTO_TCP,
mmc_stored_handler, return_value, mmc_pool_failover_handler, NULL TSRMLS_CC);
if (mmc_prepare_key_ex(ZSTR_VAL(key), key_len, request->key, &(request->key_len)) != MMC_OK) {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid key");
@@ -486,7 +481,6 @@ static void php_mmc_store(INTERNAL_FUNCTION_PARAMETERS, int op) /* {{{ */
}
}
else if (value) {
/* allocate request */
request = mmc_pool_request(pool, MMC_PROTO_TCP, mmc_stored_handler, return_value, mmc_pool_failover_handler, NULL TSRMLS_CC);
@@ -523,17 +517,28 @@ static void php_mmc_store(INTERNAL_FUNCTION_PARAMETERS, int op) /* {{{ */
static int mmc_numeric_response_handler(mmc_t *mmc, mmc_request_t *request, int response, const char *message, unsigned int message_len, void *param TSRMLS_DC) /*
handles a mutate response line, param is a zval pointer to store result into {{{ */
{
zval *result = (zval *)param;
if (response == MMC_OK) {
if (param != NULL && Z_TYPE_P((zval *)param) == IS_NULL) {
ZVAL_TRUE((zval *)param);
if (Z_TYPE_P(result) == IS_ARRAY) {
add_assoc_bool_ex(result, request->key, request->key_len + 1, 1);
}
else if (Z_TYPE_P(result) == IS_NULL) {
/* switch only from null to true, not from false to true */
ZVAL_TRUE(result);
}
return MMC_REQUEST_DONE;
}
if (response == MMC_RESPONSE_NOT_FOUND) {
if (param != NULL) {
ZVAL_FALSE((zval *)param);
if (Z_TYPE_P(result) == IS_ARRAY) {
add_assoc_bool_ex(result, request->key, request->key_len + 1, 0);
}
else {
ZVAL_FALSE(result);
}
return MMC_REQUEST_DONE;
}
@@ -551,15 +556,34 @@ static void php_mmc_numeric(INTERNAL_FUNCTION_PARAMETERS, int deleted, int inver
long value = 1, defval = 0, exptime = 0;
mmc_request_t *request;
void *value_handler_param[3];
int defval_used = 0;
if (mmc_object == NULL) {
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "Oz|lll", &mmc_object, memcache_pool_ce, &keys, &value, &defval, &exptime) == FAILURE) {
return;
if (deleted) {
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "Oz|l", &mmc_object, memcache_pool_ce, &keys, &value) == FAILURE) {
return;
}
}
else {
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "Oz|lll", &mmc_object, memcache_pool_ce, &keys, &value, &defval, &exptime) == FAILURE) {
return;
}
defval_used = ZEND_NUM_ARGS() >= 4;
}
}
else {
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z|lll", &keys, &value, &defval, &exptime) == FAILURE) {
return;
if (deleted) {
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z|l", &keys, &value) == FAILURE) {
return;
}
}
else {
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z|lll", &keys, &value, &defval, &exptime) == FAILURE) {
return;
}
defval_used = ZEND_NUM_ARGS() >= 3;
}
}
@@ -567,7 +591,6 @@ static void php_mmc_numeric(INTERNAL_FUNCTION_PARAMETERS, int deleted, int inver
RETURN_FALSE;
}
ZVAL_NULL(return_value);
value_handler_param[0] = return_value;
value_handler_param[1] = NULL;
value_handler_param[2] = NULL;
@@ -575,22 +598,24 @@ static void php_mmc_numeric(INTERNAL_FUNCTION_PARAMETERS, int deleted, int inver
if (Z_TYPE_P(keys) == IS_ARRAY) {
zval **key;
HashPosition pos;
zend_hash_internal_pointer_reset_ex(Z_ARRVAL_P(keys), &pos);
if (deleted) {
/* changed to true/false by mmc_numeric_response_handler */
RETVAL_NULL();
}
else {
/* populated with responses by mmc_numeric_response_handler and mmc_value_handler_multi */
array_init(return_value);
}
zend_hash_internal_pointer_reset_ex(Z_ARRVAL_P(keys), &pos);
while (zend_hash_get_current_data_ex(Z_ARRVAL_P(keys), (void **)&key, &pos) == SUCCESS) {
zend_hash_move_forward_ex(Z_ARRVAL_P(keys), &pos);
/* allocate request */
if (return_value_used) {
request = mmc_pool_request(
pool, MMC_PROTO_TCP, mmc_numeric_response_handler, return_value,
mmc_pool_failover_handler, NULL TSRMLS_CC);
}
else {
request = mmc_pool_request(
pool, MMC_PROTO_TCP, mmc_numeric_response_handler, NULL,
mmc_pool_failover_handler, NULL TSRMLS_CC);
}
request = mmc_pool_request(
pool, MMC_PROTO_TCP, mmc_numeric_response_handler, return_value,
mmc_pool_failover_handler, NULL TSRMLS_CC);
request->value_handler = mmc_value_handler_multi;
request->value_handler_param = value_handler_param;
@@ -605,7 +630,7 @@ static void php_mmc_numeric(INTERNAL_FUNCTION_PARAMETERS, int deleted, int inver
pool->protocol->delete(request, request->key, request->key_len, value);
}
else {
pool->protocol->mutate(request, *key, request->key, request->key_len, invert ? -value : value, defval, exptime);
pool->protocol->mutate(request, *key, request->key, request->key_len, invert ? -value : value, defval, defval_used, exptime);
}
/* schedule request */
@@ -618,16 +643,13 @@ static void php_mmc_numeric(INTERNAL_FUNCTION_PARAMETERS, int deleted, int inver
}
}
else {
if (deleted) {
RETVAL_NULL();
}
else {
RETVAL_FALSE;
}
/* changed to true/false by mmc_numeric_response_handler or set to a value
* by mmc_value_handler_single if incr/decr returns one */
RETVAL_NULL();
/* allocate request */
request = mmc_pool_request(pool, MMC_PROTO_TCP,
mmc_numeric_response_handler, return_value, mmc_pool_failover_handler, NULL TSRMLS_CC);
mmc_numeric_response_handler, return_value, mmc_pool_failover_handler, NULL TSRMLS_CC);
request->value_handler = mmc_value_handler_single;
request->value_handler_param = value_handler_param;
@@ -642,7 +664,7 @@ static void php_mmc_numeric(INTERNAL_FUNCTION_PARAMETERS, int deleted, int inver
pool->protocol->delete(request, request->key, request->key_len, value);
}
else {
pool->protocol->mutate(request, keys, request->key, request->key_len, invert ? -value : value, defval, exptime);
pool->protocol->mutate(request, keys, request->key, request->key_len, invert ? -value : value, defval, defval_used, exptime);
}
/* schedule request */
@@ -1530,7 +1552,6 @@ PHP_FUNCTION(memcache_get)
RETURN_FALSE;
}
ZVAL_FALSE(return_value);
value_handler_param[0] = return_value;
value_handler_param[1] = flags;
value_handler_param[2] = cas;
@@ -1538,12 +1559,14 @@ PHP_FUNCTION(memcache_get)
if (Z_TYPE_P(keys) == IS_ARRAY) {
zval **key;
HashPosition pos;
zend_hash_internal_pointer_reset_ex(Z_ARRVAL_P(keys), &pos);
/* return empty array if no keys found */
array_init(return_value);
failover_handler_param[0] = keys;
failover_handler_param[1] = value_handler_param;
zend_hash_internal_pointer_reset_ex(Z_ARRVAL_P(keys), &pos);
while (zend_hash_get_current_data_ex(Z_ARRVAL_P(keys), (void **)&key, &pos) == SUCCESS) {
zend_hash_move_forward_ex(Z_ARRVAL_P(keys), &pos);
@@ -1556,6 +1579,9 @@ PHP_FUNCTION(memcache_get)
}
else {
mmc_request_t *request;
/* return false if key isn't found */
ZVAL_FALSE(return_value);
/* allocate request */
request = mmc_pool_request_get(

View File

@@ -332,7 +332,7 @@ static void mmc_ascii_delete(mmc_request_t *request, const char *key, unsigned i
}
/* }}} */
static void mmc_ascii_mutate(mmc_request_t *request, zval *zkey, const char *key, unsigned int key_len, long value, long defval, unsigned int exptime) /* {{{ */
static void mmc_ascii_mutate(mmc_request_t *request, zval *zkey, const char *key, unsigned int key_len, long value, long defval, int defval_used, unsigned int exptime) /* {{{ */
{
request->parse = mmc_request_parse_mutate;

View File

@@ -493,7 +493,7 @@ static void mmc_binary_delete(mmc_request_t *request, const char *key, unsigned
}
/* }}} */
static void mmc_binary_mutate(mmc_request_t *request, zval *zkey, const char *key, unsigned int key_len, long value, long defval, unsigned int exptime) /* {{{ */
static void mmc_binary_mutate(mmc_request_t *request, zval *zkey, const char *key, unsigned int key_len, long value, long defval, int defval_used, unsigned int exptime) /* {{{ */
{
mmc_mutate_request_header_t header;
mmc_binary_request_t *req = (mmc_binary_request_t *)request;
@@ -511,7 +511,15 @@ static void mmc_binary_mutate(mmc_request_t *request, zval *zkey, const char *ke
}
header.defval = htonll(defval);
header.exptime = htonl(exptime);
if (defval_used) {
/* server inserts defval if key doesn't exist */
header.exptime = htonl(exptime);
}
else {
/* server replies with NOT_FOUND if exptime ~0 and key doesn't exist */
header.exptime = ~(uint32_t)0;
}
smart_str_appendl(&(request->sendbuf.value), (const char *)&header, sizeof(header));
smart_str_appendl(&(request->sendbuf.value), key, key_len);

View File

@@ -164,14 +164,15 @@ void mmc_request_free(mmc_request_t *request) /* {{{ */
static inline int mmc_request_send(mmc_t *mmc, mmc_request_t *request TSRMLS_DC) /* {{{ */
{
int count, bytes;
/* send next chunk of buffer */
int count = request->sendbuf.value.len - request->sendbuf.idx;
count = request->sendbuf.value.len - request->sendbuf.idx;
if (count > request->io->stream->chunk_size) {
count = request->io->stream->chunk_size;
}
int bytes = send(request->io->fd, request->sendbuf.value.c + request->sendbuf.idx, count, 0);
bytes = send(request->io->fd, request->sendbuf.value.c + request->sendbuf.idx, count, MSG_NOSIGNAL);
if (bytes >= 0) {
request->sendbuf.idx += bytes;
@@ -182,13 +183,17 @@ static inline int mmc_request_send(mmc_t *mmc, mmc_request_t *request TSRMLS_DC)
return MMC_REQUEST_MORE;
}
long err = php_socket_errno();
if (err == EAGAIN) {
return MMC_REQUEST_MORE;
else {
char *message, buf[1024];
long err = php_socket_errno();
if (err == EAGAIN) {
return MMC_REQUEST_MORE;
}
message = php_socket_strerror(err, buf, 1024);
return mmc_server_failure(mmc, request->io, message, err TSRMLS_CC);
}
return mmc_server_failure(mmc, request->io, "Write failed (socket unexpectedly closed)", err TSRMLS_CC);
}
/* }}} */
@@ -548,7 +553,9 @@ static void _mmc_server_disconnect(mmc_t *mmc, mmc_stream_t *io, int close_persi
else {
php_stream_close(io->stream);
}
io->stream = NULL;
io->fd = 0;
}
io->status = MMC_STATUS_DISCONNECTED;
@@ -645,7 +652,7 @@ int mmc_request_failure(mmc_t *mmc, mmc_stream_t *io, const char *message, unsig
checks for a valid server generated error message and calls mmc_server_failure() {{{ */
{
if (message_len) {
return mmc_server_failure(mmc, io, message, errnum TSRMLS_CC);;
return mmc_server_failure(mmc, io, message, errnum TSRMLS_CC);
}
return mmc_server_failure(mmc, io, "Malformed server response", errnum TSRMLS_CC);
@@ -699,6 +706,7 @@ static int mmc_server_connect(mmc_pool_t *pool, mmc_t *mmc, mmc_stream_t *io, in
if (php_stream_eof(io->stream)) {
php_stream_pclose(io->stream);
io->stream = NULL;
io->fd = 0;
break;
}
case PHP_STREAM_PERSISTENT_FAILURE:
@@ -742,23 +750,24 @@ static int mmc_server_connect(mmc_pool_t *pool, mmc_t *mmc, mmc_stream_t *io, in
io->status = MMC_STATUS_CONNECTED;
php_stream_auto_cleanup(io->stream);
php_stream_set_chunk_size(io->stream, io->chunk_size);
php_stream_set_option(io->stream, PHP_STREAM_OPTION_BLOCKING, 0, NULL);
php_stream_set_option(io->stream, PHP_STREAM_OPTION_READ_TIMEOUT, 0, &tv);
/* doing our own buffering increases performance */
php_stream_set_option(io->stream, PHP_STREAM_OPTION_READ_BUFFER, PHP_STREAM_BUFFER_NONE, NULL);
php_stream_set_option(io->stream, PHP_STREAM_OPTION_WRITE_BUFFER, PHP_STREAM_BUFFER_NONE, NULL);
/* php_stream buffering prevent us from detecting datagram boundaries when using udp */
if (udp) {
io->read = mmc_stream_read_buffered;
io->readline = mmc_stream_readline_buffered;
php_stream_set_option(io->stream, PHP_STREAM_OPTION_READ_BUFFER, PHP_STREAM_BUFFER_NONE, NULL);
}
else {
io->read = mmc_stream_read_wrapper;
io->readline = mmc_stream_readline_wrapper;
}
php_stream_set_option(io->stream, PHP_STREAM_OPTION_WRITE_BUFFER, PHP_STREAM_BUFFER_NONE, NULL);
php_stream_set_chunk_size(io->stream, io->chunk_size);
if (mmc->error != NULL) {
efree(mmc->error);
mmc->error = NULL;
@@ -1290,19 +1299,32 @@ static inline void mmc_pool_switch(mmc_pool_t *pool) {
mmc_queue_reset(pool->reading);
}
static void mmc_select_failure(mmc_pool_t *pool, mmc_t *mmc, mmc_request_t *request, int result TSRMLS_DC) /* {{{ */
static int mmc_select_failure(mmc_pool_t *pool, mmc_t *mmc, mmc_request_t *request, int result TSRMLS_DC) /* {{{ */
{
if (result == 0) {
/* timeout expired, non-responsive server */
if (mmc_server_failure(mmc, request->io, "Network timeout", 0 TSRMLS_CC) != MMC_REQUEST_RETRY) {
mmc_server_deactivate(pool, mmc TSRMLS_CC);
if (mmc_server_failure(mmc, request->io, "Network timeout", 0 TSRMLS_CC) == MMC_REQUEST_RETRY) {
return MMC_REQUEST_RETRY;
}
}
else {
/* hard failure, deactivate connection */
mmc_server_seterror(mmc, "Unknown select() error", errno);
mmc_server_deactivate(pool, mmc TSRMLS_CC);
char buf[1024];
const char *message;
long err = php_socket_errno();
if (err) {
message = php_socket_strerror(err, buf, 1024);
}
else {
message = "Unknown select() error";
}
mmc_server_seterror(mmc, message, errno);
}
/* hard failure, deactivate connection */
mmc_server_deactivate(pool, mmc TSRMLS_CC);
return MMC_REQUEST_FAILURE;
}
/* }}} */
@@ -1392,15 +1414,27 @@ void mmc_pool_select(mmc_pool_t *pool, long timeout TSRMLS_DC) /*
mmc = (mmc_t *)mmc_queue_item(sending, i);
if (!FD_ISSET(mmc->sendreq->io->fd, &(pool->wfds))) {
mmc_queue_remove(sending, mmc);
mmc_select_failure(pool, mmc, mmc->sendreq, result TSRMLS_CC);
mmc_queue_remove(reading, mmc);
i--;
if (mmc_select_failure(pool, mmc, mmc->sendreq, result TSRMLS_CC) == MMC_REQUEST_RETRY) {
/* allow request to try and send again */
mmc_select_retry(pool, mmc, mmc->sendreq TSRMLS_CC);
}
}
}
for (i=0; i < reading->len; i++) {
mmc = (mmc_t *)mmc_queue_item(reading, i);
if (!FD_ISSET(mmc->readreq->io->fd, &(pool->rfds))) {
mmc_queue_remove(sending, mmc);
mmc_queue_remove(reading, mmc);
mmc_select_failure(pool, mmc, mmc->readreq, result TSRMLS_CC);
i--;
if (mmc_select_failure(pool, mmc, mmc->readreq, result TSRMLS_CC) == MMC_REQUEST_RETRY) {
/* allow request to try and read again */
mmc_select_retry(pool, mmc, mmc->readreq TSRMLS_CC);
}
}
}
}
@@ -1408,7 +1442,6 @@ void mmc_pool_select(mmc_pool_t *pool, long timeout TSRMLS_DC) /*
pool->in_select = 1;
}
/* until stream buffer is empty */
for (i=0; i < sending->len; i++) {
mmc = mmc_queue_item(sending, i);
@@ -1419,7 +1452,11 @@ void mmc_pool_select(mmc_pool_t *pool, long timeout TSRMLS_DC) /*
if (FD_ISSET(mmc->sendreq->io->fd, &(pool->wfds))) {
fd = mmc->sendreq->io->fd;
/* clear bit for reentrancy reasons */
FD_CLR(fd, &(pool->wfds));
/* until stream buffer is empty */
do {
/* delegate to request send handler */
result = mmc_request_send(mmc, mmc->sendreq TSRMLS_CC);
@@ -1431,11 +1468,11 @@ void mmc_pool_select(mmc_pool_t *pool, long timeout TSRMLS_DC) /*
switch (result) {
case MMC_REQUEST_FAILURE:
/* clear readbit for this round */
FD_CLR(mmc->sendreq->io->fd, &(pool->rfds));
/* take server offline and failover requests */
mmc_server_deactivate(pool, mmc TSRMLS_CC);
/* server is failed, remove from read queue */
mmc_queue_remove(reading, mmc);
break;
case MMC_REQUEST_RETRY:
@@ -1461,9 +1498,6 @@ void mmc_pool_select(mmc_pool_t *pool, long timeout TSRMLS_DC) /*
/* add server to read queue once more */
mmc_queue_push(pool->sending, mmc);
}
/* clear bit for reentrancy reasons */
FD_CLR(fd, &(pool->wfds));
}
else {
/* add server to send queue once more */
@@ -1482,6 +1516,9 @@ void mmc_pool_select(mmc_pool_t *pool, long timeout TSRMLS_DC) /*
if (FD_ISSET(mmc->readreq->io->fd, &(pool->rfds))) {
fd = mmc->readreq->io->fd;
/* clear bit for reentrancy reasons */
FD_CLR(fd, &(pool->rfds));
/* fill read buffer if needed */
if (mmc->readreq->read != NULL) {
result = mmc->readreq->read(mmc, mmc->readreq TSRMLS_CC);
@@ -1512,6 +1549,7 @@ void mmc_pool_select(mmc_pool_t *pool, long timeout TSRMLS_DC) /*
}
}
/* until stream buffer is empty */
do {
/* delegate to request response handler */
result = mmc->readreq->parse(mmc, mmc->readreq TSRMLS_CC);
@@ -1578,9 +1616,6 @@ void mmc_pool_select(mmc_pool_t *pool, long timeout TSRMLS_DC) /*
/* add server to read queue once more */
mmc_queue_push(pool->reading, mmc);
}
/* clear bit for reentrancy reasons */
FD_CLR(fd, &(pool->rfds));
}
else {
/* add server to read queue once more */

View File

@@ -230,7 +230,7 @@ typedef int (*mmc_protocol_store)(
mmc_pool_t *pool, mmc_request_t *request, int op, const char *key, unsigned int key_len,
unsigned int flags, unsigned int exptime, unsigned long cas, zval *value TSRMLS_DC);
typedef void (*mmc_protocol_delete)(mmc_request_t *request, const char *key, unsigned int key_len, unsigned int exptime);
typedef void (*mmc_protocol_mutate)(mmc_request_t *request, zval *zkey, const char *key, unsigned int key_len, long value, long defval, unsigned int exptime);
typedef void (*mmc_protocol_mutate)(mmc_request_t *request, zval *zkey, const char *key, unsigned int key_len, long value, long defval, int defval_used, unsigned int exptime);
typedef void (*mmc_protocol_flush)(mmc_request_t *request, unsigned int exptime);
typedef void (*mmc_protocol_stats)(mmc_request_t *request, const char *type, long slabid, long limit);

View File

@@ -36,8 +36,9 @@ http://pear.php.net/dtd/package-2.0.xsd">
</stability>
<license uri="http://www.php.net/license">PHP License</license>
<notes>
Improved performance of consistent hash strategy
Fixed PECL request #13758 (Failed to extract 'connection' variable from object)
- Improved performance of consistent hash strategy
- Fixed PECL bug #14642 (3.0.x breaks BC with 2.2.x)
- Fixed PECL request #13758 (Failed to extract 'connection' variable from object)
</notes>
<contents>
<dir name="/">

View File

@@ -5,6 +5,8 @@
error_reporting(E_ALL);
ini_set('memcache.hash_strategy', 'consistent');
//ini_set('memcache.protocol', 'binary');
$threshold = 0;
$count = 50; // Keys per interation (multi-key operations do $count keys at a time)
$reps = 1000; // Number of iterations
@@ -17,19 +19,19 @@ $hosts = array(
$pools = array();
$tests1 = array(
array('test_get_single', 'Single-Get'),
array('test_get_multi', 'Multi-Get'),
array('test_get_single_obj', 'Get-Object'),
array('test_get_multi_obj', 'MulGet-Object'),
);
$tests2 = array(
array('test_set_single', 'Single-Set'),
array('test_set_single_obj', 'Set-Object'),
array('test_incr_single', 'Single-Incr'),
array('test_delete_single', 'Single-Del'),
);
$tests2 = array(
array('test_get_single', 'Single-Get'),
array('test_get_multi', 'Multi-Get'),
array('test_get_single_obj', 'Get-Object'),
array('test_get_multi_obj', 'MulGet-Object'),
);
$tests3 = array(
array('test_set_multi', 'Multi-Set'),
array('test_set_multi_obj', 'MulSet-Object'),
@@ -83,11 +85,13 @@ function run_tests($pools, $tests) {
// Create pools to run all tests against
$memcache1 = new Memcache();
$memcache1->connect($hosts[0][0], $hosts[0][1]);
$memcache1->setCompressThreshold($threshold);
$pools[] = array($memcache1, 'TCP (1 server)');
if (class_exists('MemcachePool')) {
$memcache2 = new MemcachePool();
$memcache2->connect($hosts[0][0], $hosts[0][1], $hosts[0][2], false);
$memcache2->setCompressThreshold($threshold);
$pools[] = array($memcache2, 'UDP (1 server)');
}
@@ -95,12 +99,14 @@ if (count($hosts) > 1) {
$memcache3 = new Memcache();
foreach ($hosts as $h)
$memcache3->connect($h[0], $h[1]);
$memcache3->setCompressThreshold($threshold);
$pools[] = array($memcache3, sprintf('TCP (%d servers)', count($hosts)));
if (class_exists('MemcachePool')) {
$memcache4 = new MemcachePool();
foreach ($hosts as $h)
$memcache4->connect($h[0], $h[1], $h[2], false);
$memcache4->setCompressThreshold($threshold);
$pools[] = array($memcache4, sprintf('UDP (%d servers)', count($hosts)));
}
}
@@ -115,19 +121,21 @@ $key2 = 'test_key_int';
$key3 = 'test_key_obj';
for ($i=0; $i<$count; $i++) {
$values[$key.$i] = $key.'_value_'.$i;
$values[$key.$i] = $key.'_value_'.$i.str_repeat('a', $i*1000);
$ints[$key2.$i] = $i;
$objects[$key3.$i] = new TestClass(new TestClass(new TestClass()));
$objects[$key3.$i] = new TestClass(new TestClass(new TestClass(str_repeat('a', $i*100))));
}
print "Measures are in keys-per-second (higher is better) with number of seconds\nspent in test within parentheses (lower is better).\n\n";
// Configuration
printf("memcache.hash_strategy: %s\n", ini_get('memcache.hash_strategy'));
printf("memcache.chunk_size: %u\n", ini_get('memcache.chunk_size'));
printf("servers: %d\n", count($hosts));
printf("iterations: %d\n", $reps);
printf("keys per iteration: %d\n", $count);
printf("memcache.hash_strategy: %s\n", ini_get('memcache.hash_strategy'));
printf("memcache.chunk_size: %u\n", ini_get('memcache.chunk_size'));
printf("memcache.protocol: %s\n", ini_get('memcache.protocol'));
printf("memcache.compress_threshold: %s\n", $threshold);
printf("servers: %d\n", count($hosts));
printf("iterations: %d\n", $reps);
printf("keys per iteration: %d\n", $count);
print "\n";
$ts = time();
@@ -146,7 +154,7 @@ printf("total time: %d minutes, %d seconds\n", floor(($ts2 - $ts)/60), ($ts2 - $
// Tests
class TestClass {
function __construct($obj = null) {
$this->v1 = str_repeat('abc', 250);
$this->v1 = str_repeat('abc', 25);
$this->v2 = 123;
$this->v3 = 123.123;
$this->v4 = array('abc', 123);

View File

@@ -20,7 +20,10 @@ var_dump($result);
$result = memcache_get($memcache, 'test_key');
var_dump($result);
$result = memcache_get($memcache, Array('test_key', 'test_key1'));
$result = memcache_get($memcache, array('test_key', 'test_key1'));
var_dump($result);
$result = memcache_get($memcache, array('unset_test_key', 'unset_test_key1'));
var_dump($result);
?>
@@ -64,3 +67,5 @@ array(2) {
}
}
}
array(0) {
}

View File

@@ -117,7 +117,7 @@ var_dump($result);
$keys = array_keys($values);
$result = $memcache->get($keys);
var_dump($keys);
var_dump($result);
var_dump(array_values($result));
?>
--EXPECTF--
@@ -192,8 +192,8 @@ array(2) {
string(9) "test test"
}
array(2) {
["_"]=>
[0]=>
string(5) "value"
["test_test"]=>
[1]=>
string(6) "value2"
}

View File

@@ -11,10 +11,10 @@ $var = new stdClass;
$var->plain_attribute = 'value';
$var->array_attribute = Array('test1', 'test2');
$memcache->get('test_key');
$result = $memcache->get('test_key');
var_dump($result);
$result = $memcache->get(array('unset_test_key', 'unset_test_key1'));
var_dump($result);
?>
@@ -30,3 +30,5 @@ object(stdClass)%s2) {
string(5) "test2"
}
}
array(0) {
}

View File

@@ -35,12 +35,6 @@ $largeval = str_repeat('a', 1024*2048);
$_SESSION['_test_key']= $largeval;
session_write_close();
ini_set('memcache.compress_threshold', 0);
session_start();
$largeval = str_repeat('a', 1024*2048);
$_SESSION['_test_key']= $largeval;
session_write_close();
var_dump($result1);
var_dump($id);
var_dump($result2);
@@ -51,10 +45,6 @@ var_dump($result6);
?>
--EXPECTF--
%s: SERVER_ERROR object too large for cache
(3) in %s
Warning: session_write_close(): Failed to write session data (memcache). %s
bool(true)
string(%d) "%s"
bool(false)

View File

@@ -28,6 +28,12 @@ var_dump($result);
$result = memcache_decrement($memcache, array($balanceKey1, $balanceKey2), 1);
var_dump($result);
$result = $memcache->increment(array());
var_dump($result);
$result = $memcache->increment(array('unset_test_key', 'unset_test_key1'));
var_dump($result);
?>
--EXPECTF--
array(2) {
@@ -56,3 +62,11 @@ array(2) {
["%s"]=>
int(2)
}
array(0) {
}
array(2) {
["%s"]=>
bool(false)
["%s"]=>
bool(false)
}

View File

@@ -52,4 +52,5 @@ bool(false)
bool(true)
bool(true)
bool(false)
array(0) {
}