node & server: separate dirty flag, remove DirtyState

This commit is contained in:
Luna Yao
2026-02-22 03:34:45 +01:00
parent fcfb0ad6bc
commit 2e1f9bc9cc
5 changed files with 66 additions and 46 deletions
+1 -1
View File
@@ -74,7 +74,7 @@ impl DnsNode {
last_heartbeat = Instant::now(); last_heartbeat = Instant::now();
} }
_ = self.mgr.dirty.notify.notified() => {} _ = self.mgr.dirty.notified() => {}
event = subscriber.recv() => { event = subscriber.recv() => {
match event { match event {
+2 -3
View File
@@ -1,5 +1,5 @@
use crate::dns::utils::addr::NameServerAddr; use crate::dns::utils::addr::NameServerAddr;
use crate::dns::utils::dirty::{DirtyFlag, DirtyState}; use crate::dns::utils::dirty::DirtyFlag;
use crate::dns::zone::{Zone, ZoneGroup}; use crate::dns::zone::{Zone, ZoneGroup};
use crate::proto::dns::DnsNodeMgrRpc; use crate::proto::dns::DnsNodeMgrRpc;
use crate::proto::dns::{DnsSnapshot, HeartbeatRequest, HeartbeatResponse}; use crate::proto::dns::{DnsSnapshot, HeartbeatRequest, HeartbeatResponse};
@@ -47,7 +47,7 @@ pub struct DnsNodeMgrDirtyFlags {
#[derive(Debug)] #[derive(Debug)]
pub struct DnsNodeMgr { pub struct DnsNodeMgr {
nodes: Cache<Uuid, DnsNodeInfo>, nodes: Cache<Uuid, DnsNodeInfo>,
pub(super) dirty: DirtyState<DnsNodeMgrDirtyFlags>, pub(super) dirty: DnsNodeMgrDirtyFlags,
} }
impl DnsNodeMgr { impl DnsNodeMgr {
@@ -145,7 +145,6 @@ impl DnsNodeMgrRpc for DnsNodeMgr {
} }
self.nodes.insert(id, new).await; self.nodes.insert(id, new).await;
self.dirty.notify.notify_one();
} }
false false
} else { } else {
+3 -3
View File
@@ -1,7 +1,7 @@
use crate::common::config::ConfigLoader; use crate::common::config::ConfigLoader;
use crate::common::PeerId; use crate::common::PeerId;
use crate::dns::config::{DnsExportConfig, DnsGlobalCtxExt}; use crate::dns::config::{DnsExportConfig, DnsGlobalCtxExt};
use crate::dns::utils::dirty::{DirtyFlag, DirtyState}; use crate::dns::utils::dirty::DirtyFlag;
use crate::dns::zone::ZoneGroup; use crate::dns::zone::ZoneGroup;
use crate::peer_center::instance::PeerCenterPeerManagerTrait; use crate::peer_center::instance::PeerCenterPeerManagerTrait;
use crate::peers::peer_manager::PeerManager; use crate::peers::peer_manager::PeerManager;
@@ -42,7 +42,7 @@ const DNS_PEER_TTL: Duration = Duration::from_secs(3);
#[derive(Debug, Deref)] #[derive(Debug, Deref)]
pub struct DnsPeerMgr { pub struct DnsPeerMgr {
peers: Cache<PeerId, DnsPeerInfo>, peers: Cache<PeerId, DnsPeerInfo>,
pub(super) dirty: DirtyState<DirtyFlag>, pub(super) dirty: DirtyFlag,
#[deref] #[deref]
mgr: Arc<PeerManager>, mgr: Arc<PeerManager>,
@@ -103,7 +103,7 @@ impl DnsPeerMgr {
} }
} }
self.dirty.notify.notify_one(); self.dirty.notify_one();
} }
async fn fetch(&self, peer_id: PeerId) -> anyhow::Result<DnsPeerInfo> { async fn fetch(&self, peer_id: PeerId) -> anyhow::Result<DnsPeerInfo> {
+45 -33
View File
@@ -131,9 +131,6 @@ pub struct DnsServer {
#[derivative(Debug = "ignore")] #[derivative(Debug = "ignore")]
catalog: DynamicCatalog, catalog: DynamicCatalog,
/// Current set of hijacked addresses (only UDP protocol addresses).
addresses: RwLock<HashSet<NameServerAddr>>,
} }
const DNS_SERVER_LISTENER_TCP_TIMEOUT: Duration = Duration::from_secs(5); const DNS_SERVER_LISTENER_TCP_TIMEOUT: Duration = Duration::from_secs(5);
@@ -153,23 +150,24 @@ impl DnsServer {
Self { Self {
mgr, mgr,
catalog: DynamicCatalog::new(), catalog: DynamicCatalog::new(),
addresses: RwLock::new(HashSet::new()),
} }
} }
async fn reload_addresses(&self, addresses: impl IntoIterator<Item = NameServerAddr>) { async fn reload_addresses(
&self,
addresses: impl IntoIterator<Item = NameServerAddr>,
current: &mut HashSet<NameServerAddr>,
) {
let addresses = addresses.into_iter().collect::<HashSet<_>>(); let addresses = addresses.into_iter().collect::<HashSet<_>>();
let mut active = self.addresses.write().await; let added = addresses.difference(&current).cloned().collect_vec();
let removed = current.difference(&addresses).cloned().collect_vec();
let added = addresses.difference(&active).cloned().collect_vec();
let removed = active.difference(&addresses).cloned().collect_vec();
if added.is_empty() && removed.is_empty() { if added.is_empty() && removed.is_empty() {
return; return;
} }
*active = addresses; *current = addresses;
// TODO // TODO
} }
@@ -209,30 +207,44 @@ impl DnsServer {
pub async fn run(&self) { pub async fn run(&self) {
let dirty = &self.mgr.dirty; let dirty = &self.mgr.dirty;
let mut runtime = None;
loop {
dirty.notify.notified().await;
if dirty.catalog.reset() { tokio::join!(
self.catalog.replace(self.mgr.catalog()).await; async {
} loop {
dirty.catalog.notified().await;
if dirty.addresses.reset() { if dirty.catalog.reset() {
self.reload_addresses(self.mgr.iter_addresses()).await; self.catalog.replace(self.mgr.catalog()).await;
} }
tokio::time::sleep(Duration::from_secs(1)).await;
if dirty.listeners.reset() {
if let Err(e) = self
.reload_listeners(self.mgr.iter_listeners(), &mut runtime)
.await
{
tracing::error!("failed to reload listeners: {:?}", e);
dirty.listeners.mark();
dirty.notify.notify_one();
} }
} },
async {
tokio::time::sleep(Duration::from_secs(1)).await; let mut addresses = HashSet::new();
} loop {
dirty.addresses.notified().await;
if dirty.addresses.reset() {
self.reload_addresses(self.mgr.iter_addresses(), &mut addresses)
.await;
}
tokio::time::sleep(Duration::from_secs(1)).await;
}
},
async {
let mut runtime = None;
loop {
dirty.listeners.notified().await;
if dirty.listeners.reset() {
if let Err(e) = self
.reload_listeners(self.mgr.iter_listeners(), &mut runtime)
.await
{
tracing::error!("failed to reload listeners: {:?}", e);
dirty.listeners.mark();
}
}
tokio::time::sleep(Duration::from_secs(1)).await;
}
},
);
} }
} }
+15 -6
View File
@@ -11,24 +11,33 @@ pub struct DirtyState<T> {
pub notify: Notify, pub notify: Notify,
} }
#[derive(Derivative, Debug)] #[derive(Derivative, Debug, Deref)]
#[derivative(Default)] #[derivative(Default)]
pub struct DirtyFlag(#[derivative(Default(value = "AtomicBool::new(true)"))] AtomicBool); pub struct DirtyFlag {
#[derivative(Default(value = "AtomicBool::new(true)"))]
dirty: AtomicBool,
#[deref]
notify: Notify,
}
impl DirtyFlag { impl DirtyFlag {
pub fn new(value: bool) -> Self { pub fn new(value: bool) -> Self {
Self(AtomicBool::new(value)) Self {
dirty: AtomicBool::new(value),
notify: Notify::new(),
}
} }
pub fn mark(&self) { pub fn mark(&self) {
self.0.store(true, Ordering::Release); self.dirty.store(true, Ordering::Release);
self.notify.notify_one();
} }
pub fn peek(&self) -> bool { pub fn peek(&self) -> bool {
self.0.load(Ordering::Acquire) self.dirty.load(Ordering::Acquire)
} }
pub fn reset(&self) -> bool { pub fn reset(&self) -> bool {
self.0.swap(false, Ordering::Acquire) self.dirty.swap(false, Ordering::Acquire)
} }
} }