From 78b480a41f0da0c1804bdbec0fed704d3e396957 Mon Sep 17 00:00:00 2001 From: Pavel Kuzmin Date: Sat, 8 Jun 2024 21:22:34 +0300 Subject: [PATCH] add lock --- .github/workflows/build.yml | 5 ++ Dockerfile | 2 +- src/lib.rs | 21 ++++--- src/transaction.rs | 117 ++++++++++++++++++++++-------------- src/write_batch.rs | 2 +- 5 files changed, 91 insertions(+), 56 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 950ac8b..cbf725f 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -64,6 +64,11 @@ jobs: rustup default stable rustup target add x86_64-unknown-linux-gnu + - name: Install Dependencies + run: | + sudo apt-get update + sudo apt-get install -y libc6-dev + - name: Run Tests run: | cargo test --target x86_64-unknown-linux-gnu diff --git a/Dockerfile b/Dockerfile index 2e99be7..e99dcaf 100644 --- a/Dockerfile +++ b/Dockerfile @@ -9,7 +9,7 @@ FROM php:${FROM_PHP}-fpm-${FROM_DISTRO} ENV CARGO_NET_GIT_FETCH_WITH_CLI=true -RUN apt-get update && apt install curl build-essential gcc libclang-dev make openssl libssl-dev git -y +RUN apt-get update && apt install curl build-essential gcc libclang-dev make openssl libssl-dev git libc6-dev -y RUN curl https://sh.rustup.rs -sSf | bash -s -- -y diff --git a/src/lib.rs b/src/lib.rs index 0456d27..576ea1b 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,7 +1,6 @@ #![cfg_attr(all(windows, target_arch = "x86_64"), feature(abi_vectorcall))] #![no_main] - mod backup; mod transaction; mod write_batch; @@ -11,18 +10,18 @@ use ext_php_rs::error::Error; use ext_php_rs::prelude::*; use ext_php_rs::types::{ZendHashTable, Zval}; use ext_php_rs::zend::{ce, ModuleEntry}; +use ext_php_rs::{info_table_end, info_table_row, info_table_start}; +use fs2::FileExt; use json_patch::Patch; use rust_rocksdb::{ ColumnFamilyDescriptor, DBWithThreadMode, MergeOperands, Options, SingleThreaded, DB, }; use serde_json::{from_value, Value}; use std::collections::HashMap; -use std::time::Duration; -use ext_php_rs::{info_table_end, info_table_row, info_table_start}; use std::fs::File; use std::path::Path; use std::thread; -use fs2::FileExt; +use std::time::Duration; use crate::backup::RocksDBBackup; use crate::transaction::RocksDBTransaction; @@ -90,7 +89,8 @@ fn acquire_lock(lock_file: &str) -> Result { } fn release_lock(file: File) -> PhpResult<()> { - file.unlock().map_err(|e| PhpException::from(e.to_string()))?; + file.unlock() + .map_err(|e| PhpException::from(e.to_string()))?; Ok(()) } @@ -142,23 +142,26 @@ impl RocksDB { Ok(db) => Ok(RocksDB { db, lock_handle: Some(lock_handle), - position: None + position: None, }), Err(e) => { let _ = release_lock(lock_handle); Err(e.to_string().into()) - }, + } } } #[destructor] pub fn __destruct(&self) { if let Some(lock_handle) = &self.lock_handle { - let _ = release_lock(lock_handle.try_clone().expect("Failed to clone file handle")); + let _ = release_lock( + lock_handle + .try_clone() + .expect("Failed to clone file handle"), + ); } } - pub fn put(&self, key: String, value: String, cf_name: Option) -> PhpResult<()> { match cf_name { Some(cf_name) => { diff --git a/src/transaction.rs b/src/transaction.rs index 15f388e..1a981fb 100644 --- a/src/transaction.rs +++ b/src/transaction.rs @@ -1,9 +1,9 @@ +use crate::RocksDBException; use ext_php_rs::prelude::*; use rust_rocksdb::{ Options, Transaction, TransactionDB, TransactionDBOptions, TransactionOptions, WriteOptions, }; use std::sync::{Arc, Mutex}; -use crate::RocksDBException; #[php_class] pub struct RocksDBTransaction { @@ -31,8 +31,9 @@ impl RocksDBTransaction { opts.set_max_open_files(1000); opts.set_log_level(rust_rocksdb::LogLevel::Warn); - let transaction_db = TransactionDB::open(&opts, &txn_db_opts, &path) - .map_err(|e| ext_php_rs::exception::PhpException::from_class::(e.to_string()))?; + let transaction_db = TransactionDB::open(&opts, &txn_db_opts, &path).map_err(|e| { + ext_php_rs::exception::PhpException::from_class::(e.to_string()) + })?; let transaction_db = Arc::new(transaction_db); let transaction = create_transaction(&transaction_db); @@ -58,8 +59,9 @@ impl RocksDBTransaction { pub fn commit(&self) -> PhpResult<()> { let mut txn_guard = self.transaction.lock().unwrap(); if let Some(txn) = txn_guard.take() { - txn.commit() - .map_err(|e| ext_php_rs::exception::PhpException::from_class::(e.to_string()))?; + txn.commit().map_err(|e| { + ext_php_rs::exception::PhpException::from_class::(e.to_string()) + })?; } *txn_guard = Some(create_transaction(&self.transaction_db)); Ok(()) @@ -68,8 +70,9 @@ impl RocksDBTransaction { pub fn rollback(&self) -> PhpResult<()> { let mut txn_guard = self.transaction.lock().unwrap(); if let Some(txn) = txn_guard.take() { - txn.rollback() - .map_err(|e| ext_php_rs::exception::PhpException::from_class::(e.to_string()))?; + txn.rollback().map_err(|e| { + ext_php_rs::exception::PhpException::from_class::(e.to_string()) + })?; } *txn_guard = Some(create_transaction(&self.transaction_db)); Ok(()) @@ -86,8 +89,9 @@ impl RocksDBTransaction { pub fn rollback_to_savepoint(&self) -> PhpResult<()> { let txn_guard = self.transaction.lock().unwrap(); if let Some(ref txn) = *txn_guard { - txn.rollback_to_savepoint() - .map_err(|e| ext_php_rs::exception::PhpException::from_class::(e.to_string()))?; + txn.rollback_to_savepoint().map_err(|e| { + ext_php_rs::exception::PhpException::from_class::(e.to_string()) + })?; } Ok(()) } @@ -102,16 +106,22 @@ impl RocksDBTransaction { .cf_handle(&cf_name) .ok_or("Column family not found")?; txn.put_cf(&cf, key.as_bytes(), value.as_bytes()) - .map_err(|e| ext_php_rs::exception::PhpException::from_class::(e.to_string())) + .map_err(|e| { + ext_php_rs::exception::PhpException::from_class::( + e.to_string(), + ) + }) } - None => txn - .put(key.as_bytes(), value.as_bytes()) - .map_err(|e| ext_php_rs::exception::PhpException::from_class::(e.to_string())), + None => txn.put(key.as_bytes(), value.as_bytes()).map_err(|e| { + ext_php_rs::exception::PhpException::from_class::( + e.to_string(), + ) + }), } } else { - Err(ext_php_rs::exception::PhpException::from_class::( - "No active transaction".to_string(), - )) + Err(ext_php_rs::exception::PhpException::from_class::< + RocksDBException, + >("No active transaction".to_string())) } } @@ -126,26 +136,32 @@ impl RocksDBTransaction { .ok_or("Column family not found")?; match txn.get_cf(&cf, key.as_bytes()) { Ok(Some(value)) => Ok(Some(String::from_utf8(value).map_err(|e| { - ext_php_rs::exception::PhpException::from_class::(e.to_string()) - })?)), - Ok(None) => Ok(None), - Err(e) => Err(ext_php_rs::exception::PhpException::from_class::(e.to_string())), - } - } - None => { - match txn.get(key.as_bytes()) { - Ok(Some(value)) => Ok(Some(String::from_utf8(value).map_err(|e| { - ext_php_rs::exception::PhpException::from_class::(e.to_string()) + ext_php_rs::exception::PhpException::from_class::( + e.to_string(), + ) })?)), Ok(None) => Ok(None), - Err(e) => Err(ext_php_rs::exception::PhpException::from_class::(e.to_string())), + Err(e) => Err(ext_php_rs::exception::PhpException::from_class::< + RocksDBException, + >(e.to_string())), } } + None => match txn.get(key.as_bytes()) { + Ok(Some(value)) => Ok(Some(String::from_utf8(value).map_err(|e| { + ext_php_rs::exception::PhpException::from_class::( + e.to_string(), + ) + })?)), + Ok(None) => Ok(None), + Err(e) => Err(ext_php_rs::exception::PhpException::from_class::< + RocksDBException, + >(e.to_string())), + }, } } else { - Err(ext_php_rs::exception::PhpException::from_class::( - "No active transaction".to_string(), - )) + Err(ext_php_rs::exception::PhpException::from_class::< + RocksDBException, + >("No active transaction".to_string())) } } @@ -158,17 +174,22 @@ impl RocksDBTransaction { .transaction_db .cf_handle(&cf_name) .ok_or("Column family not found")?; - txn.delete_cf(&cf, key.as_bytes()) - .map_err(|e| ext_php_rs::exception::PhpException::from_class::(e.to_string())) + txn.delete_cf(&cf, key.as_bytes()).map_err(|e| { + ext_php_rs::exception::PhpException::from_class::( + e.to_string(), + ) + }) } - None => txn - .delete(key.as_bytes()) - .map_err(|e| ext_php_rs::exception::PhpException::from_class::(e.to_string())), + None => txn.delete(key.as_bytes()).map_err(|e| { + ext_php_rs::exception::PhpException::from_class::( + e.to_string(), + ) + }), } } else { - Err(ext_php_rs::exception::PhpException::from_class::( - "No active transaction".to_string(), - )) + Err(ext_php_rs::exception::PhpException::from_class::< + RocksDBException, + >("No active transaction".to_string())) } } @@ -182,16 +203,22 @@ impl RocksDBTransaction { .cf_handle(&cf_name) .ok_or("Column family not found")?; txn.merge_cf(&cf, key.as_bytes(), value.as_bytes()) - .map_err(|e| ext_php_rs::exception::PhpException::from_class::(e.to_string())) + .map_err(|e| { + ext_php_rs::exception::PhpException::from_class::( + e.to_string(), + ) + }) } - None => txn - .merge(key.as_bytes(), value.as_bytes()) - .map_err(|e| ext_php_rs::exception::PhpException::from_class::(e.to_string())), + None => txn.merge(key.as_bytes(), value.as_bytes()).map_err(|e| { + ext_php_rs::exception::PhpException::from_class::( + e.to_string(), + ) + }), } } else { - Err(ext_php_rs::exception::PhpException::from_class::( - "No active transaction".to_string(), - )) + Err(ext_php_rs::exception::PhpException::from_class::< + RocksDBException, + >("No active transaction".to_string())) } } } diff --git a/src/write_batch.rs b/src/write_batch.rs index 9573038..44ebe7e 100644 --- a/src/write_batch.rs +++ b/src/write_batch.rs @@ -1,8 +1,8 @@ +use crate::RocksDBException; use ext_php_rs::prelude::*; use rust_rocksdb::{Options, WriteBatchWithTransaction, DB}; use std::sync::{Arc, Mutex}; use std::time::Duration; -use crate::RocksDBException; #[php_class] pub struct RocksDBWriteBatch {