static int ketama_roller( ketama_continuum* contptr, char* filename, int roller_flag ) { key_t key; continuum_resource resource; // if we have a string like "key:0x1234" that means we want to set up the infastructure // but leave continuum creation until we manually add servers with ketama_add_server char cont_filename[PATH_MAX]; time_t fmodtime; snprintf(cont_filename, sizeof(cont_filename), "%s", filename); key = get_key(cont_filename, &fmodtime); if ( key == -1 ) { snprintf( k_error, sizeof(k_error), "Ketama: ketama_roll failed to make a valid key from %s.\n", filename ); syslog1( LOG_INFO, k_error ); return 0; } // 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(key, &resource) ) { snprintf( k_error, sizeof(k_error), "Ketama: ketama_roller failed to get a valid resource.\n" ); syslog1( LOG_INFO, k_error ); return 0; } // if the continuum is not stale or new, end here and track the resource if we somehow missed tracking it if ( (resource.data->fmodtime == fmodtime) && (resource.data->cont_version != 0) ) { **contptr = resource; track_shm_resource(resource); syslog( LOG_DEBUG, "Ketama: ketama_roll() successfully found a valid shared memory segment at %p with ID: %lu and key: %lu, stored into %p.\n", resource.data, (long unsigned int) resource.shmid, (long unsigned int) resource.key, *contptr); return 1; } // detach from the shared memory segment so that we can attach again in ketama_create to initialize the continuum if ( ketama_shmdt(resource.data) == -1 ) { snprintf( k_error, sizeof(k_error), "Ketama: ketama_roll failed to detatch from shared memory with errno: %d.\n", errno ); syslog1( LOG_INFO, k_error ); } // if we've already attempted to run ketama_create then that subroutine failed and we want to fail out if ( roller_flag != 0) { snprintf( k_error, sizeof(k_error), "Ketama: ketama_create_continuum failed to create a valid continuum.\n" ); syslog1( LOG_INFO, k_error ); return 0; } // attempt to run ketama_create continuum if ( !ketama_create_continuum( key, filename, contptr ) ) { snprintf( k_error, sizeof(k_error), "Ketama: ketama_create_continuum failed!\n" ); syslog1( LOG_INFO, k_error ); return 0; } // if we reach this point then we've created the continuum and reran ketama_roll to check its validity, so just log this and exit syslog1( LOG_INFO, "Ketama: ketama_create_continuum successfully finished.\n" ); return 1; }
int ketama_roll( ketama_continuum* contptr, char* filename ) { strcpy( k_error, "" ); key_t key; int shmid; int *data; int sem_set_id; // setlogmask( LOG_UPTO ( LOG_NOTICE | LOG_ERR | LOG_INFO ) ); // openlog( "ketama", LOG_CONS | LOG_PID | LOG_NDELAY, LOG_LOCAL1 ); key = ftok( filename, 'R' ); if ( key == -1 ) { sprintf( k_error, "Invalid filename specified: %s", filename ); return 0; } *contptr = malloc( sizeof( continuum ) ); (*contptr)->numpoints = 0; (*contptr)->array = 0; (*contptr)->modtime = 0; sem_set_id = ketama_sem_init( key ); int sanity = 0; while ( semctl( sem_set_id, 0, GETVAL, 0 ) == 2 ) { // wait for the continuum creator to finish, but don't block others usleep( 5 ); // if we are waiting for > 1 second, take drastic action: if(++sanity > 1000000) { usleep( rand()%50000 ); ketama_sem_unlock( sem_set_id ); break; } } time_t modtime = file_modtime( filename ); time_t* fmodtime = 0; while ( !fmodtime || modtime != *fmodtime ) { shmid = shmget( key, MC_SHMSIZE, 0 ); // read only attempt. data = shmat( shmid, (void *)0, SHM_RDONLY ); if ( data == (void *)(-1) || (*contptr)->modtime != 0 ) { ketama_sem_lock( sem_set_id ); // if ( (*contptr)->modtime == 0 ) // syslog( LOG_INFO, "Shared memory empty, creating and populating...\n" ); // else // syslog( LOG_INFO, "Server definitions changed, reloading...\n" ); if ( !ketama_create_continuum( key, filename ) ) { // strcpy( k_error, "Ketama_create_continuum() failed!" ); ketama_sem_unlock( sem_set_id ); return 0; } /* else syslog( LOG_INFO, "ketama_create_continuum() successfully finished.\n" );*/ shmid = shmget( key, MC_SHMSIZE, 0 ); // read only attempt. data = shmat( shmid, (void *)0, SHM_RDONLY ); ketama_sem_unlock( sem_set_id ); } if ( data == (void *)(-1) ) { strcpy( k_error, "Failed miserably to get pointer to shmemdata!" ); return 0; } (*contptr)->numpoints = *data; (*contptr)->modtime = ++data; (*contptr)->array = data + sizeof( void* ); fmodtime = (time_t*)( (*contptr)->modtime ); } return 1; }