Skip to content
Snippets Groups Projects

Draft: #7 alternative kv db

Open Philipp Rothmann requested to merge #7_alternative_kv_db into master
Files
15
+ 52
37
use crate::domain::Dname;
use std::path::PathBuf;
use chrono::{Utc, DateTime};
use chrono::{Utc, DateTime, Duration};
use std::net::{Ipv4Addr, Ipv6Addr};
use log::{info, warn, error};
use std::sync::{Mutex, Arc};
use rocksdb;
use serde::{Serialize, Deserialize};
use serde_json as json;
use crate::ffdyndns::Token;
use crate::sha256;
use rocksdb::IteratorMode;
pub mod rocksdb;
pub mod redis;
#[derive(Clone)]
pub struct Database {
conn: Arc<Mutex<rocksdb::DB>>,
}
/// a database abstraction
pub trait Database: Sync {
fn get(&self, key: String) -> Option<Vec<u8>>;
fn set(&self, key: String, val: Vec<u8>) -> Result<(),()>;
impl Database {
pub fn new(path: PathBuf) -> Self {
let conn = rocksdb::DB::open_default(path).unwrap();
Database { conn: Arc::new(Mutex::new(conn)) }
}
fn delete(&self, key: String);
// pub fn get_all_domains(&self) -> Vec<Domain> {
// let db = self.conn.lock().unwrap();
// let mut stmt: sqlite::Statement = db.prepare("SELECT * FROM domains").unwrap();
// stmt.query_map(
// params![],
// |row| Ok(Domain::from_row(row))
// ).unwrap().map(|x| x.unwrap()).collect()
// }
// the following methods are provided if the above are implemented
pub fn insert_new_domain(&self, d: &Domain) {
self.conn.lock().unwrap().put(
fn insert_new_domain(&self, d: &Domain) {
self.set(
sha256!(&d.domainname),
json::to_vec(&d).unwrap()
).unwrap();
}
pub fn get_domain(&self, domain: &String) -> Option<Domain> {
let r = self.conn.lock().unwrap().get(sha256!(domain)).unwrap();
fn get_domain(&self, domain: &String) -> Option<Domain> {
let r = self.get(sha256!(domain));
r.map(|x| json::from_slice(&x).unwrap())
}
pub fn remove_domain(&self, domain: String) {
self.conn.lock().unwrap().delete(domain).unwrap();
fn remove_domain(&self, domain: &String) {
self.delete(sha256!(domain));
}
pub fn update_lastupdate(&self, domain: &String, lastupdate: DateTime<Utc>) {
fn update_lastupdate(&self, domain: &String, lastupdate: DateTime<Utc>) {
let mut d = self.get_domain(domain).unwrap();
d.lastupdate = Some(lastupdate);
d.lastupdate = lastupdate;
self.conn.lock().unwrap().put(
sha256!(domain),
@@ -62,7 +53,17 @@ impl Database {
).unwrap();
}
pub fn update_ipv4(&self, domain: &String, addr: Ipv4Addr) {
pub fn update_validity(&self, domain: &String, valid_until: DateTime<Utc>) {
let mut d = self.get_domain(domain).unwrap();
d.valid_until = valid_until;
self.set(
sha256!(domain),
json::to_vec(&d).unwrap()
).unwrap();
}
fn update_ipv4(&self, domain: &String, addr: Ipv4Addr) {
if !self.exists(domain) {
warn!("tried to update nonexistend domain: {}", domain);
return
@@ -71,25 +72,36 @@ impl Database {
let mut d = self.get_domain(domain).unwrap();
d.ipv4 = Some(addr);
self.conn.lock().unwrap().put(
self.set(
sha256!(domain),
json::to_vec(&d).unwrap()
).unwrap();
}
pub fn update_ipv6(&self, domain: &String, addr: Ipv6Addr) {
fn update_ipv6(&self, domain: &String, addr: Ipv6Addr) {
let mut d = self.get_domain(domain).unwrap();
d.ipv6 = Some(addr);
self.conn.lock().unwrap().put(
self.set(
sha256!(domain),
json::to_vec(&d).unwrap()
).unwrap();
}
pub fn exists(&self, d: &String) -> bool {
fn exists(&self, d: &String) -> bool {
self.get_domain(d).is_some()
}
pub fn get_all(&self) -> Vec<Domain> {
self.conn
.lock()
.unwrap()
.iterator(IteratorMode::Start)
.map(|(_, v)| {
json::from_slice(&*v).unwrap()
})
.collect()
}
}
@@ -97,7 +109,8 @@ impl Database {
pub struct Domain {
pub domainname: String,
pub token: Token,
pub lastupdate: Option<DateTime<Utc>>,
pub lastupdate: DateTime<Utc>,
pub valid_until: DateTime<Utc>,
pub ipv4: Option<Ipv4Addr>,
pub ipv6: Option<Ipv6Addr>,
}
@@ -115,22 +128,24 @@ impl Domain {
}
impl Domain {
pub fn new_with_token(domain: Dname, token: String) -> Self {
pub fn new_with_token(domain: &Dname, token: String, validity: Duration) -> Self {
Self {
domainname: domain.to_string(),
token: token,
lastupdate: None,
lastupdate: Utc::now(),
valid_until: Utc::now() + validity,
ipv4: None,
ipv6: None
}
}
/// creates a new Domain object and generates a random token
pub fn new(domain: String) -> Self {
pub fn new(domain: String, validity: Duration) -> Self {
Self {
domainname: domain,
token: crate::ffdyndns::generate_token(),
lastupdate: None,
lastupdate: Utc::now(),
valid_until: Utc::now() + validity,
ipv4: None,
ipv6: None
}
Loading