net-pool 0.1.3

A set of types for network connection pool.
Documentation
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);
    }
}