root/trunk/whisperlib/net/rpc/lib/server/rpc_server.cc

Revision 7, 5.4 kB (checked in by whispercastorg, 2 years ago)

version 0.2.0

Line 
1 // Copyright (c) 2009, Whispersoft s.r.l.
2 // All rights reserved.
3 //
4 // Redistribution and use in source and binary forms, with or without
5 // modification, are permitted provided that the following conditions are
6 // met:
7 //
8 // * Redistributions of source code must retain the above copyright
9 // notice, this list of conditions and the following disclaimer.
10 // * Redistributions in binary form must reproduce the above
11 // copyright notice, this list of conditions and the following disclaimer
12 // in the documentation and/or other materials provided with the
13 // distribution.
14 // * Neither the name of Whispersoft s.r.l. nor the names of its
15 // contributors may be used to endorse or promote products derived from
16 // this software without specific prior written permission.
17 //
18 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 //
30 // Author: Cosmin Tudorache
31
32 // for ::shutdown in case of error on connection creation
33 #include <sys/socket.h>
34
35 #include "common/base/log.h"
36
37 #include "net/rpc/lib/server/rpc_server.h"
38 #include "net/rpc/lib/server/rpc_server_connection.h"
39
40 namespace rpc {
41 Server::Server(net::Selector& selector,
42                net::NetFactory& net_factory,
43                net::PROTOCOL net_protocol,
44                rpc::IAsyncQueryExecutor& executor)
45   : selector_(selector),
46     net_factory_(net_factory),
47     net_acceptor_(net_factory.CreateAcceptor(net_protocol)),
48     executor_(executor),
49     open_completed_(false, true),
50     shutdown_completed_(false, true),
51     open_completed_callback_(NULL) {
52   net_acceptor_->SetFilterHandler(NewPermanentCallback(
53       this, &Server::AcceptorFilterHandler), true);
54   net_acceptor_->SetAcceptHandler(NewPermanentCallback(
55       this, &Server::AcceptorAcceptHandler), true);
56 }
57
58 Server::~Server() {
59   Shutdown();
60   CHECK_NULL(open_completed_callback_);
61   delete net_acceptor_;
62   net_acceptor_ = NULL;
63 }
64
65 //////////////////////////////////////////////////////////////////////
66 //
67 // External methods - available from any thread
68
69 bool Server::Open(const net::HostPort& addr,
70                        OpenCompletedCallback* open_completed_callback) {
71   // do not try double Open
72   CHECK_EQ(net_acceptor_->state(), net::NetAcceptor::DISCONNECTED);
73
74   open_completed_callback_ = open_completed_callback;
75   open_completed_.Reset();
76   selector_.RunInSelectLoop(
77       NewCallback(this, &Server::OpenInSelectThread, addr));
78   if ( open_completed_callback ) {
79     // asynchronous Open
80     return true;
81   }
82   // synchronous Open
83   if ( !open_completed_.Wait(5000) ) {
84     LOG_ERROR << "Timeout waiting for open process to finish";
85     return false;
86   }
87   return IsOpen();
88 }
89
90 void Server::Shutdown() {
91   if ( !IsOpen() ) {
92     return;
93   }
94   LOG_INFO << "Shutting down rpc::Server on: "
95            << net_acceptor_->local_address();
96   if ( !selector_.IsInSelectThread() ) {
97     shutdown_completed_.Reset();
98     selector_.RunInSelectLoop(NewCallback(this, &Server::Shutdown));
99     if ( !shutdown_completed_.Wait(5000) ) {
100       LOG_ERROR << "Timeout waiting for server shutdown";
101       return;
102     }
103     return;
104   }
105
106   //
107   // selector thread
108   //
109   const uint16 port = net_acceptor_->local_address().port();
110   net_acceptor_->Close();
111   CHECK_EQ(net_acceptor_->state(), net::NetAcceptor::DISCONNECTED)
112       << "Failed to shutdown server";
113   LOG_INFO << "rpc::Server shutdown (was on port " << port << ")";
114
115   if ( open_completed_callback_ &&
116        !open_completed_callback_->is_permanent() ) {
117     delete open_completed_callback_;
118   }
119   open_completed_callback_ = NULL;
120
121   // SIGNAL has to be the last statement! The destructor may be waiting us.
122   shutdown_completed_.Signal();
123   return;
124 }
125
126 //////////////////////////////////////////////////////////////////////
127 //
128 // Methods available only from the selector thread.
129 //
130 void Server::OpenInSelectThread(net::HostPort addr) {
131   CHECK(selector_.IsInSelectThread());
132   net_acceptor_->Listen(addr);
133   if ( IsOpen() ) {
134     LOG_INFO << "rpc::Server listening on: " << net_acceptor_->local_address();
135   } else {
136     LOG_ERROR << "Open failed for address: " << addr
137               << " , error: " << GetLastSystemErrorDescription();
138   }
139   if ( open_completed_callback_ ) {
140     LOG_DEBUG << "Running open_completed_callback_(" << std::boolalpha
141               << IsOpen() << ")";
142     open_completed_callback_->Run(IsOpen());
143     open_completed_callback_ = NULL;
144   }
145   open_completed_.Signal();
146 }
147
148 bool Server::AcceptorFilterHandler(const net::HostPort& peer_address) {
149   // TODO(cosmin): limit accept rate
150   return true;
151 }
152 void Server::AcceptorAcceptHandler(net::NetConnection* peer_connection) {
153   LOG_INFO << "New RPC Connection from " << peer_connection->remote_address();
154
155   // Create the RPC connection. Uses auto_delete_on_close.
156   new rpc::ServerConnection(&selector_, true, peer_connection, executor_);
157 };
158 }
Note: See TracBrowser for help on using the browser.