PHPでmemcache関数でセットして、取り出すときはtelnet接続するという奇特なことをしている時にはまったのでメモ。
こんなことする人他に居るんだろうか・・・
現象
<?php memcache_set($memcache_obj, "hoge^A6", "huga", 0 ,30); ?>
としてセット。^Aは制御文字。
<?php $fp = fsockopen($host, $port, $errno, $errstr, $timeout); ?>
で接続。
<?php fwrite($fp, "get hoge^A6\r\n"); ?>
で取得しようとすると「hoge^A6」というkeyにデータは存在しないことになっていて、ENDだけが帰ってくる。
実際にtelnetで接続して同様の記述をしても同じ。そんなkeyのvalueはねぇぜといわれる。
制御文字とかは弾かれるのかな?とか思って消してみても駄目。
ただしmemcache_getでは取得できるので、格納はされている。
どうもsetするときに何らかの処理をされているっぽいのでソースを見てみる
wget http://pecl.php.net/get/memcache-2.2.1.tgz tar xvzf memcache-2.2.1.tgz cd memcache-2.2.1 vi memcache.c
発見
memcache.c 528行目あたり
516 int mmc_prepare_key_ex(const char *key, unsigned int key_len, char *result, unsigned int *result_len TSRMLS_DC) /* {{{ */ 517 { 518 unsigned int i; 519 if (key_len == 0) { 520 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Key cannot be empty"); 521 return MMC_REQUEST_FAILURE; 522 } 523 524 *result_len = key_len < MMC_KEY_MAX_SIZE ? key_len : MMC_KEY_MAX_SIZE; 525 result[*result_len] = '\0'; 526 527 for (i=0; i<*result_len; i++) { 528 result[i] = key[i] > ' ' ? key[i] : '_'; 529 } 530 531 return MMC_OK; 532 }
アンダースコア[_]に置き換えられてる・・・orz
つまり直にたたく場合はkeyは"hoge_6"となる・・・
なので変な文字(0x1f以下)を使うとアンダースコアに置き換えられるので、まったく同じ文字列でtelnetでgetしようとしても駄目なんですねー。書いとけちくしょう。