void ConnectionPool::recycle_connections() { // The recycler periodically recycles the connections so that any new nodes // in the upstream proxy cluster get used reasonably soon after they are // active. To avoid mucking around with variable length waits, the // algorithm waits for a fixed period (one second) then recycles a // number of connections. // // Logically the algorithm runs an independent trial for each hash slot // with a success probability of (1/_recycle_period). For efficiency this // is implemented by using a binomially distributed random number to find // the number of successful trials, then selecting that number of hash slots // at random. // // Currently the selection is done with replacement which raises the possibility // that one connection may be recycled twice in the same schedule, but this // should only introduce a small error in the recycling rate. std::default_random_engine rand; std::binomial_distribution<int> rbinomial(_num_connections, 1.0/_recycle_period); while (!_terminated) { sleep(1); int recycle = rbinomial(rand); LOG_INFO("Recycling %d connections to %.*s:%d", recycle, _target.host.slen, _target.host.ptr, _target.port); for (int ii = 0; ii < recycle; ++ii) { // Pick a hash slot at random, and quiesce the connection (if active). int hash_slot = rand() % _num_connections; quiesce_connection(hash_slot); // Create a new connection for this hash slot. create_connection(hash_slot); } int index = 0; // Walk the hash table, attempting to fill in any gaps caused by transports failing. // // It is safe to walk the vector without the lock since: // // * The vector never changes size // * We only care about the value of the entry being NULL (atomic check) // * Only we can change a NULL value to a non-NULL value // * If we just miss a change from non-NULL to NULL (a transport suddenly dies), we'll catch it in a second. for (std::vector<tp_hash_slot>::iterator it = _tp_hash.begin(); it != _tp_hash.end(); ++it) { if (it->tp == NULL) { create_connection(index); } index++; } } }
void SparseGenome::init_mutations(ISet &is) { int p = 2*is.size(); // number of "strands" = 2 * #individuals int i, j, k, l; // counters and temp indices int n; // number of individuals in set mutation_t si; // mutation effect of a single gene fitness_t xw; // change in fitness due to this gene double qi; // frequency of gene double gu; // genic mutation rate int x, nx; // id of individual, #individuals int nl = 0; // for debugging, keep track of #loci and int nm = 0; // #mutations affected by this step int *bin; // also keep track of distribution of mutation values IP *v; SparseGenome *sgp; n = is.size(); v = new IP[n]; for (i=0; i<n; i++) // copy individuals to local vector for faster access v[i] = is.remove(0); bin = new int[p+1]; // cout << "Placing initial mutations in " << p << " strands...." << endl; for (i=0; i<=p; i++) bin[i] = 0; gu = u/(2*gl); // genic rate = individual rate / number of genes // cout << "Genic mutation rate (U/2N) = " << gu << endl; // Iterate over all loci; pick a mutation effect for that locus, figure // out the expected frequency of a gene with that effect, and then add it // to selected individuals. In this loop 'i' is the locus index, 'j' // is the chromosome number for that locus, and 'k' is the index of the locus // within the chromosome. // optimization: knowing that get_gene() and set_gene() in Strand scan // from "left to right", start with the higher locus indices and count // down to 0 -- this way the lookups and insertions will all be done // in one step.... for (i = gl-1; i >= 0; i--) { j = i / chrlength; k = i % chrlength; si = new_mutation_value(s,rs); // get mutation effect qi = gu/hs(si); // frequency of allele with effect si if (qi > 1.0) qi = 1.0; nx = int(rbinomial(qi,p)); // number of genes expected to have this mutation if (nx > p) nx = p; // if (qi) { // cout << "locus " << i << ": "; // cout << ", si = " << si; // cout << ", hs = " << hs(si,0.0); // cout << ", qi = " << qi; // cout << ", nx = " << nx << endl; // } nm += nx; // record info on this mutation bin[nx] += 1; if (nx) nl += 1; while (nx) { x = rword(n); l = rword(2); sgp = (SparseGenome *)v[x]->genes; if (sgp->sa[j].get_gene(k,l) == 0.0) { xw = sgp->sa[j].set_gene(k,l,si); sgp->w *= xw; nx--; } } } // cout << "Distributed " << nm << " mutations across " << nl << " loci" << endl; // for (i=0; i<=p; i++) // cout << i << ": " << bin[i] << endl; }