php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #58326 possible issue in consistent hashing algorithm
Submitted: 2008-08-25 16:16 UTC Modified: 2011-03-10 21:44 UTC
From: jyukes at gmail dot com Assigned: hradtke (profile)
Status: No Feedback Package: memcache (PECL)
PHP Version: 5.2.3 OS: ubuntu7
Private report: No CVE-ID: None
Have you experienced this issue?
Rate the importance of this bug to you:

 [2008-08-25 16:16 UTC] jyukes at gmail dot com
Description:
------------
I have attached a SimpleTest unit test that reprodues the issue.... the key can end up on multiple hosts...  when there haven't been any connection oriented issues.

If I use 10 servers -- there may be 4 copies of the key stored.

I have attached the smallest example that consistently reproduces the issue.

Reproduce code:
---------------
<?
require_once('simpletest/autorun.php');
SimpleTest :: prefer(new HtmlReporter());

// this fails for various keys - of different length
// if i use a shorter key, it doesn't fail
// and it only seems to fail in the CLI

define( 'TEST_KEY', 'TEST.MEMCACHE.CONSISTENT' );

class TestMemcacheConsistent extends UnitTestCase {
        var $mem;
        var $servers;
        var $strategy;

        function setUp() {
                ini_set('display_errors', 'On');
                error_reporting( E_ALL );
                foreach ( range( 80, 81 ) as $octet ) {
                        $server = '192.168.10.' . $octet;
                        $this->servers[] = $server;
                }
        }

        function mySetUp( $strategy ) {
                ini_set( 'memcache.hash_strategy', $strategy );
                $this->strategy = $strategy;

                foreach ( range( 1, 2 ) as $i ) {
                        $m = new MemcachePool( );
                        $this->mem[] = $m;
                }
                foreach ( $this->servers as $server ) {
                        foreach ( $this->mem as $m )  {
                                $m->addServer( $server );
                        }
                }
        }

        function myTest() {
                foreach ( $this->mem as $m ) {
                        $result = $m->set( constant( 'TEST_KEY' ), $this->servers );
                        $this->assertTrue( $result );
                }

                foreach ( range( 1, 1 ) as $i ) {
                        foreach ( $this->mem as $m ) {
                                $result = $m->get( constant( 'TEST_KEY' ) );
                                $this->assertTrue( $this->servers == $result );

                                $result = $m->set( constant( 'TEST_KEY' ), $this->servers );
                                $this->assertTrue( $result );
                        }
                }
                $count = $this->countKeysFound( constant( 'TEST_KEY' ) );
                $this->assertTrue( $count == 1 );
        }

        function testConsistent() {
                $this->deleteKeysFound( constant( 'TEST_KEY' ) );
                $this->mySetUp( 'consistent' );
                $this->myTest();
        }

        function testConsistent2() {
                $this->mySetUp( 'consistent' );
                $this->myTest();
        }

        function testStandard() {
                $this->deleteKeysFound( constant( 'TEST_KEY' ) );
                $this->mySetUp( 'standard' );
                $this->myTest();
        }

        function testStandard2() {
                $this->mySetUp( 'standard' );
                $this->myTest();
        }

        function sendCommandToServer( $server, $cmd ) {
                $s = @fsockopen($server,'11211');
                if (!$s) {
                        return FALSE;
                }
                fwrite($s, $cmd . "\r\n");

                $buf = fgets($s, 256);
                return $buf;
        }

        function countKeysFound( $key ) {
                $count = 0;
                foreach ( $this->servers as $server ) {
                        $buf = $this->sendCommandToServer( $server, 'get ' . $key );
                        if ( !strncmp( $buf, 'VALUE', 5 ) ) {
                                $count++;
                        }
                }
                return $count;
        }

        function deleteKeysFound( $key ) {
                $count = 0;
                foreach ( $this->servers as $server ) {
                        $buf = $this->sendCommandToServer( $server, 'delete ' . $key );
                        if ( !strncmp( $buf, 'DELETED', 7 ) ) $count++;
                }
                return $count;
        }

        function tearDown() {
                unset( $this->mem );
                unset( $this->servers );
        }
}

?>


Expected result:
----------------
# php test_memcache2.php
test_memcache2.php
OK
Test cases run: 1/1, Passes: 28, Failures: 0, Exceptions: 0




Actual result:
--------------
# php test_memcache2.php
test_memcache2.php
1) Expected true, got [Boolean: false] at [test_memcache2.php line 73]
        in testConsistent2
        in TestMemcacheConsistent
FAILURES!!!
Test cases run: 1/1, Passes: 27, Failures: 1, Exceptions: 0




Patches

Add a Patch

Pull Requests

Add a Pull Request

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2010-04-25 14:38 UTC] hradtke@php.net
Are you using 2.x or 3.x?  I just tried to recreate this using the 3.x branch and was not able to.
 [2011-03-10 21:44 UTC] hradtke@php.net
No feedback was provided. The bug is being suspended because
we assume that you are no longer experiencing the problem.
If this is not the case and you are able to provide the
information that was requested earlier, please do so and
change the status of the bug back to "Open". Thank you.


 
PHP Copyright © 2001-2021 The PHP Group
All rights reserved.
Last updated: Wed Dec 08 13:03:41 2021 UTC