Scalar data types (int, bool, double) are preserved by get/set using the flag field

This commit is contained in:
Mikael Johansson
2009-01-13 16:26:44 +00:00
parent 3d31fc2308
commit 91bd682fa7
9 changed files with 122 additions and 36 deletions

View File

@@ -315,28 +315,35 @@ static int mmc_uncompress(const char *data, unsigned long data_len, char **resul
int mmc_pack_value(mmc_pool_t *pool, mmc_buffer_t *buffer, zval *value, unsigned int *flags TSRMLS_DC) /*
does serialization and compression to pack a zval into the buffer {{{ */
{
if (*flags & 0xffff & ~MMC_COMPRESSED) {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "The lowest two bytes of the flags array is reserved for pecl/memcache internal use");
return MMC_REQUEST_FAILURE;
}
*flags &= ~MMC_SERIALIZED;
switch (Z_TYPE_P(value)) {
case IS_STRING:
*flags &= ~MMC_SERIALIZED;
*flags |= MMC_TYPE_STRING;
mmc_compress(pool, buffer, Z_STRVAL_P(value), Z_STRLEN_P(value), flags, 0 TSRMLS_CC);
break;
case IS_LONG:
case IS_DOUBLE:
case IS_BOOL: {
zval value_copy;
*flags &= ~MMC_SERIALIZED;
/* FIXME: we should be using 'Z' instead of this, but unfortunately it's PHP5-only */
value_copy = *value;
zval_copy_ctor(&value_copy);
convert_to_string(&value_copy);
mmc_compress(pool, buffer, Z_STRVAL(value_copy), Z_STRLEN(value_copy), flags, 0 TSRMLS_CC);
zval_dtor(&value_copy);
*flags |= MMC_TYPE_LONG;
smart_str_append_long(&(buffer->value), Z_LVAL_P(value));
break;
case IS_DOUBLE: {
char buf[256];
int len = snprintf(buf, 256, "%.14g", Z_DVAL_P(value));
*flags |= MMC_TYPE_DOUBLE;
smart_str_appendl(&(buffer->value), buf, len);
break;
}
case IS_BOOL:
*flags |= MMC_TYPE_BOOL;
smart_str_appendc(&(buffer->value), Z_BVAL_P(value) ? '1' : '0');
break;
default: {
php_serialize_data_t value_hash;
@@ -446,13 +453,37 @@ int mmc_unpack_value(
return value_handler(key_tmp, key_len, object, flags, cas, value_handler_param TSRMLS_CC);
}
else {
data[data_len] = '\0';
ZVAL_STRINGL(&value, data, data_len, 0);
if (!(flags & MMC_COMPRESSED)) {
mmc_buffer_release(buffer);
}
switch (flags & 0x0f00) {
case MMC_TYPE_LONG: {
long val;
data[data_len] = '\0';
val = strtol(data, NULL, 10);
ZVAL_LONG(&value, val);
break;
}
case MMC_TYPE_DOUBLE: {
double val = 0;
data[data_len] = '\0';
sscanf(data, "%lg", &val);
ZVAL_DOUBLE(&value, val);
break;
}
case MMC_TYPE_BOOL:
ZVAL_BOOL(&value, data_len == 1 && data[0] == '1');
break;
default:
data[data_len] = '\0';
ZVAL_STRINGL(&value, data, data_len, 0);
if (!(flags & MMC_COMPRESSED)) {
/* release buffer because it's now owned by the zval */
mmc_buffer_release(buffer);
}
}
/* delegate to value handler */
return request->value_handler(key, key_len, &value, flags, cas, request->value_handler_param TSRMLS_CC);
}

View File

@@ -41,8 +41,20 @@
#define ZSTR_VAL(v) (v).s
#endif
#define MMC_SERIALIZED 1
#define MMC_COMPRESSED 2
/* use lowest byte for flags */
#define MMC_SERIALIZED 0x0001
#define MMC_COMPRESSED 0x0002
/* use second lowest byte to indicate data type */
#define MMC_TYPE_STRING 0x0000
#define MMC_TYPE_BOOL 0x0100
/*#define MMC_TYPE_INT 0x0200*/
#define MMC_TYPE_LONG 0x0300
/*#define MMC_TYPE_DATE 0x0400*/
/*#define MMC_TYPE_BYTE 0x0500*/
/*#define MMC_TYPE_FLOAT 0x0600*/
#define MMC_TYPE_DOUBLE 0x0700
/*#define MMC_TYPE_BLOB 0x0800*/
#define MMC_BUFFER_SIZE 4096
#define MMC_MAX_UDP_LEN 1400

View File

@@ -37,10 +37,13 @@ http://pear.php.net/dtd/package-2.0.xsd">
<license uri="http://www.php.net/license">PHP License</license>
<notes>
- Enabled compression by default for values larger than 20kb
- Scalar data types (int, bool, double) are preserved by get/set
- Reserved the lowest 2 bytes of the flags for internal use
- Fixed PECL bug #14157 (Segmentation fault with errorcallback handler)
- Fixed PECL bug #15342 (memcache keys whitespaces replace issue)
- Fixed PECL bug #15447 (Persistent Connections Cause Segfaults if One Server Drops)
- Fixed PECL bug #15529 (memcache object loses port information)
- Fixed PECL bug #14730 (Types lost during get/set)
- Fixed PECL request #14801 (Session handler and large sessions)
- Added REPORT_ERRORS to php stream open
- New INI directive

View File

@@ -21,4 +21,4 @@ var_dump($result3);
--EXPECT--
int(6)
int(5)
string(1) "5"
int(5)

View File

@@ -21,4 +21,4 @@ var_dump($result3);
--EXPECT--
int(6)
int(5)
string(1) "5"
int(5)

View File

@@ -49,6 +49,6 @@ bool(true)
int(11)
int(21)
string(0) ""
string(2) "21"
string(2) "11"
int(21)
int(11)
string(0) ""

View File

@@ -36,8 +36,8 @@ array(2) {
["%s"]=>
int(3)
}
string(1) "2"
string(1) "3"
int(2)
int(3)
array(2) {
["%s"]=>
int(1)

View File

@@ -7,8 +7,8 @@ memcache->get() with flags
include 'connect.inc';
$flag1 = 0x100;
$flag2 = 0x200;
$flag1 = 0x10000;
$flag2 = 0x20000;
$memcache->set('test_key1', 'test1', $flag1);
$memcache->set('test_key2', 'test2', $flag2);
@@ -57,13 +57,13 @@ var_dump($result5);
?>
--EXPECT--
int(256)
int(65536)
string(5) "test1"
array(2) {
["test_key1"]=>
int(256)
int(65536)
["test_key2"]=>
int(512)
int(131072)
}
array(2) {
["test_key1"]=>
@@ -72,13 +72,13 @@ array(2) {
string(5) "test2"
}
string(5) "test1"
int(256)
int(65536)
string(5) "test1"
array(2) {
["test_key1"]=>
int(256)
int(65536)
["test_key2"]=>
int(512)
int(131072)
}
array(2) {
["test_key1"]=>

40
tests/055.phpt Normal file
View File

@@ -0,0 +1,40 @@
--TEST--
memcache->set()/get() datatype preservation
--SKIPIF--
<?php include 'connect.inc'; ?>
--FILE--
<?php
include 'connect.inc';
$memcache->set('test_key', '1');
$result = $memcache->get('test_key');
var_dump($result);
$memcache->set('test_key', 1);
$result = $memcache->get('test_key');
var_dump($result);
$memcache->set('test_key', true);
$result = $memcache->get('test_key');
var_dump($result);
$memcache->set('test_key', false);
$result = $memcache->get('test_key');
var_dump($result);
$memcache->set('test_key', 1.1);
$result = $memcache->get('test_key');
var_dump($result);
$memcache->set('test_key', '1', 0x10);
?>
--EXPECTF--
string(1) "1"
int(1)
bool(true)
bool(false)
float(1.1)
Warning: MemcachePool::set(): The lowest two bytes of the flags %s