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();
}
_ = self.mgr.dirty.notify.notified() => {}
_ = self.mgr.dirty.notified() => {}
event = subscriber.recv() => {
match event {
+2 -3
View File
@@ -1,5 +1,5 @@
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::proto::dns::DnsNodeMgrRpc;
use crate::proto::dns::{DnsSnapshot, HeartbeatRequest, HeartbeatResponse};
@@ -47,7 +47,7 @@ pub struct DnsNodeMgrDirtyFlags {
#[derive(Debug)]
pub struct DnsNodeMgr {
nodes: Cache<Uuid, DnsNodeInfo>,
pub(super) dirty: DirtyState<DnsNodeMgrDirtyFlags>,
pub(super) dirty: DnsNodeMgrDirtyFlags,
}
impl DnsNodeMgr {
@@ -145,7 +145,6 @@ impl DnsNodeMgrRpc for DnsNodeMgr {
}
self.nodes.insert(id, new).await;
self.dirty.notify.notify_one();
}
false
} else {
+3 -3
View File
@@ -1,7 +1,7 @@
use crate::common::config::ConfigLoader;
use crate::common::PeerId;
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::peer_center::instance::PeerCenterPeerManagerTrait;
use crate::peers::peer_manager::PeerManager;
@@ -42,7 +42,7 @@ const DNS_PEER_TTL: Duration = Duration::from_secs(3);
#[derive(Debug, Deref)]
pub struct DnsPeerMgr {
peers: Cache<PeerId, DnsPeerInfo>,
pub(super) dirty: DirtyState<DirtyFlag>,
pub(super) dirty: DirtyFlag,
#[deref]
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> {
+45 -33
View File
@@ -131,9 +131,6 @@ pub struct DnsServer {
#[derivative(Debug = "ignore")]
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);
@@ -153,23 +150,24 @@ impl DnsServer {
Self {
mgr,
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 mut active = self.addresses.write().await;
let added = addresses.difference(&active).cloned().collect_vec();
let removed = active.difference(&addresses).cloned().collect_vec();
let added = addresses.difference(&current).cloned().collect_vec();
let removed = current.difference(&addresses).cloned().collect_vec();
if added.is_empty() && removed.is_empty() {
return;
}
*active = addresses;
*current = addresses;
// TODO
}
@@ -209,30 +207,44 @@ impl DnsServer {
pub async fn run(&self) {
let dirty = &self.mgr.dirty;
let mut runtime = None;
loop {
dirty.notify.notified().await;
if dirty.catalog.reset() {
self.catalog.replace(self.mgr.catalog()).await;
}
if dirty.addresses.reset() {
self.reload_addresses(self.mgr.iter_addresses()).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();
tokio::join!(
async {
loop {
dirty.catalog.notified().await;
if dirty.catalog.reset() {
self.catalog.replace(self.mgr.catalog()).await;
}
tokio::time::sleep(Duration::from_secs(1)).await;
}
}
tokio::time::sleep(Duration::from_secs(1)).await;
}
},
async {
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,
}
#[derive(Derivative, Debug)]
#[derive(Derivative, Debug, Deref)]
#[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 {
pub fn new(value: bool) -> Self {
Self(AtomicBool::new(value))
Self {
dirty: AtomicBool::new(value),
notify: Notify::new(),
}
}
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 {
self.0.load(Ordering::Acquire)
self.dirty.load(Ordering::Acquire)
}
pub fn reset(&self) -> bool {
self.0.swap(false, Ordering::Acquire)
self.dirty.swap(false, Ordering::Acquire)
}
}