1use crate::client::{Client, Slot};
5use crate::error::{Error, Result};
6use crate::events::{Chan, Event, Hub};
7use crate::wire::*;
8use std::sync::atomic::{AtomicBool, Ordering};
9use std::sync::Arc;
10use std::time::Duration;
11
12const WATCH_QUEUE: usize = 256;
14
15pub struct Watch {
25 id: u64,
26 slot: Arc<Slot>,
27 epoch: u64,
28 chan: Arc<Chan>,
29 hub: Arc<Hub>,
30 closed: AtomicBool,
31}
32
33impl Client {
34 pub fn watch(&self, path: &str, recursive: bool, since: u64) -> Result<Watch> {
37 let chan = Arc::new(Chan::new(WATCH_QUEUE, 0));
38 let req = WatchRequest {
39 path: path.into(),
40 recursive,
41 since_sequence: since,
42 };
43 let (r, slot, epoch) = self.run_any(|c| c.call_watch(&req, chan.clone()))?;
44 Ok(Watch {
45 id: r.watch_id,
46 slot: slot.clone(),
47 epoch,
48 chan,
49 hub: self.inner.hub.clone(),
50 closed: AtomicBool::new(false),
51 })
52 }
53}
54
55impl Watch {
56 pub fn id(&self) -> u64 {
58 self.id
59 }
60
61 pub fn recv_timeout(&self, d: Duration) -> Option<Event> {
63 self.chan.pop(Some(d))
64 }
65
66 pub fn close(&self) -> Result<()> {
70 if self.closed.swap(true, Ordering::SeqCst) {
71 return Ok(());
72 }
73 self.hub.remove_watch(self.id);
74 self.chan.close(false);
75 let req = UnwatchRequest { watch_id: self.id };
76 match self
77 .slot
78 .run(Some(self.epoch), |c| c.call_msg::<Empty>(method::UNWATCH, &req, &[]))
79 {
80 Ok(_) | Err(Error::Io(_)) | Err(Error::Timeout(_)) => Ok(()),
81 Err(Error::Server { code, .. }) if code == "EBADF" => Ok(()),
82 Err(e) => Err(e),
83 }
84 }
85}
86
87impl Iterator for Watch {
88 type Item = Event;
89
90 fn next(&mut self) -> Option<Event> {
91 self.chan.pop(None)
92 }
93}
94
95impl Iterator for &Watch {
96 type Item = Event;
97
98 fn next(&mut self) -> Option<Event> {
99 self.chan.pop(None)
100 }
101}
102
103impl Drop for Watch {
104 fn drop(&mut self) {
105 let _ = self.close();
106 }
107}