Skip to content

Commit

Permalink
- release 0.1.64
Browse files Browse the repository at this point in the history
- test cases added for schema.rs
- added config file
- code refactoring
  • Loading branch information
julfikar committed Jun 13, 2023
1 parent 1ef6198 commit 9bc0ce3
Show file tree
Hide file tree
Showing 13 changed files with 460 additions and 143 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
/target
/Cargo.lock
/dbs/**
flinch.toml
13 changes: 7 additions & 6 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "flinch"
version = "0.1.63"
version = "0.1.64"
edition = "2021"
authors = ["Mohammad Julfikar <[email protected]>", "Mohammad Julfikar <[email protected]>"]
categories = ["parser-implementations","caching","database-implementations"]
Expand All @@ -17,21 +17,22 @@ repository = "https://github.com/mjm918/flinch"

[dependencies]
anyhow = "1.0.70"
bincode = "2.0.0-rc.3"
chrono = "0.4.24"
crossbeam-queue = "0.3.8"
dashmap = { version="5.4.0", features=["rayon", "serde"] }
bincode = "2.0.0-rc.3"
flql = "0.2.6"
futures = "0.3.28"
log = "0.4.17"
lazy_static = "1.4.0"
log = "0.4.17"
rayon = "1.7.0"
regex = "1.8.4"
serde = { version="1.0.160", features=["derive"] }
serde_json = "1.0.95"
sled = "0.34.7"
simple_logger = { version="4.1.0", features = ["colors", "threads", "timestamps", "stderr"] }
size = "0.4.1"
sha256 = "1.1.3"
simplelog = { version = "^0.12.1", features = ["paris"] }
size = "0.4.1"
sled = "0.34.7"
thiserror = "1.0.40"
tokio = { version="1.27.0", features=["full"] }
toml = "0.7.4"
Expand Down
62 changes: 46 additions & 16 deletions src/authenticate.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
use dashmap::DashMap;
use log::warn;
use log::{trace, warn};
use sha256::digest as sha_hash;
use sled::Db;

use crate::errors::DbError;
use crate::headers::{DbName, DbUser, FlinchCnf, PermissionTypes, SessionId, UserName};
use crate::headers::{DbName, DbUser, FlinchCnf, SessionId, UserName};
use crate::persistent::Persistent;
use crate::pri_headers::PermissionTypes;
use crate::utils::{DBUSER_PREFIX, uuid};

pub struct Authenticate {
Expand All @@ -21,8 +22,10 @@ impl Authenticate {
users: Default::default(),
session: Default::default(),
};

let users = slf.storage.prefix(format!("{}", &DBUSER_PREFIX));
for (_, user) in users {
for (key, user) in users {
trace!("{} user from persistent {:?}",key,&user);
let json = serde_json::from_str::<DbUser>(user.as_str());
if json.is_err() {
warn!("user info from persistent storage failed to parse {}", user);
Expand All @@ -33,8 +36,8 @@ impl Authenticate {
}
let config = cfg.clone();
let root = DbUser {
name: config.root,
pw: config.pw,
name: config.login.username,
pw: config.login.password,
db: "*".to_string(),
create: true,
drop: true,
Expand All @@ -43,7 +46,7 @@ impl Authenticate {
permit: true,
flush: true,
};
slf.add_user_with_hash(root);
let _ = slf.add_user_with_hash(root);
slf
}

Expand All @@ -68,41 +71,55 @@ impl Authenticate {
}

pub fn add_user(&self, user: DbUser) {
trace!("adding user {:?} to memory",&user);
if let Some(mut col) = self.users.get_mut(user.db.as_str()) {
let users = col.value_mut();
let user_name = user.name.to_owned();
users.insert(user_name, user);
} else {
let db = user.db.clone();
let mut user_map = DashMap::new();
let user_map = DashMap::new();
user_map.insert(user.name.to_owned(), user);
self.users.insert(db, user_map);
}
}

pub fn add_user_with_hash(&self, user: DbUser) {
pub fn add_user_with_hash(&self, user: DbUser) -> anyhow::Result<(), DbError> {
let mut user = user;
user.pw = sha_hash(user.pw);

for map in &self.users.get(user.db.as_str()) {
let user_map = map.value();
for u in user_map {
let username = u.key();
if username.eq(user.name.as_str()) {
return Err(DbError::UserExists(user.name.to_owned()));
}
}
}

self.add_user(user.clone());
self.storage.put_any(format!("{}{}", &DBUSER_PREFIX, uuid()), user);
self.storage.put_any(format!("{}{}{}", &DBUSER_PREFIX, user.name.as_str(), uuid()), user);
Ok(())
}

pub fn drop_user(&self, db: &str, name: &str) -> anyhow::Result<(), DbError> {
trace!("removing user {:?} {:?}", db, name);
if let Some(mut col) = self.users.get_mut(db) {
let user = col.value_mut();
return if let Some(_) = user.get_mut(name) {
user.remove(name);
self.storage.remove(format!("{}{}", &DBUSER_PREFIX, name)).expect("removed user from persistent");
Ok(())
} else {
Err(DbError::NoSuchUser(name.to_owned()))
};
if user.get_mut(name).is_none() {
return Err(DbError::NoSuchUser(name.to_owned()));
}
user.remove(name);
self.storage.remove_by_prefix(format!("{}{}", &DBUSER_PREFIX, name));

return Ok(());
}
return Err(DbError::DbNotExists(db.to_string()));
}

pub fn chk_permission(&self, session_id: SessionId, perm_type: PermissionTypes) -> bool {
trace!("permission check SessionID {:?} permission type {:?}",&session_id, &perm_type);
if let Some(record) = self.session.get(session_id.as_str()) {
let user = record.value();
return match perm_type {
Expand All @@ -124,4 +141,17 @@ impl Authenticate {
}
None
}

pub fn drop_by_db(&self, db: &str) {
trace!("removing database from auth");
let _ = self.users.remove(format!("{}", &db).as_str());
let mut session_id = format!("");
for session in &self.session {
let user = session.value();
if user.db.eq(db) {
session_id = format!("{}", session.key());
}
}
self.session.remove(session_id.as_str());
}
}
60 changes: 19 additions & 41 deletions src/database.rs
Original file line number Diff line number Diff line change
@@ -1,27 +1,19 @@
#![feature(integer_atomics, const_fn_trait_bound)]

use std::alloc::System;
use std::sync::Arc;

use anyhow::Result;
use dashmap::DashMap;
use dashmap::mapref::one::Ref;
use log::{error, info, trace, warn};
use log::{info, warn};
use serde::{Deserialize, Serialize};
use serde::de::DeserializeOwned;
use simple_logger::SimpleLogger;
use size::{Base, Size};
use sled::Db;

use crate::collection::Collection;
use crate::doc_trait::{Document, ViewConfig};
use crate::errors::CollectionError;
use crate::persistent::Persistent;
use crate::pri_headers::INTERNAL_COL;
use crate::utils::{COL_PREFIX, database_path, get_col_name, prefix_col_name};
use crate::zalloc::Zalloc;

#[global_allocator]
static ALLOCMEASURE: Zalloc<System> = Zalloc::new(System);

/// `CollectionOptions` is used while creating a collection
#[derive(Serialize, Deserialize, Clone, Debug)]
Expand All @@ -39,6 +31,7 @@ pub struct Database<D> where D: Document + 'static {
storage: Arc<DashMap<String, Arc<Collection<D>>>>,
persist: Db,
internal_tree: Persistent,
db_path: String,
}

impl<D> Database<D>
Expand All @@ -59,22 +52,11 @@ impl<D> Database<D>
}

async fn boot(name: Option<String>) -> Self {
// Reset allocation count
ALLOCMEASURE.reset();
// Set database logger
let logger = SimpleLogger::new()
.with_module_level("sled", log::LevelFilter::Info)
.with_colors(true)
.with_level(log::LevelFilter::Debug)
.init();
if logger.is_ok() {
logger.unwrap();
} else {
error!("{:?}",logger.err().unwrap());
}
let storage = DashMap::new();
let persist = sled::open(database_path(name)).unwrap();
let internal_tree = Persistent::open(&persist, "__flinch_internal");
let db_path = database_path(name);
let persist = sled::open(db_path.as_str()).unwrap();

let internal_tree = Persistent::open(&persist, INTERNAL_COL);

let existing = internal_tree.prefix(format!("{}", COL_PREFIX));
for exi in existing {
Expand All @@ -94,21 +76,11 @@ impl<D> Database<D>
storage: Arc::new(storage),
persist,
internal_tree,
db_path,
};
instance.watch_memory();
instance
}

/// watch current memory usage
fn watch_memory(&self) {
std::thread::spawn(move || {
loop {
trace!("memory used: {}", Size::from_bytes(ALLOCMEASURE.get()).format().with_base(Base::Base10));
std::thread::sleep(std::time::Duration::from_secs(1));
}
});
}

/// `ls` list out all the collections in the database
pub fn ls(&self) -> Vec<String> {
self.storage.iter().map(|kv| kv.key().to_string()).collect::<Vec<String>>()
Expand Down Expand Up @@ -139,12 +111,14 @@ impl<D> Database<D>

/// `drop` drops a collection by `name`
pub async fn drop(&self, name: &str) -> Result<(), CollectionError> {
if let Err(err) = self.exi(name) {
return Err(err);
if let None = self.storage.get(name) {
return Err(CollectionError::NoSuchCollection);
}
{
let col = self.using(name);
let col = col.unwrap();
col.value().empty().await;
}
let col = self.using(name);
let col = col.unwrap();
col.value().empty().await;
self.storage.remove(name);
self.internal_tree.remove(prefix_col_name(name)).expect("remove from local storage");
self.persist.drop_tree(name).expect("drop collection from local storage");
Expand All @@ -154,6 +128,10 @@ impl<D> Database<D>
Ok(())
}

pub fn delete_disk_dir(&self) -> std::io::Result<()> {
std::fs::remove_dir_all(self.db_path.as_str())
}

fn exi(&self, name: &str) -> Result<(), CollectionError> {
if let Some(_) = self.storage.get(name) {
return Err(CollectionError::DuplicateCollection);
Expand Down
6 changes: 6 additions & 0 deletions src/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -89,4 +89,10 @@ pub enum DbError {
InvalidPassword,
#[error("user does not permission")]
UserNoPermission,
#[error("naming convention for `{0}` rejected. char length must be in between `{1}`-`{2}`")]
InvalidNamingConventionLen(String, String, String),
#[error("minimum password length required: `{0}` characters")]
MinPwLen(String),
#[error("database name malformed")]
DbNameMalformed,
}
31 changes: 20 additions & 11 deletions src/headers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -107,17 +107,26 @@ pub struct QueryResult {

#[derive(Serialize, Deserialize, Clone, Debug)]
pub struct FlinchCnf {
pub root: String,
pub pw: String,
pub data_dir: String,
pub login: FlinchCnfLogin,
pub dir: FlinchCnfDir,
pub enable: FlinchCnfEnable,
}

#[derive(Serialize, Deserialize, Clone, Debug, PartialEq)]
pub enum PermissionTypes {
AssignUser,
CreateCollection,
DropCollection,
Read,
Write,
Flush,
#[derive(Serialize, Deserialize, Clone, Debug)]
pub struct FlinchCnfLogin {
pub username: String,
pub password: String,
}

#[derive(Serialize, Deserialize, Clone, Debug)]
pub struct FlinchCnfDir {
pub data: String,
pub log: String,
pub mem_watch: String,
}

#[derive(Serialize, Deserialize, Clone, Debug)]
pub struct FlinchCnfEnable {
pub log: bool,
pub mem_watch: bool,
}
21 changes: 11 additions & 10 deletions src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,23 +1,24 @@
mod index_hash;
mod index_fields;
mod range;
mod authenticate;
mod clips;
mod errors;
mod watchman;
mod pub_sub;
mod events;
mod index_fields;
mod index_hash;
mod notif_type;
mod utils;
mod persistent;
mod pri_headers;
mod pub_sub;
mod range;
mod ttl;
mod events;
mod utils;
mod watchman;
mod zalloc;
mod authenticate;

pub mod doc_trait;
pub mod collection;
pub mod database;
pub mod headers;
pub mod doc_trait;
pub mod doc;
pub mod headers;
pub mod query;
pub mod schemas;

11 changes: 11 additions & 0 deletions src/persistent.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,17 @@ impl Persistent {
.expect(format!("inserting {} into local storage", &k).as_str());
}

pub fn remove_by_prefix(&self, prefix: String) -> Vec<sled::Result<Option<IVec>>> {
let mut res = vec![];
let prefix_data = self.prefix(prefix);
for (key, _) in prefix_data {
res.push(
self.remove(key)
);
}
res
}

pub fn remove(&self, k: String) -> sled::Result<Option<IVec>> {
trace!("{} - key removed from storage",&k);
self.tree.remove(k)
Expand Down
Loading

0 comments on commit 9bc0ce3

Please sign in to comment.