Ejemplo n.º 1
0
int createContinuum( proxyContext *p, redisAddr *addr, redisContext **c, int cont ) {
    float pct = ((float)1/p->max_count);
    unsigned int ks = floorf( pct * 40.0 * (float)p->max_count );
    
    for( unsigned int k = 0; k < ks; k++ )
    {
        /* 40 hashes, 4 numbers per hash = 160 points per server */
        char ss[128];
        unsigned char digest[16];

        sprintf( ss, "%s:%d-%d", addr->ip, addr->port, k );
        ketama_md5_digest( ss, digest );

        /* Use successive 4-bytes from hash as numbers
         * for the points on the circle: */
        for( int h = 0; h < 4; h++ )
        {
            p->mcs[cont].point = ( digest[3+h*4] << 24 )
                | ( digest[2+h*4] << 16 )
                | ( digest[1+h*4] <<  8 )
                |   digest[h*4];

            p->mcs[cont].c = c;
            p->mcs[cont].ip = addr->ip;
            p->mcs[cont].port = addr->port;
            cont++;
        }
    }

    return cont;
}
Ejemplo n.º 2
0
static int
lketama_md5digest(lua_State *L){
	const char *str = luaL_checkstring(L, 2);
	unsigned char md5pword[16];
	ketama_md5_digest((char*)str, md5pword);
	lua_pushfstring(L, "%p", md5pword);
	return 1;
}
Ejemplo n.º 3
0
unsigned int ketama_hashi( const char* key)
{
    unsigned char digest[16];

    ketama_md5_digest( key, digest );
    return (unsigned int)(( digest[3] << 24 )
            | ( digest[2] << 16 )
            | ( digest[1] <<  8 )
            |   digest[0] );
}
Ejemplo n.º 4
0
Archivo: ketama.c Proyecto: lsm/zir
unsigned int
ketama_hashi( char* inString )
{
    unsigned char digest[16];

    ketama_md5_digest( inString, digest );
    return (unsigned int)(( digest[3] << 24 )
                        | ( digest[2] << 16 )
                        | ( digest[1] <<  8 )
                        |   digest[0] );
}
Ejemplo n.º 5
0
unsigned int
ketama_hashi( char* inString )
{
#if defined(ENABLE_FNV_HASH)
    return fnv_32a_str( inString, FNV1_32_INIT );
#else
    unsigned char digest[16];

    ketama_md5_digest( inString, digest );
    return (unsigned int)(( digest[3] << 24 )
                        | ( digest[2] << 16 )
                        | ( digest[1] <<  8 )
                        |   digest[0] );
#endif
}
Ejemplo n.º 6
0
Archivo: ketama.c Proyecto: lsm/zir
/** \brief Generates the continuum of servers (each server as many points on a circle).
  * \param key Shared memory key for storing the newly created continuum.
  * \param filename Server definition file, which will be parsed to create this continuum.
  * \return 0 on failure, 1 on success. */
static int
ketama_create_continuum( key_t key, char* filename )
{
    int shmid;
    int* data;  /* Pointer to shmem location */
    unsigned int numservers = 0;
    unsigned long memory;
    serverinfo* slist;

    slist = read_server_definitions( filename, &numservers, &memory );
    /* Check numservers first; if it is zero then there is no error message
     * and we need to set one. */
    if ( numservers < 1 )
    {
        sprintf( k_error, "No valid server definitions in file %s", filename );
        return 0;
    }
    else if ( slist == 0 )
    {
        /* read_server_definitions must've set error message. */
        return 0;
    }
#ifdef DEBUG
     syslog( LOG_INFO, "Server definitions read: %u servers, total memory: %lu.\n",
        numservers, memory );
#endif

    /* Continuum will hold one mcs for each point on the circle: */
    mcs continuum[ numservers * 160 ];
    unsigned int i, k, cont = 0;

    for( i = 0; i < numservers; i++ )
    {
        float pct = (float)slist[i].memory / (float)memory;
        unsigned int ks = floorf( pct * 40.0 * (float)numservers );
#ifdef DEBUG
        int hpct = floorf( pct * 100.0 );

        syslog( LOG_INFO, "Server no. %d: %s (mem: %lu = %u%% or %d of %d)\n",
            i, slist[i].addr, slist[i].memory, hpct, ks, numservers * 40 );
#endif

        for( k = 0; k < ks; k++ )
        {
            /* 40 hashes, 4 numbers per hash = 160 points per server */
            char ss[30];
            unsigned char digest[16];

            sprintf( ss, "%s-%d", slist[i].addr, k );
            ketama_md5_digest( ss, digest );

            /* Use successive 4-bytes from hash as numbers 
             * for the points on the circle: */
            int h;
            for( h = 0; h < 4; h++ )
            {
                continuum[cont].point = ( digest[3+h*4] << 24 )
                                      | ( digest[2+h*4] << 16 )
                                      | ( digest[1+h*4] <<  8 )
                                      |   digest[h*4];

                memcpy( continuum[cont].ip, slist[i].addr, 22 );
                cont++;
            }
        }
    }
    free( slist );

    /* Sorts in ascending order of "point" */
    qsort( (void*) &continuum, cont, sizeof( mcs ), (compfn)ketama_compare );

    /* Add data to shmmem */
    shmid = shmget( key, MC_SHMSIZE, 0644 | IPC_CREAT );
    data = shmat( shmid, (void *)0, 0 );
    if ( data == (void *)(-1) )
    {
        strcpy( k_error, "Can't open shmmem for writing." );
        return 0;
    }

    time_t modtime = file_modtime( filename );
    int nump = cont;
    memcpy( data, &nump, sizeof( int ) );
    memcpy( data + 1, &modtime, sizeof( time_t ) );
    memcpy( data + 1 + sizeof( void* ), &continuum, sizeof( mcs ) * nump );

    /* We detatch here because we will re-attach in read-only
     * mode to actually use it. */
    if ( shmdt( data ) == -1 )
        strcpy( k_error, "Error detatching from shared memory!" );

    return 1;
}
Ejemplo n.º 7
0
/** \brief Adds a specified server to the continuum that has just been added to the server list
  * \param addr The address of the server that you want to add points for.
  * \param newmemory The amount of allocated memory from the new server to be added to the cluster
  * \param cont Pointer to the continuum which we will refresh. 
  * \param key Shared memory key for storing the newly created continuum.
  * \param slist The address of the list of servers that your building the continuum from.
  * \param numservers Number of servers available
  * \param memory Amount of memory available accross all servers
  * \param fmodtime File modtime
  * \return 0 on failure, 1 on success. */
int
add_server_to_continuum(char* addr, unsigned long newmemory, continuum* cont, key_t key, serverinfo* slist, int numservers, unsigned long memory, time_t fmodtime)
{
    int maxpoints = POINTS_PER_SERVER * numservers; // maximum number of ring points (HASH_COUNT * POINTS_PER_HASH * numservers)
    int numoldpoints = cont->numpoints; // total number of points in the ring prior to adding the server

    // Continuum will hold one mcs for each point on the circle:
    mcs *ring = (mcs*) malloc( maxpoints * sizeof(mcs) );
    int i, k, indx = -1, numpoints = 0;

    // determine the number of hashes to create
    float ratio = (float)newmemory / (float)memory; // ratio of hashes for this server to total hashes
    int numhashes = floorf( ratio * HASH_COUNT * (float)numservers ); // number of hashes for this server
    //given unevenly distributed memory we need to limit number of hashes
    int max_hashcount = POINTS_PER_SERVER / POINTS_PER_HASH;
    if (numhashes > max_hashcount) {
	numhashes = max_hashcount;
    }
#ifdef DEBUG
    int percent = floorf( ratio * 100.0 ); // percent of total hashes linked to this sever
    syslog( LOG_INFO, "Ketama: Server no. %d: %s (mem: %lu = %u%% or %d of %d)\n",
        i, addr, newmemory, percent, numhashes * POINTS_PER_HASH, HASH_COUNT * numservers * POINTS_PER_HASH );
#endif

#if defined(ENABLE_FNV_HASH)
    Fnv32_t hval = FNV1_32_INIT;
#endif

    // create the points on the ring for the new server
    for( k = 0; k < numhashes; k++ )
    {
#if defined(ENABLE_FNV_HASH)
        hval = fnv_32a_str(addr, hval);
        ring[numpoints].point = hval;
        snprintf( ring[numpoints].ip, sizeof(ring[numpoints].ip), "%s", addr);
        numpoints++;
        if (numpoints > maxpoints) {
       	   snprintf( k_error, sizeof(k_error), "Ketama: add_server_to_continuum tried to exceed mcs array bounds.\n" );
           syslog1( LOG_INFO, k_error );
           free(ring);
           free(slist);
           return 0;
        }
#else
        char ss[30];
        unsigned char digest[16];

        snprintf( ss, sizeof(ss), "%s-%d", addr, k );
        ketama_md5_digest( ss, digest );

        // Use successive 4-bytes from hash as numbers for the points on the circle:
        int h;
        for( h = 0; h < POINTS_PER_HASH; h++ )
        {
            ring[numpoints].point = ( digest[3+h*4] << 24 )
                                  | ( digest[2+h*4] << 16 )
                                  | ( digest[1+h*4] <<  8 )
                                  |   digest[h*4];

            snprintf( ring[numpoints].ip, sizeof(ring[numpoints].ip), "%s", addr);
            numpoints++;
            if (numpoints > maxpoints) {
                snprintf( k_error, sizeof(k_error), "Ketama: add_server_to_continuum tried to exceed mcs array bounds.\n" );
                syslog1( LOG_INFO, k_error );
                free(ring);
                free(slist);
                return 0;
            }
        }
#endif
    }
    
    // append the points on the current ring (will be sorted in the reconstruction phase)
    for( i = 0; i < numoldpoints; i++ )
    {
        memcpy( &ring[numpoints], &cont->array[i], sizeof(mcs) );
        numpoints++;
        if (numpoints > maxpoints) {
            snprintf( k_error, sizeof(k_error), "Ketama: add_server_to_continuum tried to exceed mcs array bounds.\n" );
            syslog1( LOG_INFO, k_error );
            free(ring);
            free(slist);
            return 0;
        }
    }

    // reconstruct the continuum
    return reconstruct_continuum(key, slist, numservers, ring, numpoints, memory, fmodtime);
}
Ejemplo n.º 8
0
/** \brief Loads the continuum of servers (each server as many points on a circle).
  * \param key Shared memory key for storing the newly created continuum.
  * \param slist The address of the list of servers that your building the continuum from.
  * \param numservers Number of servers available
  * \param memory Amount of memory available accross all servers
  * \param fmodtime File modtime
  * \return 0 on failure, 1 on success. */
int
load_continuum(key_t key, serverinfo* slist, int numservers, unsigned long memory, time_t fmodtime)
{
    int maxpoints = POINTS_PER_SERVER * numservers; // maximum number of ring points (HASH_COUNT * POINTS_PER_HASH * numservers)

    // Continuum will hold one mcs for each point on the circle:
    mcs *ring = (mcs*) malloc( maxpoints * sizeof(mcs) );
    int i, k, numpoints = 0;

    // buildup the continuum ring
    for( i = 0; i < numservers; i++ )
    {
        float ratio = (float) slist[i].memory / (float)memory; // ratio of hashes for this server to total hashes
        int numhashes = floorf( ratio * HASH_COUNT * (float)numservers ); // number of hashes for this server
#ifdef DEBUG
        int percent = floorf( ratio * 100.0 ); // percent of total hashes linked to this sever
        syslog( LOG_INFO, "Ketama: Server no. %d: %s (mem: %lu = %u%% or %d of %d)\n",
            i, slist[i].addr, slist[i].memory, percent, numhashes * POINTS_PER_HASH, HASH_COUNT * numservers * POINTS_PER_HASH );
#endif

#if defined(ENABLE_FNV_HASH)
        Fnv32_t hval = FNV1_32_INIT;
#endif

        // create the points on the ring for this server
        for( k = 0; k < numhashes; k++ )
        {
#if defined(ENABLE_FNV_HASH)
            hval = fnv_32a_str(slist[i].addr, hval);
            ring[numpoints].point = hval;
            snprintf( ring[numpoints].ip, sizeof(ring[numpoints].ip), "%s", slist[i].addr);
            numpoints++;
#else
            char ss[30];
            unsigned char digest[16];

            snprintf( ss, sizeof(ss), "%s-%d", slist[i].addr, k );
            ketama_md5_digest( ss, digest );

            // Use successive 4-bytes from hash as numbers for the points on the circle:
            int h;
            for( h = 0; h < POINTS_PER_HASH; h++ )
            {
                ring[numpoints].point = ( digest[3+h*4] << 24 )
                                      | ( digest[2+h*4] << 16 )
                                      | ( digest[1+h*4] <<  8 )
                                      |   digest[h*4];

                snprintf( ring[numpoints].ip, sizeof(ring[numpoints].ip), "%s", slist[i].addr);
                numpoints++;
                if (numpoints > maxpoints) {
                    snprintf( k_error, sizeof(k_error), "Ketama: load_continuum tried to exceed mcs array bounds.\n" );
                    syslog1( LOG_INFO, k_error );
                    free(ring);
                    free(slist);
                    return 0;
                }
            }
#endif
        }
    }

    return reconstruct_continuum(key, slist, numservers, ring, numpoints, memory, fmodtime);
}