use crate::backend::{Address, BackendState, BackendStates};
use std::sync::RwLock;
use std::sync::atomic::{AtomicUsize, Ordering};
pub struct RRStrategy {
index: AtomicUsize,
bss: RwLock<BackendStates>,
}
impl RRStrategy {
pub fn new() -> Self {
RRStrategy::default()
}
fn valid_backend(&self, addr: &Address, valid: bool) -> bool {
let mut g = self.bss.write().unwrap();
let bss = g.get_backends_mut();
if bss.is_empty() {
return false;
}
let code = addr.hash_code();
for bs in bss.iter_mut() {
if bs.hash_code() == code {
bs.set_valid(valid);
return true;
}
}
return false;
}
}
impl Default for RRStrategy {
fn default() -> Self {
RRStrategy {
index: AtomicUsize::new(0),
bss: RwLock::new(BackendStates::new()),
}
}
}
impl super::LbStrategy for RRStrategy {
fn strategy(&self) -> super::Strategy {
super::Strategy::RoundRobin
}
fn contain(&self, hash_code: u64) -> bool {
let g = self.bss.read().unwrap();
g.contain(hash_code)
}
fn add_backend(&self, addr: Address) {
let mut g = self.bss.write().unwrap();
g.add_backend(addr);
}
fn remove_backend(&self, addr: &Address) -> bool {
let mut g = self.bss.write().unwrap();
g.remove_backend(&addr)
}
fn get_backend(&self, _: &str) -> Option<BackendState> {
let g = self.bss.read().unwrap();
let bss = g.get_backends();
if bss.is_empty() {
return None;
}
let index = self.index.fetch_add(1, Ordering::Relaxed);
let idx = index % bss.len();
Some(bss[idx].clone())
}
fn get_backends(&self) -> Vec<BackendState> {
let g = self.bss.read().unwrap();
let bss = g.get_backends();
bss.iter().map(|bs| bs.clone()).collect()
}
fn get_origin_backends(&self) -> Vec<BackendState> {
self.get_backends()
}
fn disable_backend(&self, addr: &Address) -> bool {
self.valid_backend(addr, false)
}
fn enable_backend(&self, addr: &Address) {
self.valid_backend(addr, true);
}
}