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