GNU Radio Manual and C++ API Reference 3.9.4.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 * 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>
18#include <boost/date_time/posix_time/posix_time.hpp>
19#include <memory>
20
21namespace {
22// Time, in milliseconds, to wait between checks to the Thrift runtime to see if
23// it has fully initialized.
24static constexpr unsigned int THRIFTAPPLICATION_ACTIVATION_TIMEOUT_MS(200);
25}; // namespace
26
27namespace apache {
28namespace thrift {
29namespace server {
30class 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{
42public:
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
73template <typename TserverBase, typename TserverClass>
75{
76public:
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
98protected:
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
152private:
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
185template <typename TserverBase, typename TserverClass>
187
188template <typename TserverBase, typename TserverClass>
190 TserverClass* _app)
191 : d_lock(), d_thirft_is_running(false)
192{
194 d_application = _app;
195}
196
197template <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
226template <typename TserverBase, typename TserverClass>
227const std::vector<std::string>
229{
230 std::vector<std::string> ep;
231 ep.push_back(p_impl->d_endpointStr);
232 return ep;
233}
234
235template <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
243template <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
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
virtual TserverBase * i_impl()=0
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:180
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