diff --git a/lqdetect.c b/lqdetect.c index 9083759e..137114f7 100644 --- a/lqdetect.c +++ b/lqdetect.c @@ -80,9 +80,10 @@ struct lq_detect_global { }; struct lq_detect_global lqdetect; -static bool do_command_dupcheck(char *key, enum lq_detect_command cmd, struct lq_detect_argument *arg) +static bool is_command_duplicated(char *key, int keylen, enum lq_detect_command cmd, struct lq_detect_argument *arg) { int count = lqdetect.buffer[cmd].nsaved; + struct lq_detect_buffer *buf = &lqdetect.buffer[cmd]; switch (cmd) { case LQCMD_LOP_INSERT: @@ -102,15 +103,10 @@ static bool do_command_dupcheck(char *key, enum lq_detect_command cmd, struct lq case LQCMD_MOP_GET: case LQCMD_SOP_GET: for (int ii = 0; ii < count; ii++) { - if (arg->count == 0) { - uint32_t offset = lqdetect.buffer[cmd].keypos[ii]; - uint32_t cmplen = lqdetect.buffer[cmd].keylen[ii]; - if (cmplen == strlen(key) && - memcmp(lqdetect.buffer[cmd].data+offset, key, cmplen) == 0) { - return true; - } - } else { - if (strcmp(lqdetect.arg[cmd][ii].query, arg->query) == 0) { + if (strcmp(lqdetect.arg[cmd][ii].query, arg->query) == 0) { + if (arg->count > 0) return true; + if (buf->keylen[ii] == keylen && + memcmp(buf->data + buf->keypos[ii], key, keylen) == 0) { return true; } } @@ -131,11 +127,15 @@ static void do_lqdetect_write(char *client_ip, char *key, char *bufptr = buffer->data + buffer->offset; uint32_t nwrite, length, keylen = strlen(key); char keybuf[251]; + char *keyptr = key; if (keylen > 250) { /* long key string */ keylen = snprintf(keybuf, sizeof(keybuf), "%.*s...%.*s", 124, key, 123, (key+(keylen - 123))); - } else { /* short key string */ - keylen = snprintf(keybuf, sizeof(keybuf), "%s", key); + keyptr = keybuf; + } + + if (is_command_duplicated(keyptr, keylen, cmd, arg) == true) { + return; } gettimeofday(&val, NULL); @@ -152,7 +152,7 @@ static void do_lqdetect_write(char *client_ip, char *key, length -= nwrite; bufptr += nwrite; - snprintf(bufptr, length, "%s %s\n", keybuf, arg->query); + snprintf(bufptr, length, "%s %s\n", keyptr, arg->query); nwrite += strlen(bufptr); buffer->offset += nwrite; lqdetect.arg[cmd][nsaved] = *arg; @@ -175,8 +175,7 @@ static void do_lqdetect_save_cmd(char *client_ip, char* key, pthread_mutex_lock(&lqdetect.lock); if (lqdetect_in_use) { lqdetect.buffer[cmd].ntotal++; - if (lqdetect.buffer[cmd].nsaved < LQ_SAVE_CNT && - do_command_dupcheck(key, cmd, arg) == false) { + if (lqdetect.buffer[cmd].nsaved < LQ_SAVE_CNT) { /* write to buffer */ do_lqdetect_write(client_ip, key, cmd, arg); /* internal stop */ diff --git a/t/long_query_detect_issue.t b/t/long_query_detect_issue.t index 1a0279ca..7edbf035 100644 --- a/t/long_query_detect_issue.t +++ b/t/long_query_detect_issue.t @@ -1,7 +1,7 @@ #!/usr/bin/perl use strict; -use Test::More tests => 107; +use Test::More tests => 125; use FindBin qw($Bin); use lib "$Bin/lib"; use MemcachedTest; @@ -102,6 +102,63 @@ sub do_btree_efilter { mem_cmd_is($sock, $cmd, "", $rst); } +sub do_sop_prepare { + my $long_key = "A" x 251; + + mem_cmd_is($sock, "sop insert skey1 5 create 0 0 5", "datum", "CREATED_STORED"); + mem_cmd_is($sock, "sop insert skey2 5 create 0 0 5", "datum", "CREATED_STORED"); + mem_cmd_is($sock, "sop insert $long_key 5 create 0 0 5", "datum", "CREATED_STORED"); +} + +sub do_sop_get { + my $idx; + my $long_key = "A" x 251; + + $rst = "VALUE 0 1\n" + . "5 datum\n" + . "END"; + for ($idx = 1; $idx < 3; $idx += 1) { + mem_cmd_is($sock, "sop get skey1 $idx", "", $rst); + } + mem_cmd_is($sock, "sop get skey1 0", "", $rst); + for ($idx = 0; $idx < 3; $idx += 1) { + mem_cmd_is($sock, "sop get skey2 $idx", "", $rst); + } + $rst = "VALUE 0 1\n" + . "5 datum\n" + . "END"; + mem_cmd_is($sock, "sop get $long_key 0", "", $rst); + mem_cmd_is($sock, "sop get $long_key 0", "", $rst); +} + +sub do_lqdetect_show { + my $idx; + my $substring; + my $line; + my $long_key = "A" x 124 + "..." + "A" x 123; + + print $sock "lqdetect show\r\n"; + $line = scalar <$sock>; + print $line; + for ($idx = 1; $idx < 3; $idx += 1) { + $line = scalar <$sock>; + $substring = "sop get skey1 $idx"; + like($line, qr/$substring/, "lqdetect show $substring"); + } + $line = scalar <$sock>; + $substring = "sop get skey1 0"; + like($line, qr/$substring/, "lqdetect show $substring"); + $line = scalar <$sock>; + $substring = "sop get skey2 0"; + like($line, qr/$substring/, "lqdetect show $substring"); + $line = scalar <$sock>; + $substring = "sop get "+ $long_key + " 0"; + like($line, qr/$substring/, "lqdetect show $substring"); + $line = scalar <$sock>; + $substring = "mop delete : 0"; + like($line, qr/$substring/, "lqdetect show $substring"); +} + # do test my $key = "AA"; my $line; @@ -116,5 +173,16 @@ $line = scalar <$sock>; $line = scalar <$sock>; mem_cmd_is($sock, "delete $key", "", "DELETED"); +$rst = "long query detection started"; +print $sock "lqdetect start 1\r\n"; +$line = scalar <$sock>; +like($line, qr/$rst/, "lqdetect start"); +$line = scalar <$sock>; +do_sop_prepare(); +do_sop_get(); +do_lqdetect_show(); +print $sock "lqdetect stop\r\n"; +$line = scalar <$sock>; +$line = scalar <$sock>; # after test release_memcached($engine, $server);