Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

implement graph #16

Open
wants to merge 21 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 8 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions build.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,14 @@
/*
* Copyright FalkorDB Ltd. 2023 - present
* Licensed under the Server Side Public License v1 (SSPLv1).
*/

use std::env;

fn main() {
println!("cargo:rerun-if-changed=build.rs");
println!("cargo:rerun-if-env-changed=BINROOT");
println!("cargo:rerun-if-env-changed=CLANG");

let bin_root = env::var("BINROOT");
if let Ok(bin_root) = bin_root {
Expand Down
44 changes: 44 additions & 0 deletions src/binding/cmutex.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
/*
* Copyright FalkorDB Ltd. 2023 - present
* Licensed under the Server Side Public License v1 (SSPLv1).
*/

use std::{cell::UnsafeCell, mem::MaybeUninit, ptr::null_mut};

use libc::pthread_mutex_t;

/// Wrap C mutex as we can't use Rust Mutex.
/// Used to lock the matrix only when we apply pending changes.
pub struct CMutex {
mutex: UnsafeCell<pthread_mutex_t>,
}

impl CMutex {
pub fn new() -> Self {
unsafe {
let mut mutex = MaybeUninit::uninit();
libc::pthread_mutex_init(mutex.as_mut_ptr(), null_mut());
Self {
mutex: UnsafeCell::new(mutex.assume_init()),
}
}
}

pub fn lock(&self) {
unsafe {
libc::pthread_mutex_lock(self.mutex.get());
}
}

pub fn unlock(&self) {
unsafe {
libc::pthread_mutex_unlock(self.mutex.get());
}
}
}

impl Drop for CMutex {
fn drop(&mut self) {
unsafe { libc::pthread_mutex_destroy(self.mutex.get()) };
}
}
53 changes: 53 additions & 0 deletions src/binding/crwlock.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
/*
* Copyright FalkorDB Ltd. 2023 - present
* Licensed under the Server Side Public License v1 (SSPLv1).
*/

use std::ptr::null_mut;

use libc::{pthread_rwlock_t, PTHREAD_RWLOCK_INITIALIZER};

/// Wrap C rwlock as we can't use Rust RWLock.
/// Used to lock the graph.
pub struct CRWLock {
rwlock: Box<pthread_rwlock_t>,
}

impl CRWLock {
pub fn new() -> Self {
let mut res = CRWLock {
rwlock: Box::new(PTHREAD_RWLOCK_INITIALIZER),
};
unsafe {
libc::pthread_rwlock_init(res.rwlock.as_mut(), null_mut());
}
res
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Add error handling for pthread_rwlock_init.

The initialization of the rwlock looks correct, but there's no error handling for pthread_rwlock_init. This function can fail in certain conditions (e.g., insufficient memory).

Consider adding error handling:

pub fn new() -> Result<Self, std::io::Error> {
    let mut rwlock = Box::new(PTHREAD_RWLOCK_INITIALIZER);
    let result = unsafe {
        libc::pthread_rwlock_init(rwlock.as_mut(), null_mut())
    };
    if result != 0 {
        Err(std::io::Error::last_os_error())
    } else {
        Ok(CRWLock { rwlock })
    }
}

This change would propagate any initialization errors to the caller.


pub fn acquire_read(&mut self) {
unsafe {
let res = libc::pthread_rwlock_rdlock(self.rwlock.as_mut());
debug_assert!(res == 0, "pthread_rwlock_rdlock failed");
}
}

pub fn acquire_write(&mut self) {
unsafe {
let res = libc::pthread_rwlock_wrlock(self.rwlock.as_mut());
debug_assert!(res == 0, "pthread_rwlock_wrlock failed");
}
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Improve error handling for acquire_write.

Similar to acquire_read, this method should handle errors properly and propagate them to the caller. The use of debug_assert! only checks in debug builds.

Suggested improvement:

pub fn acquire_write(&mut self) -> Result<(), std::io::Error> {
    let result = unsafe { libc::pthread_rwlock_wrlock(self.rwlock.as_mut()) };
    if result != 0 {
        Err(std::io::Error::from_raw_os_error(result))
    } else {
        Ok(())
    }
}

This change ensures that any errors during lock acquisition are properly handled and communicated to the caller.


pub fn release(&mut self) {
unsafe {
let res = libc::pthread_rwlock_unlock(self.rwlock.as_mut());
debug_assert!(res == 0, "pthread_rwlock_unlock failed");
}
}
}

impl Drop for CRWLock {
fn drop(&mut self) {
unsafe { libc::pthread_rwlock_destroy(self.rwlock.as_mut()) };
}
}
Loading
Loading