diff options
Diffstat (limited to '')
-rw-r--r-- | src/jaegertracing/thrift/tutorial/rs/src/bin/tutorial_server.rs | 179 |
1 files changed, 179 insertions, 0 deletions
diff --git a/src/jaegertracing/thrift/tutorial/rs/src/bin/tutorial_server.rs b/src/jaegertracing/thrift/tutorial/rs/src/bin/tutorial_server.rs new file mode 100644 index 000000000..95b1a2b6e --- /dev/null +++ b/src/jaegertracing/thrift/tutorial/rs/src/bin/tutorial_server.rs @@ -0,0 +1,179 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +#[macro_use] +extern crate clap; + +extern crate thrift; +extern crate thrift_tutorial; + +use std::collections::HashMap; +use std::convert::{From, Into}; +use std::default::Default; +use std::sync::Mutex; + +use thrift::protocol::{TCompactInputProtocolFactory, TCompactOutputProtocolFactory}; +use thrift::server::TServer; + +use thrift::transport::{TFramedReadTransportFactory, TFramedWriteTransportFactory}; +use thrift_tutorial::shared::{SharedServiceSyncHandler, SharedStruct}; +use thrift_tutorial::tutorial::{CalculatorSyncHandler, CalculatorSyncProcessor}; +use thrift_tutorial::tutorial::{InvalidOperation, Operation, Work}; + +fn main() { + match run() { + Ok(()) => println!("tutorial server ran successfully"), + Err(e) => { + println!("tutorial server failed with error {:?}", e); + std::process::exit(1); + } + } +} + +fn run() -> thrift::Result<()> { + let options = clap_app!(rust_tutorial_server => + (version: "0.1.0") + (author: "Apache Thrift Developers <dev@thrift.apache.org>") + (about: "Thrift Rust tutorial server") + (@arg port: --port +takes_value "port on which the tutorial server listens") + ); + let matches = options.get_matches(); + + let port = value_t!(matches, "port", u16).unwrap_or(9090); + let listen_address = format!("127.0.0.1:{}", port); + + println!("binding to {}", listen_address); + + let i_tran_fact = TFramedReadTransportFactory::new(); + let i_prot_fact = TCompactInputProtocolFactory::new(); + + let o_tran_fact = TFramedWriteTransportFactory::new(); + let o_prot_fact = TCompactOutputProtocolFactory::new(); + + // demux incoming messages + let processor = CalculatorSyncProcessor::new(CalculatorServer { + ..Default::default() + }); + + // create the server and start listening + let mut server = TServer::new( + i_tran_fact, + i_prot_fact, + o_tran_fact, + o_prot_fact, + processor, + 10, + ); + + server.listen(&listen_address) +} + +/// Handles incoming Calculator service calls. +struct CalculatorServer { + log: Mutex<HashMap<i32, SharedStruct>>, +} + +impl Default for CalculatorServer { + fn default() -> CalculatorServer { + CalculatorServer { + log: Mutex::new(HashMap::new()), + } + } +} + +// since Calculator extends SharedService we have to implement the +// handler for both traits. +// + +// SharedService handler +impl SharedServiceSyncHandler for CalculatorServer { + fn handle_get_struct(&self, key: i32) -> thrift::Result<SharedStruct> { + let log = self.log.lock().unwrap(); + log.get(&key) + .cloned() + .ok_or_else(|| format!("could not find log for key {}", key).into()) + } +} + +// Calculator handler +impl CalculatorSyncHandler for CalculatorServer { + fn handle_ping(&self) -> thrift::Result<()> { + println!("pong!"); + Ok(()) + } + + fn handle_add(&self, num1: i32, num2: i32) -> thrift::Result<i32> { + println!("handling add: n1:{} n2:{}", num1, num2); + Ok(num1 + num2) + } + + fn handle_calculate(&self, logid: i32, w: Work) -> thrift::Result<i32> { + println!("handling calculate: l:{}, w:{:?}", logid, w); + + let res = if let Some(ref op) = w.op { + if w.num1.is_none() || w.num2.is_none() { + Err(InvalidOperation { + what_op: Some(*op as i32), + why: Some("no operands specified".to_owned()), + }) + } else { + // so that I don't have to call unwrap() multiple times below + let num1 = w.num1.as_ref().expect("operands checked"); + let num2 = w.num2.as_ref().expect("operands checked"); + + match *op { + Operation::Add => Ok(num1 + num2), + Operation::Subtract => Ok(num1 - num2), + Operation::Multiply => Ok(num1 * num2), + Operation::Divide => { + if *num2 == 0 { + Err(InvalidOperation { + what_op: Some(*op as i32), + why: Some("divide by 0".to_owned()), + }) + } else { + Ok(num1 / num2) + } + } + } + } + } else { + Err(InvalidOperation::new( + None, + "no operation specified".to_owned(), + )) + }; + + // if the operation was successful log it + if let Ok(ref v) = res { + let mut log = self.log.lock().unwrap(); + log.insert(logid, SharedStruct::new(logid, format!("{}", v))); + } + + // the try! macro automatically maps errors + // but, since we aren't using that here we have to map errors manually + // + // exception structs defined in the IDL have an auto-generated + // impl of From::from + res.map_err(From::from) + } + + fn handle_zip(&self) -> thrift::Result<()> { + println!("handling zip"); + Ok(()) + } +} |