1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
use chrono::prelude::*;
use crate::prelude::*;
use crate::bucket::*;
use log::{debug, warn};
use std::collections::BTreeMap;
use std::path::{Path, PathBuf};

/// A Database consists of multiple buckets; each indexed by a Date.
pub struct Db {
    buckets: BTreeMap<Date<Local>, Bucket<Checked>>,
    pub root: PathBuf,
}

impl Db {
    pub fn new<P: AsRef<Path>>(root: P) -> Db {
        Db {
            buckets: BTreeMap::new(),
            root: root.as_ref().to_path_buf(),
        }
    }

    pub fn open<P: AsRef<Path>>(root: P) -> Result<Db> {
        use std::fs::*;
        let mut db = Db::new(root.as_ref());
        let entries = read_dir(root.as_ref()).expect("root is not a directory!");
        for entry in entries {
            let entry = entry?;
            let path = entry.path();
            if !path.is_dir() {
                let bucket = Bucket::open(&path)?;
                match bucket.check_headers() {
                    Ok(bucket) => {
                        let datetime = Local.timestamp(bucket.header.timestamp, 0);
                        db.buckets.insert(datetime.date(), bucket);
                    },
                    Err(e) => {
                        warn!("could not load bucket from file {:?} with error: {}", &path, e);
                    }
                }
            }
        }
        Ok(db)
    }

    pub fn query(&mut self, hash: HashedKey, start_date: Date<Local>, end_date: Date<Local>) -> Result<Vec<Value>> {
        let range = self.buckets.range_mut(start_date ..= end_date);
        let mut v = Vec::new();

        for (date, bucket) in range {
            debug!("querying bucket for date: {} with hash: {}", date, hash);
            match bucket.get(hash)? {
                Some(set) => {
                    for e in set {
                        v.push(e);
                    }
                },
                None => ()
            };
        }
        Ok(v)
    }

    pub fn len(&self) -> usize {
        self.buckets.len()
    }
}