diff --git a/miner/src/transaction_queue.rs b/miner/src/transaction_queue.rs index ecfb2b8b0..6a1721f1d 100644 --- a/miner/src/transaction_queue.rs +++ b/miner/src/transaction_queue.rs @@ -672,10 +672,10 @@ impl TransactionQueue { } fn check_too_cheap(is_in: bool) -> Result<(), TransactionError> { - if !is_in { - Err(TransactionError::TooCheapToReplace) - } else { + if is_in { Ok(()) + } else { + Err(TransactionError::TooCheapToReplace) } } diff --git a/rpc/src/v1/impls/ethcore.rs b/rpc/src/v1/impls/ethcore.rs index f15d0a3d5..36116cfaa 100644 --- a/rpc/src/v1/impls/ethcore.rs +++ b/rpc/src/v1/impls/ethcore.rs @@ -84,7 +84,7 @@ impl Ethcore for EthcoreClient where M: MinerService + 'static { fn dev_logs(&self, _params: Params) -> Result { let logs = self.logger.logs(); - to_value(&logs.deref()) + to_value(&logs.deref().as_slice()) } fn dev_logs_levels(&self, _params: Params) -> Result { diff --git a/rpc/src/v1/tests/ethcore.rs b/rpc/src/v1/tests/ethcore.rs index 06d4ffc1c..51542e9dc 100644 --- a/rpc/src/v1/tests/ethcore.rs +++ b/rpc/src/v1/tests/ethcore.rs @@ -22,16 +22,20 @@ use ethminer::MinerService; use v1::tests::helpers::TestMinerService; use util::numbers::*; use rustc_serialize::hex::FromHex; +use util::log::RotatingLogger; fn miner_service() -> Arc { Arc::new(TestMinerService::default()) } +fn logger() -> Arc { + Arc::new(RotatingLogger::new("rpc=trace".to_owned())) +} #[test] fn rpc_ethcore_extra_data() { let miner = miner_service(); - let ethcore = EthcoreClient::new(&miner).to_delegate(); + let ethcore = EthcoreClient::new(&miner, logger()).to_delegate(); let io = IoHandler::new(); io.add_delegate(ethcore); @@ -45,7 +49,7 @@ fn rpc_ethcore_extra_data() { #[test] fn rpc_ethcore_gas_floor_target() { let miner = miner_service(); - let ethcore = EthcoreClient::new(&miner).to_delegate(); + let ethcore = EthcoreClient::new(&miner, logger()).to_delegate(); let io = IoHandler::new(); io.add_delegate(ethcore); @@ -58,7 +62,7 @@ fn rpc_ethcore_gas_floor_target() { #[test] fn rpc_ethcore_min_gas_price() { let miner = miner_service(); - let ethcore = EthcoreClient::new(&miner).to_delegate(); + let ethcore = EthcoreClient::new(&miner, logger()).to_delegate(); let io = IoHandler::new(); io.add_delegate(ethcore); @@ -71,7 +75,7 @@ fn rpc_ethcore_min_gas_price() { #[test] fn rpc_ethcore_set_min_gas_price() { let miner = miner_service(); - let ethcore = EthcoreClient::new(&miner).to_delegate(); + let ethcore = EthcoreClient::new(&miner, logger()).to_delegate(); let io = IoHandler::new(); io.add_delegate(ethcore); @@ -85,7 +89,7 @@ fn rpc_ethcore_set_min_gas_price() { #[test] fn rpc_ethcore_set_gas_floor_target() { let miner = miner_service(); - let ethcore = EthcoreClient::new(&miner).to_delegate(); + let ethcore = EthcoreClient::new(&miner, logger()).to_delegate(); let io = IoHandler::new(); io.add_delegate(ethcore); @@ -99,7 +103,7 @@ fn rpc_ethcore_set_gas_floor_target() { #[test] fn rpc_ethcore_set_extra_data() { let miner = miner_service(); - let ethcore = EthcoreClient::new(&miner).to_delegate(); + let ethcore = EthcoreClient::new(&miner, logger()).to_delegate(); let io = IoHandler::new(); io.add_delegate(ethcore); @@ -113,7 +117,7 @@ fn rpc_ethcore_set_extra_data() { #[test] fn rpc_ethcore_set_author() { let miner = miner_service(); - let ethcore = EthcoreClient::new(&miner).to_delegate(); + let ethcore = EthcoreClient::new(&miner, logger()).to_delegate(); let io = IoHandler::new(); io.add_delegate(ethcore); @@ -123,3 +127,32 @@ fn rpc_ethcore_set_author() { assert_eq!(io.handle_request(request), Some(response.to_owned())); assert_eq!(miner.author(), Address::from_str("cd1722f3947def4cf144679da39c4c32bdc35681").unwrap()); } + +#[test] +fn rpc_ethcore_dev_logs() { + let miner = miner_service(); + let logger = logger(); + logger.append("a".to_owned()); + logger.append("b".to_owned()); + let ethcore = EthcoreClient::new(&miner, logger.clone()).to_delegate(); + let io = IoHandler::new(); + io.add_delegate(ethcore); + + let request = r#"{"jsonrpc": "2.0", "method": "ethcore_devLogs", "params":[], "id": 1}"#; + let response = r#"{"jsonrpc":"2.0","result":["b","a"],"id":1}"#; + + assert_eq!(io.handle_request(request), Some(response.to_owned())); +} + +#[test] +fn rpc_ethcore_dev_logs_levels() { + let miner = miner_service(); + let ethcore = EthcoreClient::new(&miner, logger()).to_delegate(); + let io = IoHandler::new(); + io.add_delegate(ethcore); + + let request = r#"{"jsonrpc": "2.0", "method": "ethcore_devLogsLevels", "params":[], "id": 1}"#; + let response = r#"{"jsonrpc":"2.0","result":"rpc=trace","id":1}"#; + + assert_eq!(io.handle_request(request), Some(response.to_owned())); +} diff --git a/util/src/log.rs b/util/src/log.rs index c5ad40239..45017bfcd 100644 --- a/util/src/log.rs +++ b/util/src/log.rs @@ -20,7 +20,7 @@ use std::env; use rlog::{LogLevelFilter}; use env_logger::LogBuilder; use std::sync::{RwLock, RwLockReadGuard}; -use std::sync::atomic::{AtomicBool, AtomicUsize, Ordering}; +use arrayvec::ArrayVec; lazy_static! { static ref LOG_DUMMY: bool = { @@ -43,35 +43,39 @@ pub fn init_log() { let _ = *LOG_DUMMY; } -static LOG_SIZE : usize = 128; +const LOG_SIZE : usize = 128; +/// Logger implementation that keeps up to `LOG_SIZE` log elements. pub struct RotatingLogger { - idx: AtomicUsize, + /// Defined logger levels levels: String, - logs: RwLock>, + /// Logs array. Latest log is always at index 0 + logs: RwLock>, } impl RotatingLogger { + /// Creates new `RotatingLogger` with given levels. + /// It does not enforce levels - it's just read only. pub fn new(levels: String) -> Self { RotatingLogger { - idx: AtomicUsize::new(0), levels: levels, - logs: RwLock::new(Vec::with_capacity(LOG_SIZE)), + logs: RwLock::new(ArrayVec::<[_; LOG_SIZE]>::new()), } } + /// Append new log entry pub fn append(&self, log: String) { - let idx = self.idx.fetch_add(1, Ordering::SeqCst); - let idx = idx % LOG_SIZE; - self.logs.write().unwrap().insert(idx, log); + self.logs.write().unwrap().insert(0, log); } + /// Return levels pub fn levels(&self) -> &str { &self.levels } - pub fn logs(&self) -> RwLockReadGuard> { + /// Return logs + pub fn logs(&self) -> RwLockReadGuard> { self.logs.read().unwrap() }