target.cc (1485B)
1 #include "roundrobin" 2 3 unsigned Roundrobin::target(struct in_addr clientip, 4 BackendVector &targetlist) { 5 // Regardless of a pre-existent targetlist, we rebuild it here. 6 // We do that to take weights into accounts. 7 static bool building; 8 mutex_lock(&building); 9 targetlist.reset(); 10 for (unsigned int i = 0; i < balancer.nbackends(); i++) 11 for (unsigned int j = 0; j < balancer.backend(i).weight(); j++) 12 targetlist.add(i); 13 mutex_unlock(&building); 14 15 if (config.debug()) { 16 ostringstream o; 17 o << "Round robin target list: "; 18 for (unsigned i = 0; i < targetlist.size(); i++) 19 o << targetlist[i] << ' '; 20 o << '\n'; 21 debugmsg(o.str()); 22 } 23 24 if (targetlist.size() == 1) 25 return (targetlist[0]); 26 27 static int prev_run_index = -1; 28 29 unsigned first_try_val = 0; 30 bool first_try_set = false; 31 while (true) { 32 // See where we will start 33 unsigned cur_val; 34 35 if (prev_run_index == -1) { 36 cur_val = 0; 37 } else { 38 if (! first_try_set) { 39 first_try_set = true; 40 first_try_val = prev_run_index; 41 } 42 cur_val = prev_run_index + 1; 43 cur_val %= targetlist.size(); 44 if (cur_val == first_try_val) 45 throw Error("Round robin dispatcher: no backends\n"); 46 } 47 48 // Store for next time 'round 49 mutex_lock(&prev_run_index); 50 prev_run_index = cur_val; 51 mutex_unlock(&prev_run_index); 52 53 if (! balancer.backend(targetlist[cur_val]).available()) 54 continue; 55 56 // Done. 57 return (targetlist[cur_val]); 58 } 59 }