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
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
|
use std::sync::Mutex;
use camino::Utf8PathBuf;
use rusqlite::{params, Connection, OptionalExtension};
use time::OffsetDateTime;
use crate::gatherer::Meminfo;
pub struct Database {
db_path: Utf8PathBuf,
conn: Mutex<Connection>,
}
impl Database {
pub fn new(db_path: Utf8PathBuf) -> Self {
Self {
conn: Mutex::new(Connection::open(&db_path).unwrap()),
db_path,
}
}
pub fn create_tables(&self) {
let conn = self.conn.lock().unwrap();
conn.execute(CREATE_TABLE_HOSTMEM, params![]).unwrap();
conn.execute(CREATE_TABLE_HOSTNET, params![]).unwrap();
}
pub fn insert_host_meminfo(&self, meminfo: Meminfo) {
let conn = self.conn.lock().unwrap();
conn.execute(
"INSERT INTO stats_hostmem(total_kb, available_kb) VALUES (?1, ?2)",
params![meminfo.total, meminfo.avaialable],
)
.unwrap();
}
pub fn get_last_host_meminfo(&self) -> DbMeminfo {
let conn = self.conn.lock().unwrap();
conn.query_row(
"SELECT * FROM stats_hostmem ORDER BY stamp DESC LIMIT 1",
[],
|row| {
let (stamp, total_kb, available_kb) = row.try_into().unwrap();
Ok(DbMeminfo {
stamp,
total_kb,
available_kb,
})
},
)
.optional()
.unwrap()
.unwrap()
}
pub fn get_last_n_host_meminfo(&self, count: usize) -> Vec<DbMeminfo> {
let conn = self.conn.lock().unwrap();
let mut stmt = conn
.prepare("SELECT * FROM stats_hostmem ORDER BY stamp DESC LIMIT ?1")
.unwrap();
stmt.query_map(params![count], |row| {
Ok(DbMeminfo {
stamp: row.get(0)?,
total_kb: row.get(1)?,
available_kb: row.get(2)?,
})
})
.unwrap()
.map(|r| r.unwrap())
.collect()
}
pub fn get_date_bound_n_host_meminfo(
&self,
since: OffsetDateTime,
until: OffsetDateTime,
count: usize,
) -> Vec<DbMeminfo> {
let conn = self.conn.lock().unwrap();
let mut stmt = conn
.prepare("SELECT * FROM stats_hostmem WHERE stamp > ?1 AND stamp < ?2 ORDER BY stamp DESC LIMIT ?3")
.unwrap();
stmt.query_map(params![since, until, count], |row| {
Ok(DbMeminfo {
stamp: row.get(0)?,
total_kb: row.get(1)?,
available_kb: row.get(2)?,
})
})
.unwrap()
.map(|r| r.unwrap())
.collect()
}
pub fn insert_hostnet(&self, span_sec: usize, rx_delta: usize, tx_delta: usize) {
let conn = self.conn.lock().unwrap();
conn.execute(
"INSERT INTO stats_hostnet(span_sec, rx_delta, tx_delta) VALUES (?1, ?2, ?3)",
params![span_sec, rx_delta, tx_delta],
)
.unwrap();
}
pub fn get_last_n_hostnet(&self, count: usize) -> Vec<DbNetinfo> {
let conn = self.conn.lock().unwrap();
let mut stmt = conn
.prepare("SELECT * FROM stats_hostnet ORDER BY stamp DESC LIMIT ?1")
.unwrap();
stmt.query_map(params![count], |row| {
Ok(DbNetinfo {
stamp: row.get(0)?,
span_sec: row.get(1)?,
rx_delta: row.get(2)?,
tx_delta: row.get(3)?,
})
})
.unwrap()
.map(|r| r.unwrap())
.collect()
}
}
pub const CREATE_TABLE_HOSTMEM: &'static str = "\
CREATE TABLE IF NOT EXISTS stats_hostmem (
stamp TEXT NOT NULL DEFAULT CURRENT_TIMESTAMP,
total_kb INTEGER NOT NULL,
available_kb INTEGER NOT NULL
);";
pub const CREATE_TABLE_HOSTNET: &'static str = "\
CREATE TABLE IF NOT EXISTS stats_hostnet(
stamp TEXT NOT NULL DEFAULT CURRENT_TIMESTAMP,
span_sec INTEGER NOT NULL,
rx_delta INTEGER NOT NULL,
tx_delta INTEGER NOT NULL
);";
pub struct DbMeminfo {
pub stamp: OffsetDateTime,
pub total_kb: usize,
pub available_kb: usize,
}
impl DbMeminfo {
pub fn usage(&self) -> usize {
self.total_kb - self.available_kb
}
}
#[derive(Copy, Clone, Debug)]
pub struct DbNetinfo {
pub stamp: OffsetDateTime,
pub span_sec: usize,
pub rx_delta: usize,
pub tx_delta: usize,
}
impl DbNetinfo {
pub fn rx_bytes_per_sec(&self) -> f32 {
self.rx_delta as f32 / self.span_sec as f32
}
pub fn tx_bytes_per_sec(&self) -> f32 {
self.tx_delta as f32 / self.span_sec as f32
}
}
|