diff --git a/benches/engine.rs b/benches/engine.rs index e9f38b716454c74c5eece12ba72fc260af338110..2aea2e0518692f254be98ef3f44c407f76966686 100644 --- a/benches/engine.rs +++ b/benches/engine.rs @@ -3,7 +3,7 @@ extern crate sbroad; use sbroad::errors::QueryPlannerError; use sbroad::executor::bucket::Buckets; use sbroad::executor::engine::cartridge::hash::str_to_bucket_id; -use sbroad::executor::engine::Engine; +use sbroad::executor::engine::{Engine, LocalMetadata}; use sbroad::executor::ir::ExecutionPlan; use sbroad::executor::result::{BoxExecuteFormat, Value}; use sbroad::executor::vtable::VirtualTable; @@ -225,15 +225,15 @@ impl Engine for EngineMock { self.metadata.tables.is_empty() } - fn get_schema(&self) -> Result<Option<String>, QueryPlannerError> { - Ok(Some("".to_string())) + fn get_metadata(&self) -> Result<Option<LocalMetadata>, QueryPlannerError> { + let metadata = LocalMetadata { + schema: "".into(), + timeout: 0, + }; + Ok(Some(metadata)) } - fn get_timeout(&self) -> Result<Option<u64>, QueryPlannerError> { - Ok(Some(0)) - } - - fn update_metadata(&mut self, _schema: String, _timeout: u64) -> Result<(), QueryPlannerError> { + fn update_metadata(&mut self, _metadata: LocalMetadata) -> Result<(), QueryPlannerError> { self.metadata = MetadataMock::new(); Ok(()) } diff --git a/src/executor/engine.rs b/src/executor/engine.rs index 69ff881970ba3c3a9bfac18b2880f05545c58927..c415a095daf278b5ea5df3f9eb083eb0b42ce4e6 100644 --- a/src/executor/engine.rs +++ b/src/executor/engine.rs @@ -45,6 +45,14 @@ pub trait Metadata { fn get_sharding_key_by_space(&self, space: &str) -> Result<Vec<&str>, QueryPlannerError>; } +/// Local storage for uploading metadata. +pub struct LocalMetadata { + /// Cluster schema. + pub schema: String, + /// Query execution timeout. + pub timeout: u64, +} + /// An execution engine trait. pub trait Engine { type Metadata; @@ -60,23 +68,17 @@ pub trait Engine { /// Check if the cache is empty. fn is_metadata_empty(&self) -> bool; - /// Retrieve cluster schema. - /// - /// # Errors - /// - Failed to retrieve cluster schema. - fn get_schema(&self) -> Result<Option<String>, QueryPlannerError>; - - /// Retrieve timeout to wait for execution completion. + /// Retrieve cluster metadata. /// /// # Errors - /// - Failed to get timeout from the configuration. - fn get_timeout(&self) -> Result<Option<u64>, QueryPlannerError>; + /// - Internal error. + fn get_metadata(&self) -> Result<Option<LocalMetadata>, QueryPlannerError>; /// Update cached metadata information. /// /// # Errors /// - Failed to update metadata information (invalid metadata). - fn update_metadata(&mut self, schema: String, timeout: u64) -> Result<(), QueryPlannerError>; + fn update_metadata(&mut self, metadata: LocalMetadata) -> Result<(), QueryPlannerError>; /// Materialize result motion node to virtual table /// diff --git a/src/executor/engine/cartridge.rs b/src/executor/engine/cartridge.rs index badfa234a5a6e67711be258bd2f075f16aba54b3..598f52422a873318a2e403c2f6b33a0ca61cf32b 100644 --- a/src/executor/engine/cartridge.rs +++ b/src/executor/engine/cartridge.rs @@ -10,7 +10,7 @@ use crate::errors::QueryPlannerError; use crate::executor::bucket::Buckets; use crate::executor::engine::cartridge::cache::ClusterAppConfig; use crate::executor::engine::cartridge::hash::str_to_bucket_id; -use crate::executor::engine::Engine; +use crate::executor::engine::{Engine, LocalMetadata}; use crate::executor::ir::ExecutionPlan; use crate::executor::result::BoxExecuteFormat; use crate::executor::vtable::VirtualTable; @@ -44,13 +44,12 @@ impl Engine for Runtime { self.metadata.is_empty() } - fn get_schema(&self) -> Result<Option<String>, QueryPlannerError> { + fn get_metadata(&self) -> Result<Option<LocalMetadata>, QueryPlannerError> { if self.metadata.is_empty() { let lua = tarantool::lua_state(); let get_schema: LuaFunction<_> = lua.eval("return get_schema;").unwrap(); - - let res: String = match get_schema.call() { + let schema: String = match get_schema.call() { Ok(res) => res, Err(e) => { say( @@ -63,17 +62,9 @@ impl Engine for Runtime { return Err(QueryPlannerError::LuaError(format!("Lua error: {:?}", e))); } }; - return Ok(Some(res)); - } - Ok(None) - } - fn get_timeout(&self) -> Result<Option<u64>, QueryPlannerError> { - if self.metadata.is_empty() { - let lua = tarantool::lua_state(); - let timeout: LuaFunction<_> = lua.eval("return get_waiting_timeout;").unwrap(); - - let waiting_timeout: u64 = match timeout.call() { + let waiting_timeout: LuaFunction<_> = lua.eval("return get_waiting_timeout;").unwrap(); + let timeout: u64 = match waiting_timeout.call() { Ok(res) => res, Err(e) => { say( @@ -86,14 +77,16 @@ impl Engine for Runtime { return Err(QueryPlannerError::LuaError(format!("Lua error: {:?}", e))); } }; - return Ok(Some(waiting_timeout)); + + let metadata = LocalMetadata { schema, timeout }; + return Ok(Some(metadata)); } Ok(None) } - fn update_metadata(&mut self, schema: String, timeout: u64) -> Result<(), QueryPlannerError> { - self.metadata.load_schema(&schema)?; - self.metadata.set_exec_waiting_timeout(timeout); + fn update_metadata(&mut self, metadata: LocalMetadata) -> Result<(), QueryPlannerError> { + self.metadata.load_schema(&metadata.schema)?; + self.metadata.set_exec_waiting_timeout(metadata.timeout); Ok(()) } diff --git a/src/executor/engine/mock.rs b/src/executor/engine/mock.rs index 7578566e08d459884e52f92c1e2eba78b33fca94..b1d8e24adf459b1ce0a1da5d96731dd6f536807d 100644 --- a/src/executor/engine/mock.rs +++ b/src/executor/engine/mock.rs @@ -4,7 +4,7 @@ use std::collections::HashMap; use crate::errors::QueryPlannerError; use crate::executor::bucket::Buckets; use crate::executor::engine::cartridge::hash::str_to_bucket_id; -use crate::executor::engine::Engine; +use crate::executor::engine::{Engine, LocalMetadata}; use crate::executor::ir::ExecutionPlan; use crate::executor::result::{BoxExecuteFormat, Value}; use crate::executor::vtable::VirtualTable; @@ -166,15 +166,15 @@ impl Engine for EngineMock { self.metadata.tables.is_empty() } - fn get_schema(&self) -> Result<Option<String>, QueryPlannerError> { - Ok(Some("".to_string())) + fn get_metadata(&self) -> Result<Option<LocalMetadata>, QueryPlannerError> { + let metadata = LocalMetadata { + schema: "".into(), + timeout: 0, + }; + Ok(Some(metadata)) } - fn get_timeout(&self) -> Result<Option<u64>, QueryPlannerError> { - Ok(Some(0)) - } - - fn update_metadata(&mut self, _schema: String, _timeout: u64) -> Result<(), QueryPlannerError> { + fn update_metadata(&mut self, _metadata: LocalMetadata) -> Result<(), QueryPlannerError> { self.metadata = MetadataMock::new(); Ok(()) } diff --git a/src/parser.rs b/src/parser.rs index 944599e71625e8cb27476c0c3a25e7242ec4eff2..a498fa32feb6eeab9795da1e6e77fcc109385166 100644 --- a/src/parser.rs +++ b/src/parser.rs @@ -9,7 +9,7 @@ use tarantool::tuple::{AsTuple, FunctionArgs, FunctionCtx, Tuple}; use crate::errors::QueryPlannerError; use crate::executor::engine::cartridge::load_extra_function; -use crate::executor::engine::{cartridge, Engine}; +use crate::executor::engine::{cartridge, Engine, LocalMetadata}; use crate::executor::Query; use self::extargs::{BucketCalcArgs, BucketCalcArgsDict}; @@ -146,17 +146,15 @@ pub extern "C" fn execute_query(ctx: FunctionCtx, args: FunctionArgs) -> c_int { fn load_metadata() -> c_int { // Tarantool can yield in the middle of a current closure, // so we can hold only an immutable reference to the engine. - let mut schema: Option<String> = None; - let mut timeout: Option<u64> = None; + let mut metadata: Option<LocalMetadata> = None; QUERY_ENGINE.with(|e| { let engine = &*e.borrow(); - match (engine.get_schema(), engine.get_timeout()) { - (Ok(s), Ok(t)) => { - schema = s; - timeout = t; + match engine.get_metadata() { + Ok(meta) => { + metadata = meta; 0 } - (Err(e), _) | (_, Err(e)) => { + Err(e) => { return tarantool::set_error!(TarantoolErrorCode::ProcC, "{}", e.to_string()); } } @@ -172,10 +170,10 @@ fn load_metadata() -> c_int { // Tarantool never yields here, so it is possible to hold // a mutable reference to the engine. if is_metadata_empty { - if let (Some(schema), Some(timeout)) = (schema, timeout) { + if let Some(metadata) = metadata { QUERY_ENGINE.with(|e| { let engine = &mut *e.borrow_mut(); - if let Err(e) = engine.update_metadata(schema, timeout) { + if let Err(e) = engine.update_metadata(metadata) { return tarantool::set_error!(TarantoolErrorCode::ProcC, "{}", e.to_string()); } 0