]> git.proxmox.com Git - ceph.git/blob - ceph/src/jaegertracing/thrift/tutorial/rs/src/bin/tutorial_server.rs
buildsys: switch source download to quincy
[ceph.git] / ceph / src / jaegertracing / thrift / tutorial / rs / src / bin / tutorial_server.rs
1 // Licensed to the Apache Software Foundation (ASF) under one
2 // or more contributor license agreements. See the NOTICE file
3 // distributed with this work for additional information
4 // regarding copyright ownership. The ASF licenses this file
5 // to you under the Apache License, Version 2.0 (the
6 // "License"); you may not use this file except in compliance
7 // with the License. You may obtain a copy of the License at
8 //
9 // http://www.apache.org/licenses/LICENSE-2.0
10 //
11 // Unless required by applicable law or agreed to in writing,
12 // software distributed under the License is distributed on an
13 // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14 // KIND, either express or implied. See the License for the
15 // specific language governing permissions and limitations
16 // under the License.
17
18 #[macro_use]
19 extern crate clap;
20
21 extern crate thrift;
22 extern crate thrift_tutorial;
23
24 use std::collections::HashMap;
25 use std::convert::{From, Into};
26 use std::default::Default;
27 use std::sync::Mutex;
28
29 use thrift::protocol::{TCompactInputProtocolFactory, TCompactOutputProtocolFactory};
30 use thrift::server::TServer;
31
32 use thrift::transport::{TFramedReadTransportFactory, TFramedWriteTransportFactory};
33 use thrift_tutorial::shared::{SharedServiceSyncHandler, SharedStruct};
34 use thrift_tutorial::tutorial::{CalculatorSyncHandler, CalculatorSyncProcessor};
35 use thrift_tutorial::tutorial::{InvalidOperation, Operation, Work};
36
37 fn main() {
38 match run() {
39 Ok(()) => println!("tutorial server ran successfully"),
40 Err(e) => {
41 println!("tutorial server failed with error {:?}", e);
42 std::process::exit(1);
43 }
44 }
45 }
46
47 fn run() -> thrift::Result<()> {
48 let options = clap_app!(rust_tutorial_server =>
49 (version: "0.1.0")
50 (author: "Apache Thrift Developers <dev@thrift.apache.org>")
51 (about: "Thrift Rust tutorial server")
52 (@arg port: --port +takes_value "port on which the tutorial server listens")
53 );
54 let matches = options.get_matches();
55
56 let port = value_t!(matches, "port", u16).unwrap_or(9090);
57 let listen_address = format!("127.0.0.1:{}", port);
58
59 println!("binding to {}", listen_address);
60
61 let i_tran_fact = TFramedReadTransportFactory::new();
62 let i_prot_fact = TCompactInputProtocolFactory::new();
63
64 let o_tran_fact = TFramedWriteTransportFactory::new();
65 let o_prot_fact = TCompactOutputProtocolFactory::new();
66
67 // demux incoming messages
68 let processor = CalculatorSyncProcessor::new(CalculatorServer {
69 ..Default::default()
70 });
71
72 // create the server and start listening
73 let mut server = TServer::new(
74 i_tran_fact,
75 i_prot_fact,
76 o_tran_fact,
77 o_prot_fact,
78 processor,
79 10,
80 );
81
82 server.listen(&listen_address)
83 }
84
85 /// Handles incoming Calculator service calls.
86 struct CalculatorServer {
87 log: Mutex<HashMap<i32, SharedStruct>>,
88 }
89
90 impl Default for CalculatorServer {
91 fn default() -> CalculatorServer {
92 CalculatorServer {
93 log: Mutex::new(HashMap::new()),
94 }
95 }
96 }
97
98 // since Calculator extends SharedService we have to implement the
99 // handler for both traits.
100 //
101
102 // SharedService handler
103 impl SharedServiceSyncHandler for CalculatorServer {
104 fn handle_get_struct(&self, key: i32) -> thrift::Result<SharedStruct> {
105 let log = self.log.lock().unwrap();
106 log.get(&key)
107 .cloned()
108 .ok_or_else(|| format!("could not find log for key {}", key).into())
109 }
110 }
111
112 // Calculator handler
113 impl CalculatorSyncHandler for CalculatorServer {
114 fn handle_ping(&self) -> thrift::Result<()> {
115 println!("pong!");
116 Ok(())
117 }
118
119 fn handle_add(&self, num1: i32, num2: i32) -> thrift::Result<i32> {
120 println!("handling add: n1:{} n2:{}", num1, num2);
121 Ok(num1 + num2)
122 }
123
124 fn handle_calculate(&self, logid: i32, w: Work) -> thrift::Result<i32> {
125 println!("handling calculate: l:{}, w:{:?}", logid, w);
126
127 let res = if let Some(ref op) = w.op {
128 if w.num1.is_none() || w.num2.is_none() {
129 Err(InvalidOperation {
130 what_op: Some(*op as i32),
131 why: Some("no operands specified".to_owned()),
132 })
133 } else {
134 // so that I don't have to call unwrap() multiple times below
135 let num1 = w.num1.as_ref().expect("operands checked");
136 let num2 = w.num2.as_ref().expect("operands checked");
137
138 match *op {
139 Operation::Add => Ok(num1 + num2),
140 Operation::Subtract => Ok(num1 - num2),
141 Operation::Multiply => Ok(num1 * num2),
142 Operation::Divide => {
143 if *num2 == 0 {
144 Err(InvalidOperation {
145 what_op: Some(*op as i32),
146 why: Some("divide by 0".to_owned()),
147 })
148 } else {
149 Ok(num1 / num2)
150 }
151 }
152 }
153 }
154 } else {
155 Err(InvalidOperation::new(
156 None,
157 "no operation specified".to_owned(),
158 ))
159 };
160
161 // if the operation was successful log it
162 if let Ok(ref v) = res {
163 let mut log = self.log.lock().unwrap();
164 log.insert(logid, SharedStruct::new(logid, format!("{}", v)));
165 }
166
167 // the try! macro automatically maps errors
168 // but, since we aren't using that here we have to map errors manually
169 //
170 // exception structs defined in the IDL have an auto-generated
171 // impl of From::from
172 res.map_err(From::from)
173 }
174
175 fn handle_zip(&self) -> thrift::Result<()> {
176 println!("handling zip");
177 Ok(())
178 }
179 }