mirror of
				https://github.com/isar/rusqlite.git
				synced 2025-11-04 08:08:55 +08:00 
			
		
		
		
	Unlock notification
This commit is contained in:
		@@ -28,6 +28,7 @@ buildtime_bindgen = ["libsqlite3-sys/buildtime_bindgen"]
 | 
			
		||||
limits = []
 | 
			
		||||
hooks = []
 | 
			
		||||
sqlcipher = ["libsqlite3-sys/sqlcipher"]
 | 
			
		||||
unlock_notify = ["libsqlite3-sys/unlock_notify"]
 | 
			
		||||
 | 
			
		||||
[dependencies]
 | 
			
		||||
time = "0.1.0"
 | 
			
		||||
 
 | 
			
		||||
@@ -21,6 +21,8 @@ min_sqlite_version_3_6_23 = ["pkg-config", "vcpkg"]
 | 
			
		||||
min_sqlite_version_3_7_3 = ["pkg-config", "vcpkg"]
 | 
			
		||||
min_sqlite_version_3_7_4 = ["pkg-config", "vcpkg"]
 | 
			
		||||
min_sqlite_version_3_7_16 = ["pkg-config", "vcpkg"]
 | 
			
		||||
# sqlite3_unlock_notify >= 3.6.12
 | 
			
		||||
unlock_notify = []
 | 
			
		||||
 | 
			
		||||
[build-dependencies]
 | 
			
		||||
bindgen = { version = "0.32", optional = true }
 | 
			
		||||
 
 | 
			
		||||
@@ -18,8 +18,8 @@ mod build {
 | 
			
		||||
        fs::copy("sqlite3/bindgen_bundled_version.rs", out_path)
 | 
			
		||||
            .expect("Could not copy bindings to output directory");
 | 
			
		||||
 | 
			
		||||
        cc::Build::new()
 | 
			
		||||
            .file("sqlite3/sqlite3.c")
 | 
			
		||||
        let mut cfg = cc::Build::new();
 | 
			
		||||
        cfg.file("sqlite3/sqlite3.c")
 | 
			
		||||
            .flag("-DSQLITE_CORE")
 | 
			
		||||
            .flag("-DSQLITE_DEFAULT_FOREIGN_KEYS=1")
 | 
			
		||||
            .flag("-DSQLITE_ENABLE_API_ARMOR")
 | 
			
		||||
@@ -38,8 +38,11 @@ mod build {
 | 
			
		||||
            .flag("-DSQLITE_SOUNDEX")
 | 
			
		||||
            .flag("-DSQLITE_THREADSAFE=1")
 | 
			
		||||
            .flag("-DSQLITE_USE_URI")
 | 
			
		||||
            .flag("-DHAVE_USLEEP=1")
 | 
			
		||||
            .compile("libsqlite3.a");
 | 
			
		||||
            .flag("-DHAVE_USLEEP=1");
 | 
			
		||||
        if cfg!(feature = "unlock_notify") {
 | 
			
		||||
            cfg.flag("-DSQLITE_ENABLE_UNLOCK_NOTIFY");
 | 
			
		||||
        }
 | 
			
		||||
        cfg.compile("libsqlite3.a");
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -125,6 +125,8 @@ pub mod limits;
 | 
			
		||||
mod hooks;
 | 
			
		||||
#[cfg(feature = "hooks")]
 | 
			
		||||
pub use hooks::*;
 | 
			
		||||
#[cfg(feature = "unlock_notify")]
 | 
			
		||||
pub mod unlock_notify;
 | 
			
		||||
 | 
			
		||||
// Number of cached prepared statements we'll hold on to.
 | 
			
		||||
const STATEMENT_CACHE_DEFAULT_CAPACITY: usize = 16;
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										80
									
								
								src/unlock_notify.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										80
									
								
								src/unlock_notify.rs
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,80 @@
 | 
			
		||||
//! [Unlock Notification](http://sqlite.org/unlock_notify.html)
 | 
			
		||||
 | 
			
		||||
use std::sync::{Mutex, Condvar};
 | 
			
		||||
use std::os::raw::{c_char, c_int, c_void};
 | 
			
		||||
 | 
			
		||||
use ffi;
 | 
			
		||||
use InnerConnection;
 | 
			
		||||
 | 
			
		||||
struct UnlockNotification {
 | 
			
		||||
    cond: Condvar, // Condition variable to wait on
 | 
			
		||||
    mutex: Mutex<bool>, // Mutex to protect structure
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl UnlockNotification {
 | 
			
		||||
    fn new() -> UnlockNotification {
 | 
			
		||||
        UnlockNotification {
 | 
			
		||||
            cond: Condvar::new(),
 | 
			
		||||
            mutex: Mutex::new(false),
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    fn fired(&mut self) {
 | 
			
		||||
        *self.mutex.lock().unwrap() = true;
 | 
			
		||||
        self.cond.notify_one();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    fn wait(&mut self) -> bool {
 | 
			
		||||
        let mut fired = self.mutex.lock().unwrap();
 | 
			
		||||
        if !*fired {
 | 
			
		||||
            fired = self.cond.wait(fired).unwrap();
 | 
			
		||||
        }
 | 
			
		||||
        *fired
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/// This function is an unlock-notify callback
 | 
			
		||||
unsafe extern "C" fn unlock_notify_cb(ap_arg: *mut *mut c_void, n_arg: c_int) {
 | 
			
		||||
  /*int i;
 | 
			
		||||
  for(i=0; i<nArg; i++){
 | 
			
		||||
    UnlockNotification *p = (UnlockNotification *)apArg[i];
 | 
			
		||||
    pthread_mutex_lock(&p->mutex);
 | 
			
		||||
    p->fired = 1;
 | 
			
		||||
    pthread_cond_signal(&p->cond);
 | 
			
		||||
    pthread_mutex_unlock(&p->mutex);
 | 
			
		||||
  }*/
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl InnerConnection {
 | 
			
		||||
    fn blocking_prepare(&mut self,
 | 
			
		||||
            z_sql: *const c_char,
 | 
			
		||||
            n_byte: c_int,
 | 
			
		||||
            pp_stmt: *mut *mut ffi::sqlite3_stmt,
 | 
			
		||||
            pz_tail: *mut *const c_char) -> c_int {
 | 
			
		||||
        let mut rc;
 | 
			
		||||
        loop {
 | 
			
		||||
            rc = unsafe {
 | 
			
		||||
                ffi::sqlite3_prepare_v2(self.db, z_sql, n_byte, pp_stmt, pz_tail)
 | 
			
		||||
            };
 | 
			
		||||
            if rc != ffi::SQLITE_LOCKED {
 | 
			
		||||
                break;
 | 
			
		||||
            }
 | 
			
		||||
            rc = self.wait_for_unlock_notify();
 | 
			
		||||
            if rc != ffi::SQLITE_OK {
 | 
			
		||||
                break;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        rc
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    fn wait_for_unlock_notify(&mut self) -> c_int {
 | 
			
		||||
        let mut un = UnlockNotification::new();
 | 
			
		||||
        /* Register for an unlock-notify callback. */
 | 
			
		||||
        let rc = unsafe { ffi::sqlite3_unlock_notify(self.db, Some(unlock_notify_cb), &mut un as *mut UnlockNotification as *mut c_void) };
 | 
			
		||||
        debug_assert!(rc == ffi::SQLITE_LOCKED || rc == ffi::SQLITE_OK);
 | 
			
		||||
        if rc == ffi::SQLITE_OK {
 | 
			
		||||
            un.wait();
 | 
			
		||||
        }
 | 
			
		||||
        rc
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
		Reference in New Issue
	
	Block a user