int main(int argc, char **argv) { if(argc==1){ printf("Usage: %s <ketama.servers file>\n", *argv); return 1; } ketama_continuum c; serverinfo* serverinfo; ketama_roll( &c, *++argv, serverinfo ); printf( "%s\n", ketama_error() ); int i; for ( i = 0; i < 1000000; i++ ) { char k[10]; sprintf( k, "%d", i ); unsigned int kh = ketama_hashi( k ); mcs* m = ketama_get_server( k, c ); printf( "%u %u %s\n", kh, m->point, m->ip ); } ketama_smoke(c); return 0; }
mcs* ketama_get_server( char* key, ketama_continuum cont ) { unsigned int h = ketama_hashi( key ); int highp = cont->numpoints; mcs (*mcsarr)[cont->numpoints] = cont->array; int lowp = 0, midp; unsigned int midval, midval1; // divide and conquer array search to find server with next biggest // point after what this key hashes to while ( 1 ) { midp = (int)( ( lowp+highp ) / 2 ); if ( midp == cont->numpoints ) return &( (*mcsarr)[0] ); // if at the end, roll back to zeroth midval = (*mcsarr)[midp].point; midval1 = midp == 0 ? 0 : (*mcsarr)[midp-1].point; if ( h <= midval && h > midval1 ) return &( (*mcsarr)[midp] ); if ( midval < h ) lowp = midp + 1; else highp = midp - 1; if ( lowp > highp ) return &( (*mcsarr)[0] ); } }
static int lketama_fnv1a32digest(lua_State *L){ const char *str = luaL_checkstring(L, 2); int hval = ketama_hashi((char*)str); lua_pushfstring(L, "%d", hval); return 1; }
static int lketama_hashi(lua_State *L){ const char *str = luaL_checkstring(L, 2); unsigned int res = ketama_hashi((char*)str); lua_pushnumber(L, res); return 1; }
PY_DEF(pyketama_hashi, self, args) { char *data; PyObject *r = NULL; if (PyArg_ParseTuple(args, "s", &data)) { r = Py_BuildValue("I", ketama_hashi(data)); } }
mcs* ketama_get_server( char* key, ketama_continuum cont ) { unsigned int h = ketama_hashi( key ); int lowp = 0, midp, highp; unsigned int midval, midval1; // verify that a valid resource was passed in before getting its key if (cont == NULL) { snprintf( k_error, sizeof(k_error), "Ketama: ketama_get_server passed illegal pointer to a continuum resource.\n" ); syslog1( LOG_INFO, k_error ); return NULL; } key_t fkey = cont->key; // try to find an existsing resource with a shared memory segment in the array of tracked resources, or create a new attachment resource if ( !get_shm_resource(fkey, cont) ) { snprintf( k_error, sizeof(k_error), "Ketama: ketama_get_server failed to get a valid resource.\n" ); syslog1( LOG_INFO, k_error ); return NULL; } // divide and conquer array search to find server with next biggest // point after what this key hashes to highp = cont->data->numpoints; while ( 1 ) { midp = ( lowp+highp ) >> 1; if ( midp == cont->data->numpoints ) return &cont->data->array[0]; // if at the end, roll back to zeroth midval = cont->data->array[midp].point; midval1 = midp == 0 ? 0 : cont->data->array[midp-1].point; if ( h <= midval && h > midval1 ) return &cont->data->array[midp]; if ( midval < h ) lowp = ++midp; else highp = --midp; if ( lowp > highp ) return &cont->data->array[0]; } }
redisContext *lookupRedisServerWithKey( proxyContext *p, const char *key ) { unsigned int h = ketama_hashi( key ); int highp = p->mcs_count-1; int lowp = 0, midp; unsigned int midval, midval1; ketamaMCS *mcs = p->mcs; while ( lowp < highp ) { midp = (int)( ( lowp+highp ) / 2 ); midval = mcs[midp].point; midval1 = (midp == 0) ? 0 : mcs[midp-1].point; if ( h <= midval && h > midval1 ) return getFirstContext(p, midp); if ( midval < h ) lowp = midp + 1; else highp = midp - 1; } return getFirstContext(p, lowp); }