use crate::db::Keyspace;
use crate::pubsub::PubSub;
use crate::resp::Frame;
use bytes::Bytes;
use std::collections::{HashMap, HashSet};
use std::net::SocketAddr;
use std::sync::atomic::{AtomicBool, AtomicU64, Ordering};
use std::sync::Mutex;
use std::time::Instant;
use tokio::sync::mpsc::UnboundedSender;
use tokio::sync::Notify;
pub struct Shared {
pub db: Mutex<Keyspace>,
pub pubsub: PubSub,
pub requirepass: Option<String>,
pub config: Mutex<HashMap<String, String>>,
pub scripts: Mutex<HashMap<String, Bytes>>,
pub write_notify: Notify,
pub clients: Mutex<HashMap<u64, ClientInfo>>,
pub run_id: String,
pub commands_processed: AtomicU64,
pub connections_received: AtomicU64,
next_client_id: AtomicU64,
verbose: AtomicBool,
pub port: u16,
pub maxclients: usize,
pub start: Instant,
}
impl Shared {
pub fn new(
requirepass: Option<String>,
port: u16,
maxclients: usize,
databases: usize,
verbose: bool,
start: Instant,
) -> Shared {
let mut config = HashMap::new();
let databases_str = databases.to_string();
for (k, v) in [
("maxmemory", "0"),
("maxmemory-policy", "noeviction"),
("save", ""),
("appendonly", "no"),
("appendfsync", "everysec"),
("databases", databases_str.as_str()),
("maxclients", "10000"),
("timeout", "0"),
("tcp-keepalive", "300"),
("loglevel", if verbose { "verbose" } else { "notice" }),
] {
config.insert(k.to_string(), v.to_string());
}
Shared {
db: Mutex::new(Keyspace::new(databases)),
pubsub: PubSub::default(),
requirepass,
config: Mutex::new(config),
scripts: Mutex::new(HashMap::new()),
write_notify: Notify::new(),
clients: Mutex::new(HashMap::new()),
run_id: gen_run_id(),
commands_processed: AtomicU64::new(0),
connections_received: AtomicU64::new(0),
next_client_id: AtomicU64::new(1),
verbose: AtomicBool::new(verbose),
port,
maxclients,
start,
}
}
pub fn next_client_id(&self) -> u64 {
self.next_client_id.fetch_add(1, Ordering::Relaxed)
}
pub fn verbose(&self) -> bool {
self.verbose.load(Ordering::Relaxed)
}
pub fn set_verbose(&self, on: bool) {
self.verbose.store(on, Ordering::Relaxed);
}
}
fn gen_run_id() -> String {
let mut s = String::with_capacity(40);
while s.len() < 40 {
s.push_str(&format!("{:016x}", crate::commands::rand_u64()));
}
s.truncate(40);
s
}
#[derive(Clone)]
pub struct ClientInfo {
pub id: u64,
pub addr: String,
pub name: String,
pub resp3: bool,
pub db: usize,
}
pub struct ConnState {
pub id: u64,
pub addr: SocketAddr,
pub name: Bytes,
pub resp3: bool,
pub db_index: usize,
pub authenticated: bool,
pub subscribed_channels: HashSet<Bytes>,
pub subscribed_patterns: HashSet<Bytes>,
pub in_multi: bool,
pub multi_queue: Vec<Vec<Bytes>>,
pub multi_error: bool,
pub watched: HashMap<(usize, Bytes), (bool, u64)>,
pub tx: UnboundedSender<Frame>,
}
impl ConnState {
pub fn subscription_count(&self) -> usize {
self.subscribed_channels.len() + self.subscribed_patterns.len()
}
}