/** \brief Locks the semaphore only after it is unlocked by another process. * \param sem_set_id The semaphore handle that you want to lock. */ static void ketama_sem_safely_lock( int sem_set_id ) { 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 > 200000) { usleep( rand()%50000 ); ketama_sem_unlock( sem_set_id ); break; } } ketama_sem_lock( sem_set_id ); }
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; }