GNU Radio Manual and C++ API Reference  3.8.1.0
The Free & Open Software Radio Ecosystem
thrift_application_base.h
Go to the documentation of this file.
1 /* -*- c++ -*- */
2 /*
3  * Copyright 2015 Free Software Foundation, Inc.
4  *
5  * This file is part of GNU Radio
6  *
7  * GNU Radio is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 3, or (at your option)
10  * any later version.
11  *
12  * GNU Radio is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with GNU Radio; see the file COPYING. If not, write to
19  * the Free Software Foundation, Inc., 51 Franklin Street,
20  * Boston, MA 02110-1301, USA.
21  */
22 
23 #ifndef THRIFT_APPLICATION_BASE_H
24 #define THRIFT_APPLICATION_BASE_H
25 
26 #include <gnuradio/api.h>
27 #include <gnuradio/logger.h>
28 #include <gnuradio/prefs.h>
29 #include <gnuradio/thread/thread.h>
30 #include <boost/date_time/posix_time/posix_time.hpp>
31 #include <boost/scoped_ptr.hpp>
32 
33 namespace {
34 // Time, in milliseconds, to wait between checks to the Thrift runtime to see if
35 // it has fully initialized.
36 static const unsigned int THRIFTAPPLICATION_ACTIVATION_TIMEOUT_MS(200);
37 }; // namespace
38 
39 namespace apache {
40 namespace thrift {
41 namespace server {
42 class TServer;
43 }
44 } // namespace thrift
45 } // namespace apache
46 
47 /*!
48  * \brief Class to be statically initialized by thrift_application_base. Used
49  * to store state for thrift_application_base's singleton functions.
50  */
51 
53 {
54 public:
56  : d_application_initialized(false), d_endpointStr(""), d_start_thrift_thread()
57  {
58  ;
59  }
60 
61  // Used to ensure the Thrift runtime is initialized on the first call to ::i().
63  // Stores the generated endpoint string after the Thrift runtime has initialized.
64  std::string d_endpointStr;
65  // Thread to execute the Thrift runtime's blocking serve() function.
66  boost::shared_ptr<gr::thread::thread> d_start_thrift_thread;
67 };
68 
69 /*!
70  * \brief Base class for a Thrift application with a singleton with
71  * instance function thrift_application_base::i(). Lazy initialization
72  * is used to start the Thrift runtime, therefore the Thrift runtime
73  * is not started unless thrift_application_base::i() is called at
74  * least once. This typically means that at least one rpc variable
75  * must be registered by a block before the runtime will start.
76  *
77  * \param TserverBase Template parameter naming the type of the server
78  * base, which is typically rpcserverbase.
79  * \param TserverClass Template parameter naming the eventual type of
80  * the fully derived application.
81  * \param _app Reference to the fully derived application instance to
82  * be returned by thrift_application_base::i().
83  */
84 
85 template <typename TserverBase, typename TserverClass>
87 {
88 public:
89  thrift_application_base(TserverClass* _app);
90 
91  /*!
92  * Destructor for the application. Since shutdown and cleanup of the
93  * runtime is typically custom to a particular booter
94  * implementation, this must be implemented as a specialized function
95  * for a particular booter. Thus a template implementation is not
96  * provided here.
97  */
99 
100  /*!
101  * The application singleton instance function.
102  */
103  static TserverBase* i();
104 
105  /*!
106  * Returns the endpoint string of this application.
107  */
108  static const std::vector<std::string> endpoints();
109 
110 protected:
111  /*!
112  * Allows this application's booter to set the endpoint string after
113  * the Thrift runtime has initialized.
114  *
115  * \param[in] endpoint The endpoint string reported by this class.
116  */
117  void set_endpoint(const std::string& endpoint);
118 
119  virtual TserverBase* i_impl() = 0;
120 
121  /*!
122  * Reference to the fully derived application instance.
123  */
124  static TserverClass* d_application;
125 
126  /*!
127  * Reference to the Thrift runtime.
128  */
129  boost::scoped_ptr<apache::thrift::server::TServer> d_thriftserver;
130 
131  /*!
132  * Max number of attempts when checking the Thrift runtime for
133  * Initialization before giving up. Set in the Thrift config file
134  * (see \ref ctrlport_thrift_prefs).
135  */
136  static const unsigned int d_default_max_init_attempts;
137 
138  /*!
139  * Default port for the runtime to listen on, if a static port is
140  * not specified. Set in the Thrift config file (see \ref
141  * ctrlport_thrift_prefs).
142  */
143  static const unsigned int d_default_thrift_port;
144 
145  /*!
146  * Maximum number of threads to create when serving multiple rpc
147  * clients. Set in the Thrift config file (see \ref
148  * ctrlport_thrift_prefs).
149  */
150  static const unsigned int d_default_num_thrift_threads;
151 
152  /*!
153  * Default packet size for the IP payload of thrift packets. Set in
154  * the Thrift config file (see \ref ctrlport_thrift_prefs).
155  */
156  static const unsigned int d_default_thrift_buffer_size;
157 
158  /*!
159  * <a href="https://wiki.gnuradio.org/index.php/Logging" target="_blank">Logging</a>
160  * instances.
161  */
162  gr::logger_ptr d_logger, d_debug_logger;
163 
164 private:
165  // Function to be called in a separate thread to invoke the blocking
166  // ThriftServer::serve() function. Must be specialized for a particular
167  // booter implementation, therefore a template implementation is
168  // not provided here.
169  void start_thrift();
170 
171  // Non-blocking function that returns true when the Thrift
172  // runtime has finished initialization. Must be implemented
173  // as a specialized template function for a particular booter
174  // implementation, therefore template implementation is not
175  // provided here.
176  bool application_started();
177 
178  // Internal function to start the initialization of the runtime.
179  // Since this singleton uses lazy instantiation, this function
180  // will be called on the first call to the instance function ::i(),
181  // and since ::i() is static, this function must be static as well.
182  static void start_application();
183 
184  // Pointer to the structure containing statically allocated
185  // state information for the applicaiton_base singleton.
186  static boost::scoped_ptr<thrift_application_base_impl> p_impl;
187 
188  // Mutex to protect the endpoint string.
189  gr::thread::mutex d_lock;
190 
191  // Will be set to true by a the application_started() function,
192  // specialized for a particular booter implementation, once the
193  // thrift runtime has successfully initialized.
194  bool d_thirft_is_running;
195 };
196 
197 template <typename TserverBase, typename TserverClass>
199 
200 template <typename TserverBase, typename TserverClass>
202  TserverClass* _app)
203  : d_lock(), d_thirft_is_running(false)
204 {
206  d_application = _app;
207 }
208 
209 template <typename TserverBase, typename TserverClass>
211 {
212  unsigned int max_init_attempts =
213  static_cast<unsigned int>(gr::prefs::singleton()->get_long(
214  "thrift", "init_attempts", d_default_max_init_attempts));
215 
216  if (!p_impl->d_application_initialized) {
217  p_impl->d_start_thrift_thread.reset((new gr::thread::thread(
218  boost::bind(&thrift_application_base::start_thrift, d_application))));
219 
220  bool app_started(false);
221  for (unsigned int attempts(0); (!app_started && attempts < max_init_attempts);
222  ++attempts) {
223  boost::this_thread::sleep(
224  boost::posix_time::milliseconds(THRIFTAPPLICATION_ACTIVATION_TIMEOUT_MS));
225  app_started = d_application->application_started();
226  }
227 
228  if (!app_started) {
229  GR_WARN("thrift_application_base",
230  "thrift_application_base::start_application(), "
231  "timeout waiting to port number might have failed?");
232  }
233 
234  p_impl->d_application_initialized = true;
235  }
236 }
237 
238 template <typename TserverBase, typename TserverClass>
239 const std::vector<std::string>
241 {
242  std::vector<std::string> ep;
243  ep.push_back(p_impl->d_endpointStr);
244  return ep;
245 }
246 
247 template <typename TserverBase, typename TserverClass>
249  const std::string& endpoint)
250 {
251  gr::thread::scoped_lock guard(d_lock);
252  p_impl->d_endpointStr = endpoint;
253 }
254 
255 template <typename TserverBase, typename TserverClass>
257 {
258  if (!p_impl->d_application_initialized) {
259  start_application();
260  }
261  return d_application->i_impl();
262 }
263 
264 #endif
boost::unique_lock< boost::mutex > scoped_lock
Definition: thread.h:49
#define GR_WARN(name, msg)
Definition: logger.h:188
gr::logger_ptr d_logger
Definition: thrift_application_base.h:162
std::string d_endpointStr
Definition: thrift_application_base.h:64
static const unsigned int d_default_max_init_attempts
Definition: thrift_application_base.h:136
static const std::vector< std::string > endpoints()
Definition: thrift_application_base.h:240
static TserverClass * d_application
Definition: thrift_application_base.h:124
static const unsigned int d_default_num_thrift_threads
Definition: thrift_application_base.h:150
boost::thread thread
Definition: thread.h:47
static TserverBase * i()
Definition: thrift_application_base.h:256
virtual long get_long(const std::string &section, const std::string &option, long default_val)
If option exists and value can be converted to long, return it; else default_val. ...
boost::scoped_ptr< apache::thrift::server::TServer > d_thriftserver
Definition: thrift_application_base.h:129
Base class for a Thrift application with a singleton with instance function thrift_application_base::...
Definition: thrift_application_base.h:86
GR_RUNTIME_API bool configure_default_loggers(gr::logger_ptr &l, gr::logger_ptr &d, const std::string name)
Class to be statically initialized by thrift_application_base. Used to store state for thrift_applica...
Definition: thrift_application_base.h:52
thrift_application_base(TserverClass *_app)
Definition: thrift_application_base.h:201
Definition: thrift_application_base.h:39
bool d_application_initialized
Definition: thrift_application_base.h:62
static const unsigned int d_default_thrift_port
Definition: thrift_application_base.h:143
log4cpp::Category * logger_ptr
GR_LOG macrosThese macros wrap the standard LOG4CPP_LEVEL macros. The availablie macros are: LOG_DEBU...
Definition: logger.h:71
boost::mutex mutex
Definition: thread.h:48
static prefs * singleton()
thrift_application_base_impl()
Definition: thrift_application_base.h:55
boost::shared_ptr< gr::thread::thread > d_start_thrift_thread
Definition: thrift_application_base.h:66
static const unsigned int d_default_thrift_buffer_size
Definition: thrift_application_base.h:156
gr::logger_ptr d_debug_logger
Definition: thrift_application_base.h:162
void set_endpoint(const std::string &endpoint)
Definition: thrift_application_base.h:248