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