1use std::io;
2use std::sync::{Arc, Mutex};
3
4use rotor::GenericScope;
5
6use {Query, Resolver, CacheEntry, Request, TimeEntry};
7
8quick_error! {
9 #[derive(Debug)]
15 pub enum QueryError {
16 TruncatedPacket {
19 description("query results in packet truncation")
20 }
21 Net(err: io::Error) {
22 description(err.description())
23 display("{}", err)
24 cause(err)
25 from()
26 }
27 }
28}
29
30impl Resolver {
31 pub fn query<S>(&self, query: Query, scope: &mut GenericScope)
32 -> Result<Arc<Mutex<Option<Arc<CacheEntry>>>>, QueryError>
33 where S: GenericScope
34 {
35 let ref mut res = *self.0.lock().unwrap();
36 if let Some(cache) = res.cache.get(&query).map(|x| x.clone()) {
37 if scope.now() > cache.expire {
38 res.cache.remove(&query);
39 } else {
40 scope.notifier().wakeup().unwrap();
43 return Ok(Arc::new(Mutex::new(Some(cache.clone()))));
44 }
45 }
46 let server = 0;
48 let id = try!(res.send_request(&query, server));
49
50 let result = Arc::new(Mutex::new(None));
51 let deadline = scope.now() + res.config.timeout;
52 res.running.insert(id, Request {
53 id: id,
54 query: query,
55 nameserver_index: server,
56 attempts: 1,
57 server: res.config.nameservers[server],
58 deadline: deadline,
59 notifiers: vec![(result.clone(), scope.notifier())],
60 });
61 res.timeouts.push(TimeEntry(deadline, id));
62 res.notifier.wakeup().unwrap(); Ok(result)
64 }
65}