summaryrefslogtreecommitdiff
path: root/gnuradio-runtime/include/gnuradio/thrift_application_base.h
diff options
context:
space:
mode:
Diffstat (limited to 'gnuradio-runtime/include/gnuradio/thrift_application_base.h')
-rw-r--r--gnuradio-runtime/include/gnuradio/thrift_application_base.h253
1 files changed, 253 insertions, 0 deletions
diff --git a/gnuradio-runtime/include/gnuradio/thrift_application_base.h b/gnuradio-runtime/include/gnuradio/thrift_application_base.h
new file mode 100644
index 0000000000..aa50c55dc8
--- /dev/null
+++ b/gnuradio-runtime/include/gnuradio/thrift_application_base.h
@@ -0,0 +1,253 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2015 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef THRIFT_APPLICATION_BASE_H
+#define THRIFT_APPLICATION_BASE_H
+
+#include <gnuradio/api.h>
+#include <gnuradio/logger.h>
+#include <gnuradio/prefs.h>
+#include <gnuradio/thread/thread.h>
+#include <boost/date_time/posix_time/posix_time.hpp>
+
+namespace {
+ // Time, in milliseconds, to wait between checks to the Thrift runtime to see if
+ // it has fully initialized.
+ static const unsigned int THRIFTAPPLICATION_ACTIVATION_TIMEOUT_MS(200);
+};
+
+namespace apache { namespace thrift { namespace server { class TServer; } } }
+
+/*!
+ * \brief Class to be statically initialized by thrift_application_base. Used
+ * to store state for thrift_application_base's singleton functions.
+ */
+
+class thrift_application_base_impl
+{
+public:
+ thrift_application_base_impl() :
+ d_application_initilized(false),
+ d_endpointStr(""),
+ d_start_thrift_thread() {;}
+
+ // Used to ensure the Thrift runtime is initialized on the first call to ::i().
+ bool d_application_initilized;
+ // Stores the generated endpoint string after the Thrift runtime has initialized.
+ std::string d_endpointStr;
+ // Thread to execute the Thrift runtime's blocking serve() function.
+ boost::shared_ptr<gr::thread::thread> d_start_thrift_thread;
+};
+
+/*!
+ * \brief Base class for a Thrift application with a singleton with
+ * instance function thrift_application_base::i(). Lazy initialization
+ * is used to start the Thrift runtime, therefore the Thrift runtime
+ * is not started unless thrift_application_base::i() is called at
+ * least once. This typically means that at least one rpc variable
+ * must be registered by a block before the runtime will start.
+ *
+ * \param TserverBase Template parameter naming the type of the server
+ * base, which is typically rpcserverbase.
+ * \param TserverClass Template parameter naming the eventual type of
+ * the fully derived application.
+ * \param _app Reference to the fully derived application instance to
+ * be returned by thrift_application_base::i().
+ */
+
+template<typename TserverBase, typename TserverClass>
+class thrift_application_base
+{
+public:
+ thrift_application_base(TserverClass* _app);
+
+ /*!
+ * Destructor for the application. Since shutdown and cleanup of the
+ * runtime is typically custom to a particular booter
+ * implementation, this must be implemented as a specalized function
+ * for a particular booter. Thus a template implementation is not
+ * provided here.
+ */
+ ~thrift_application_base();
+
+ /*!
+ * The application singleton instance function.
+ */
+ static TserverBase* i();
+
+ /*!
+ * Returns the endpoint string of this application.
+ */
+ static const std::vector<std::string> endpoints();
+
+protected:
+ /*!
+ * Allows this application's booter to set the endpoint string after
+ * the Thrift runtime has initialized.
+ *
+ * \param[in] endpoint The endpoint string reported by this class.
+ */
+ void set_endpoint(const std::string& endpoint);
+
+ virtual TserverBase* i_impl() = 0;
+
+ /*!
+ * Reference to the fully derived application instance.
+ */
+ static TserverClass* d_application;
+
+ /*!
+ * Reference to the Thrift runtime.
+ */
+ std::auto_ptr<apache::thrift::server::TServer> d_thriftserver;
+
+ /*!
+ * Max number of attempts when checking the Thrift runtime for
+ * Initialization before giving up. Set in the Thrift config file
+ * (see \ref ctrlport_thrift_prefs).
+ */
+ static const unsigned int d_default_max_init_attempts;
+
+ /*!
+ * Default port for the runtime to listen on, if a static port is
+ * not specified. Set in the Thrift config file (see \ref
+ * ctrlport_thrift_prefs).
+ */
+ static const unsigned int d_default_thrift_port;
+
+ /*!
+ * Maximum number of threads to create when serving multiple rpc
+ * clients. Set in the Thrift config file (see \ref
+ * ctrlport_thrift_prefs).
+ */
+ static const unsigned int d_default_num_thrift_threads;
+
+ /*!
+ * Default packet size for the IP payload of thrift packets. Set in
+ * the Thrift config file (see \ref ctrlport_thrift_prefs).
+ */
+ static const unsigned int d_default_thrift_buffer_size;
+
+ /*!
+ * \ref page_logger instances.
+ */
+ gr::logger_ptr d_logger, d_debug_logger;
+
+private:
+
+ // Function to be called in a separate thread to invoke the blocking
+ // ThriftServer::serve() function. Must be specialized for a particular
+ // booter implementation, therefore a template implementation is
+ // not provided here.
+ void start_thrift();
+
+ // Non-blocking function that returns true when the Thrift
+ // runtime has finished initialization. Must be implemented
+ // as a specialized template function for a particular booter
+ // implementation, therefore template implementation is not
+ // provided here.
+ bool application_started();
+
+ // Internal function to start the initialization of the runtime.
+ // Since this singleton uses lazy instantiation, this function
+ // will be called on the first call to the instance function ::i(),
+ // and since ::i() is static, this function must be static as well.
+ static void start_application();
+
+ // Pointer to the structure containing staticly allocated
+ // state information for the applicaiton_base singleton.
+ static std::auto_ptr<thrift_application_base_impl > p_impl;
+
+ // Mutex to protect the endpoint string.
+ gr::thread::mutex d_lock;
+
+ // Will be set to true by a the application_started() function,
+ // specialized for a particular booter implementation, once the
+ // thrift runtime has successfully initialized.
+ bool d_thirft_is_running;
+};
+
+template<typename TserverBase, typename TserverClass>
+TserverClass* thrift_application_base<TserverBase, TserverClass>::d_application(0);
+
+template<typename TserverBase, typename TserverClass>
+thrift_application_base<TserverBase, TserverClass>::thrift_application_base(TserverClass* _app)
+ : d_lock(),
+ d_thirft_is_running(false)
+{
+ gr::configure_default_loggers(d_logger, d_debug_logger, "controlport");
+ d_application = _app;
+ //GR_LOG_DEBUG(d_debug_logger, "thrift_application_base: ctor");
+}
+
+template<typename TserverBase, typename TserverClass>
+void thrift_application_base<TserverBase, TserverClass>::start_application()
+{
+ //std::cerr << "thrift_application_base: start_application" << std::endl;
+
+ unsigned int max_init_attempts = \
+ static_cast<unsigned int>(gr::prefs::singleton()->get_long("thrift", "init_attempts",
+ d_default_max_init_attempts));
+
+ if(!p_impl->d_application_initilized) {
+ p_impl->d_start_thrift_thread.reset(
+ (new gr::thread::thread(boost::bind(&thrift_application_base::start_thrift, d_application))));
+
+ bool app_started(false);
+ for(unsigned int attempts(0); (!app_started && attempts < max_init_attempts); ++attempts) {
+ boost::this_thread::sleep(boost::posix_time::milliseconds(THRIFTAPPLICATION_ACTIVATION_TIMEOUT_MS));
+ app_started = d_application->application_started();
+ }
+
+ if(!app_started) {
+ std::cerr << "thrift_application_base::start_application(), timeout waiting to port number might have failed?" << std::endl;
+ }
+
+ p_impl->d_application_initilized = true;
+ }
+}
+
+template<typename TserverBase, typename TserverClass>
+const std::vector<std::string> thrift_application_base<TserverBase, TserverClass>::endpoints()
+{
+ std::vector<std::string> ep;
+ ep.push_back(p_impl->d_endpointStr);
+ return ep;
+}
+
+template<typename TserverBase, typename TserverClass>
+void thrift_application_base<TserverBase, TserverClass>::set_endpoint(const std::string& endpoint)
+{
+ gr::thread::scoped_lock guard(d_lock);
+ p_impl->d_endpointStr = endpoint;
+}
+
+template<typename TserverBase, typename TserverClass>
+TserverBase* thrift_application_base<TserverBase, TserverClass>::i()
+{
+ if(!p_impl->d_application_initilized) {
+ start_application();
+ }
+ return d_application->i_impl();
+}
+
+#endif