blob: 344945b4153a5ec98a47cd028f0b87dc97a1e4d7 [file] [log] [blame]
David Reissea2cba82009-03-30 21:35:00 +00001/*
2 * Licensed to the Apache Software Foundation (ASF) under one
3 * or more contributor license agreements. See the NOTICE file
4 * distributed with this work for additional information
5 * regarding copyright ownership. The ASF licenses this file
6 * to you under the Apache License, Version 2.0 (the
7 * "License"); you may not use this file except in compliance
8 * with the License. You may obtain a copy of the License at
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing,
13 * software distributed under the License is distributed on an
14 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15 * KIND, either express or implied. See the License for the
16 * specific language governing permissions and limitations
17 * under the License.
18 */
Mark Slee9f0c6512007-02-28 23:58:26 +000019
Mark Sleee8540632006-05-30 09:24:40 +000020#include "server/TSimpleServer.h"
Mark Slee8d7e1f62006-06-07 06:48:56 +000021#include "transport/TTransportException.h"
Mark Sleee8540632006-05-30 09:24:40 +000022#include <string>
Mark Slee8d7e1f62006-06-07 06:48:56 +000023#include <iostream>
Mark Sleee8540632006-05-30 09:24:40 +000024
T Jake Lucianib5e62212009-01-31 22:36:20 +000025namespace apache { namespace thrift { namespace server {
Marc Slemko6f038a72006-08-03 18:58:09 +000026
Mark Slee5ea15f92007-03-05 22:55:59 +000027using namespace std;
T Jake Lucianib5e62212009-01-31 22:36:20 +000028using namespace apache::thrift;
29using namespace apache::thrift::protocol;
30using namespace apache::thrift::transport;
Mark Slee5ea15f92007-03-05 22:55:59 +000031using boost::shared_ptr;
32
Mark Slee8d7e1f62006-06-07 06:48:56 +000033/**
34 * A simple single-threaded application server. Perfect for unit tests!
35 *
Mark Slee8d7e1f62006-06-07 06:48:56 +000036 */
Mark Slee794993d2006-09-20 01:56:10 +000037void TSimpleServer::serve() {
Marc Slemko16698852006-08-04 03:16:10 +000038
39 shared_ptr<TTransport> client;
Aditya Agarwal9abb0d62007-01-24 22:53:54 +000040 shared_ptr<TTransport> inputTransport;
41 shared_ptr<TTransport> outputTransport;
42 shared_ptr<TProtocol> inputProtocol;
43 shared_ptr<TProtocol> outputProtocol;
Mark Sleee8540632006-05-30 09:24:40 +000044
Roger Meierd8f50f32012-04-11 21:48:56 +000045 // Start the server listening
46 serverTransport_->listen();
Mark Sleee8540632006-05-30 09:24:40 +000047
Mark Sleeb4d3e7b2007-11-28 01:51:43 +000048 // Run the preServe event
49 if (eventHandler_ != NULL) {
50 eventHandler_->preServe();
51 }
52
Mark Sleee8540632006-05-30 09:24:40 +000053 // Fetch client from server
Mark Slee6e3f6372007-03-01 22:05:46 +000054 while (!stop_) {
Aditya Agarwalfdef47e2007-02-07 03:54:18 +000055 try {
Mark Slee8d7e1f62006-06-07 06:48:56 +000056 client = serverTransport_->accept();
Aditya Agarwal9abb0d62007-01-24 22:53:54 +000057 inputTransport = inputTransportFactory_->getTransport(client);
58 outputTransport = outputTransportFactory_->getTransport(client);
59 inputProtocol = inputProtocolFactory_->getProtocol(inputTransport);
60 outputProtocol = outputProtocolFactory_->getProtocol(outputTransport);
Aditya Agarwalfdef47e2007-02-07 03:54:18 +000061 } catch (TTransportException& ttx) {
Mark Slee3303f362007-03-05 20:09:37 +000062 if (inputTransport != NULL) { inputTransport->close(); }
63 if (outputTransport != NULL) { outputTransport->close(); }
64 if (client != NULL) { client->close(); }
Jake Farrell6ce27042012-01-27 04:32:17 +000065 if (!stop_ || ttx.getType() != TTransportException::INTERRUPTED) {
66 string errStr = string("TServerTransport died on accept: ") + ttx.what();
67 GlobalOutput(errStr.c_str());
68 }
Aditya Agarwalfdef47e2007-02-07 03:54:18 +000069 continue;
70 } catch (TException& tx) {
Mark Slee3303f362007-03-05 20:09:37 +000071 if (inputTransport != NULL) { inputTransport->close(); }
72 if (outputTransport != NULL) { outputTransport->close(); }
73 if (client != NULL) { client->close(); }
David Reiss25df8e72010-10-06 17:10:54 +000074 string errStr = string("Some kind of accept exception: ") + tx.what();
75 GlobalOutput(errStr.c_str());
Aditya Agarwalfdef47e2007-02-07 03:54:18 +000076 continue;
77 } catch (string s) {
Mark Slee3303f362007-03-05 20:09:37 +000078 if (inputTransport != NULL) { inputTransport->close(); }
79 if (outputTransport != NULL) { outputTransport->close(); }
80 if (client != NULL) { client->close(); }
David Reiss25df8e72010-10-06 17:10:54 +000081 string errStr = string("Some kind of accept exception: ") + s;
82 GlobalOutput(errStr.c_str());
Aditya Agarwalfdef47e2007-02-07 03:54:18 +000083 break;
Mark Sleed788b2e2006-09-07 01:26:35 +000084 }
David Reiss25df8e72010-10-06 17:10:54 +000085
Bryan Duxbury6dd9cd02011-09-01 18:06:20 +000086 // Get the processor
87 shared_ptr<TProcessor> processor = getProcessor(inputProtocol,
88 outputProtocol, client);
89
David Reiss25df8e72010-10-06 17:10:54 +000090 void* connectionContext = NULL;
91 if (eventHandler_ != NULL) {
92 connectionContext = eventHandler_->createContext(inputProtocol, outputProtocol);
93 }
94 try {
95 for (;;) {
96 if (eventHandler_ != NULL) {
97 eventHandler_->processContext(connectionContext, client);
98 }
Bryan Duxbury6dd9cd02011-09-01 18:06:20 +000099 if (!processor->process(inputProtocol, outputProtocol,
100 connectionContext) ||
101 // Peek ahead, is the remote side closed?
David Reiss25df8e72010-10-06 17:10:54 +0000102 !inputProtocol->getTransport()->peek()) {
103 break;
104 }
105 }
Bryan Duxbury1e987582011-08-25 17:33:03 +0000106 } catch (const TTransportException& ttx) {
David Reiss25df8e72010-10-06 17:10:54 +0000107 string errStr = string("TSimpleServer client died: ") + ttx.what();
108 GlobalOutput(errStr.c_str());
Bryan Duxbury1e987582011-08-25 17:33:03 +0000109 } catch (const std::exception& x) {
110 GlobalOutput.printf("TSimpleServer exception: %s: %s",
111 typeid(x).name(), x.what());
David Reiss25df8e72010-10-06 17:10:54 +0000112 } catch (...) {
113 GlobalOutput("TSimpleServer uncaught exception.");
114 }
115 if (eventHandler_ != NULL) {
116 eventHandler_->deleteContext(connectionContext, inputProtocol, outputProtocol);
117 }
118
119 try {
120 inputTransport->close();
Bryan Duxburye04159c2011-08-25 17:43:56 +0000121 } catch (const TTransportException& ttx) {
122 string errStr = string("TSimpleServer input close failed: ")
123 + ttx.what();
David Reiss25df8e72010-10-06 17:10:54 +0000124 GlobalOutput(errStr.c_str());
125 }
126 try {
127 outputTransport->close();
Bryan Duxburye04159c2011-08-25 17:43:56 +0000128 } catch (const TTransportException& ttx) {
129 string errStr = string("TSimpleServer output close failed: ")
130 + ttx.what();
David Reiss25df8e72010-10-06 17:10:54 +0000131 GlobalOutput(errStr.c_str());
132 }
133 try {
134 client->close();
Bryan Duxburye04159c2011-08-25 17:43:56 +0000135 } catch (const TTransportException& ttx) {
136 string errStr = string("TSimpleServer client close failed: ")
137 + ttx.what();
David Reiss25df8e72010-10-06 17:10:54 +0000138 GlobalOutput(errStr.c_str());
139 }
Mark Sleee8540632006-05-30 09:24:40 +0000140 }
141
Mark Slee6e3f6372007-03-01 22:05:46 +0000142 if (stop_) {
143 try {
144 serverTransport_->close();
145 } catch (TTransportException &ttx) {
David Reiss25df8e72010-10-06 17:10:54 +0000146 string errStr = string("TServerTransport failed on close: ") + ttx.what();
147 GlobalOutput(errStr.c_str());
Mark Slee6e3f6372007-03-01 22:05:46 +0000148 }
149 stop_ = false;
150 }
Mark Sleee8540632006-05-30 09:24:40 +0000151}
Marc Slemko6f038a72006-08-03 18:58:09 +0000152
T Jake Lucianib5e62212009-01-31 22:36:20 +0000153}}} // apache::thrift::server