use crate::client::{Client, Slot};
use crate::error::{Error, Result};
use crate::events::{Chan, Event, Hub};
use crate::wire::*;
use std::sync::atomic::{AtomicBool, Ordering};
use std::sync::Arc;
use std::time::Duration;
const WATCH_QUEUE: usize = 256;
pub struct Watch {
id: u64,
slot: Arc<Slot>,
epoch: u64,
chan: Arc<Chan>,
hub: Arc<Hub>,
closed: AtomicBool,
}
impl Client {
pub fn watch(&self, path: &str, recursive: bool, since: u64) -> Result<Watch> {
let chan = Arc::new(Chan::new(WATCH_QUEUE, 0));
let req = WatchRequest {
path: path.into(),
recursive,
since_sequence: since,
};
let (r, slot, epoch) = self.run_any(|c| c.call_watch(&req, chan.clone()))?;
Ok(Watch {
id: r.watch_id,
slot: slot.clone(),
epoch,
chan,
hub: self.inner.hub.clone(),
closed: AtomicBool::new(false),
})
}
}
impl Watch {
pub fn id(&self) -> u64 {
self.id
}
pub fn recv_timeout(&self, d: Duration) -> Option<Event> {
self.chan.pop(Some(d))
}
pub fn close(&self) -> Result<()> {
if self.closed.swap(true, Ordering::SeqCst) {
return Ok(());
}
self.hub.remove_watch(self.id);
self.chan.close(false);
let req = UnwatchRequest { watch_id: self.id };
match self
.slot
.run(Some(self.epoch), |c| c.call_msg::<Empty>(method::UNWATCH, &req, &[]))
{
Ok(_) | Err(Error::Io(_)) | Err(Error::Timeout(_)) => Ok(()),
Err(Error::Server { code, .. }) if code == "EBADF" => Ok(()),
Err(e) => Err(e),
}
}
}
impl Iterator for Watch {
type Item = Event;
fn next(&mut self) -> Option<Event> {
self.chan.pop(None)
}
}
impl Iterator for &Watch {
type Item = Event;
fn next(&mut self) -> Option<Event> {
self.chan.pop(None)
}
}
impl Drop for Watch {
fn drop(&mut self) {
let _ = self.close();
}
}