2009-07-13
■[MySQL]次回勉強会は「MySQLハッキングの手引き」
宣伝です。
次回のオープンソーステクノロジー勉強会は松信嘉範さんをお迎えして
「MySQLハッキングの手引き」というテーマでお話を伺います。
日本MySQLユーザー会 松信 嘉範 (MATSUNOBU Yoshinori)
MySQLはオープンソースなので、必要に応じてMySQLのソースコードを改変して、自分好みの機能を追加することができます。またストレージエンジンなどプラグイン形式になっている部分もあり、場合によってはMySQL本体を改変することなくお望みの機能を用意することもできます。このセッションでは、いくつかの例を挙げながら、具体的なMySQLハッキングのデモをお見せします。またMySQL本家へのコントリビューションの方法も紹介します。
第18回 オープンソーステクノロジー勉強会 - GREE Labs
みなさま、よろしくおねがいします。
2009-07-02
■[PHP]PHPでlibdrizzleを使うときのメモ
http://pecl.php.net/package/drizzle/
<?php $drizzle = new drizzle(); $db = 'information_schema'; $query = 'SELECT * FROM character_sets'; $host = 'localhost'; $port = '3306'; $user = 'root'; $password = NULL; $options = DRIZZLE_CON_MYSQL; $concurrent_queries = 5; for ($i=0; $i<$concurrent_queries; $i++) { $con = $drizzle->addTcp($host, $port, $user, $password, $db, $options); $drizzle->queryAdd($con, $query, 0, $i); } while ($q = $drizzle->run()) { $data = $q->data(); $result = $q->result(); while (($column = $result->columnNext()) != NULL) { print $column->name() . ':'; } print "\n"; while (($row = $result->rowNext()) != NULL) { print "$data " . implode(':', $row) . "\n"; } print "\n"; } if ($drizzle->returnCode() != DRIZZLE_RETURN_OK) { exit(0); }
とりあえずあとで。
2008-12-10
■[memcached] memcachedのdecrementコマンドでバイトサイズがresizeされないのは仕様でした
memcachedにはincrementとdecrementコマンドというのがあって、
incr <key> <value>
もしくは
decr <key> <value>
とやると<key>に入ってる値から<value>を足したり、引いたりします。
increment
memcachedの1.2.6を使って、
incrementで9から10に変更し、getのレスポンスを見るとバイト数も1から2に変更されます。
VALUE <key> <flags> <bytes>
<data>
です。
set key 0 0 1 9 STORED get key VALUE key 0 1 9 END incr key 1 10 get key VALUE key 0 2 10 END
decrement
同様にmemcachedの1.2.6を使って、
decrementで10から9に変えてみると、getしたときのサイズが2のままです。
set key 0 0 2 10 STORED get key VALUE key 0 2 10 END decr key 1 9 get key VALUE key 0 2 9 END
偉いひとに聞いたら、これは仕様らしくて実際にmemcachedプロトコルのドキュメントに書いてありました。
Note also that decrementing a number such that it loses length isn't
guaranteed to decrement its returned length. The number MAY be
space-padded at the end, but this is purely an implementation
optimization, so you also shouldn't rely on that.
http://code.sixapart.com/svn/memcached/trunk/server/doc/protocol.txt
memcachedの実装をみてみると、
memcached-1.2.6/memcached.c
1562 char *do_add_delta(conn *c, item *it, const bool incr, const int64_t delta, char *buf) { 略 1584 sprintf(buf, "%llu", value); 1585 res = strlen(buf); 1586 if (res + 2 > it->nbytes) { /* need to realloc */ 1587 item *new_it; 1588 new_it = do_item_alloc(ITEM_key(it), it->nkey, atoi(ITEM_suffix(it) + 1), it->exptime, res + 2 ); 1589 if (new_it == 0) { 1590 return "SERVER_ERROR out of memory in incr/decr"; 1591 } 1592 memcpy(ITEM_data(new_it), buf, res); 1593 memcpy(ITEM_data(new_it) + res, "\r\n", 2); 1594 do_item_replace(it, new_it); 1595 do_item_remove(new_it); /* release our reference */ 1596 } else { /* replace in-place */ 1597 memcpy(ITEM_data(it), buf, res); 1598 memset(ITEM_data(it) + res, ' ', it->nbytes - res - 2); 1599 }
1586行目でincrementもしくはdecrement後の値のサイズがもとのバイト数よりも大きい場合は、バイト数の置き換えも伴うデータの置き換えが行われてます、
そうでない場合、同じか小さくなった場合は変更後の値のみ置き換わり(1597行目)、小さくなった場合の余りのバイトにはスペースがパディングされてます(1598行目)。
きっとこのぐらいの変更で解消されそう。
diff --git a/memcached.c b/memcached.c index 3b7a187..15b32b0 100644 --- a/memcached.c +++ b/memcached.c @@ -1583,7 +1583,7 @@ char *do_add_delta(conn *c, item *it, const bool incr, const int64_t delta, char } sprintf(buf, "%llu", value); res = strlen(buf); - if (res + 2 > it->nbytes) { /* need to realloc */ + if (res + 2 != it->nbytes) { /* need to realloc */ item *new_it; new_it = do_item_alloc(ITEM_key(it), it->nkey, atoi(ITEM_suffix(it) + 1), it->exptime, res + 2 ); if (new_it == 0) {
2008-12-05
■[PHP] PHP 5.3 でlambda!
5.3 alpha1から使えるclosureの機能をつかってみたよ!
php-5.3.0alpha3/Zend/tests$ ls closure_* closure_001.phpt closure_006.phpt closure_011.phpt closure_016.phpt closure_021.phpt closure_026.phpt closure_031.phpt closure_002.phpt closure_007.phpt closure_012.phpt closure_017.phpt closure_022.phpt closure_027.phpt closure_032.phpt closure_003.phpt closure_008.phpt closure_013.phpt closure_018.phpt closure_023.phpt closure_028.phpt closure_004.phpt closure_009.phpt closure_014.phpt closure_019.phpt closure_024.phpt closure_029.phpt closure_005.phpt closure_010.phpt closure_015.phpt closure_020.phpt closure_025.phpt closure_030.phpt
- closure_003.phpt
--TEST-- Closure 003: Lambda with lexical variables (local scope) --FILE-- <?php function run () { $x = 4; $lambda1 = function () use ($x) { echo "$x\n"; }; $lambda2 = function () use (&$x) { echo "$x\n"; }; $lambda1(); $lambda2(); $x++; $lambda1(); $lambda2(); } run(); echo "Done\n"; ?> --EXPECT-- 4 4 4 5 Done
$ php closure_003.phpt --TEST-- Closure 003: Lambda with lexical variables (local scope) --FILE-- 4 4 4 5 Done --EXPECT-- 4 4 4 5 Done
■[PHP] PHP 5.3 alpha3 released!
PHP 5.3 alpha3 released!したのを
PHP5.3.0α3が来る - Do You PHP はてなを見て知りました!
$ php -v PHP 5.3.0alpha3 (cli) (built: Dec 5 2008 16:06:48) Copyright (c) 1997-2008 The PHP Group Zend Engine v2.3.0, Copyright (c) 1998-2008 Zend Technologies
$ php -r 'namespace A::B;' Parse error: syntax error, unexpected T_PAAMAYIM_NEKUDOTAYIM, expecting T_NS_SEPARATOR or ';' or '{' in Command line code on line 1
$ php -r 'namespace A\B; var_dump(__NAMESPACE__);' string(3) "A\B"
2008-12-02
■[PHP]PHPのarray_mergeと+演算子が気になったから
array_merge と + は key がぶつかると、value は片方残る。array_merge は後勝ち。+ は早いもの勝ち。
PHP 配列の + 演算子が便利な件 - yoyaのメモ
が気になったので。
+演算子の処理はphp-5.2.6/Zend/zend_operators.cのadd_function()にあって、
ZEND_API int add_function(zval *result, zval *op1, zval *op2 TSRMLS_DC) { zval op1_copy, op2_copy; if (op1->type == IS_ARRAY && op2->type == IS_ARRAY) { zval *tmp; if ((result == op1) && (result == op2)) { /* $a += $a */ return SUCCESS; } if (result != op1) { *result = *op1; zval_copy_ctor(result); } zend_hash_merge(result->value.ht, op2->value.ht, (void (*)(void *pData)) zval_add_ref, (void *) &tmp, sizeof(zval *), 0); return SUCCESS; }
両方ともarrayだとzend_hash_mergeがよばれます。
- php-5.2.6/Zend/zend_hash.c
801 ZEND_API void _zend_hash_merge(HashTable *target, HashTable *source, copy_ctor_func_t pCopyConstructor, void *tmp, uint size, int overwrite ZEND_FILE_LINE_DC) 805 int mode = (overwrite?HASH_UPDATE:HASH_ADD); 813 if (_zend_hash_quick_add_or_update(target, p->arKey, p->nKeyLength, p->h, p->pData, size, &t, mode ZEND_FILE_LINE_RELAY_CC)==SUCCESS && pCopyConstructor) {
zend_hash_merge()をみると、
int overwriteは0が来てるので,805行目のmodeはHASH_ADDになります。
で、このmodeが813行目の_zend_hash_quick_add_or_updateの引数としてつかわれます。
- php-5.2.6/Zend/zend_hash.c
270 ZEND_API int _zend_hash_quick_add_or_update(HashTable *ht, char *arKey, uint nKeyLength, ulong h, void *pData, uint nDataSize, v oid **pDest, int flag ZEND_FILE_LINE_DC) 285 if ((p->h == h) && (p->nKeyLength == nKeyLength)) { 286 if (!memcmp(p->arKey, arKey, nKeyLength)) { 287 if (flag & HASH_ADD) { 288 return FAILURE; 289 }
_zend_hash_quick_add_or_updateをみると、さきほどのmodeはflagという変数名でつかわれてて中身はHASH_ADDです。
286行目以降にmemcmpで比較してkeyが同じ場合の処理が書かれてるんですが、
そのまえに287行目のif文でHASH_ADDだと処理を中断してます。
なので、値の上書きはおこなわれません
つぎにarray_mergeは、
- php-5.2.6/ext/standard/array.c
2293 PHPAPI int php_array_merge(HashTable *dest, HashTable *src, int recursive TSRMLS_DC) /* {{{ */ 2342 zend_hash_update(dest, string_key, string_key_len, 2343 src_entry, sizeof(zval *), NULL);
zend_hash_updateがよばれて配列のマージがおこなわれます。
zend_hash_updateはphp-5.2.6/Zend/zend_hash.hにかかれてて、
102 #define zend_hash_update(ht, arKey, nKeyLength, pData, nDataSize, pDest) \ 103 _zend_hash_add_or_update(ht, arKey, nKeyLength, pData, nDataSize, pDest, HASH_UPDATE ZEND_FILE_LINE_CC) 104 #define zend_hash_add(ht, arKey, nKeyLength, pData, nDataSize, pDest) \ 105 _zend_hash_add_or_update(ht, arKey, nKeyLength, pData, nDataSize, pDest, HASH_ADD ZEND_FILE_LINE_CC)
大事なのは7番目の引数でHASH_UPDATEが入ってるところです。
HASH_UPDATEだと、さっきのzend_hash.cの287行目の条件にマッチしないので,
そのまま処理が続いて値の上書きがおこなわれてます。
_zend_hash_add_or_update()と_zend_hash_quick_add_or_update()の違いってkeyがemptyだったときの処理のちがいくらいでした。
