diff options
Diffstat (limited to 'gnuradio-runtime/include/gnuradio')
11 files changed, 892 insertions, 18 deletions
diff --git a/gnuradio-runtime/include/gnuradio/CMakeLists.txt b/gnuradio-runtime/include/gnuradio/CMakeLists.txt index 3fc2fe7bd8..472f91847b 100644 --- a/gnuradio-runtime/include/gnuradio/CMakeLists.txt +++ b/gnuradio-runtime/include/gnuradio/CMakeLists.txt @@ -86,6 +86,16 @@ install(FILES COMPONENT "runtime_devel" ) +if(THRIFT_FOUND) +install(FILES + rpcserver_booter_thrift.h + thrift_application_base.h + thrift_server_template.h + DESTINATION ${GR_INCLUDE_DIR}/gnuradio + COMPONENT "runtime_devel" +) +endif(THRIFT_FOUND) + ########################################################################## # Configure logger ########################################################################## diff --git a/gnuradio-runtime/include/gnuradio/prefs.h b/gnuradio-runtime/include/gnuradio/prefs.h index a9a28586ab..4dc92b3631 100644 --- a/gnuradio-runtime/include/gnuradio/prefs.h +++ b/gnuradio-runtime/include/gnuradio/prefs.h @@ -1,6 +1,6 @@ /* -*- c++ -*- */ /* - * Copyright 2006,2013 Free Software Foundation, Inc. + * Copyright 2006,2013,2015 Free Software Foundation, Inc. * * This file is part of GNU Radio * @@ -47,10 +47,38 @@ namespace gr { public: static prefs *singleton(); + /*! + * \brief Creates an object to read preference files. + * + * \details + * + * If no file name is given (empty arg list or ""), this opens up + * the standard GNU Radio configuration files in + * prefix/etc/gnuradio/conf.d as well as ~/.gnuradio/config.conf. + * + * Only access this through the singleton defined here: + * \code + * prefs *p = prefs::singleton(); + * \endcode + */ prefs(); + virtual ~prefs(); /*! + * If specifying a file name, this opens that specific + * configuration file of the standard form containing sections and + * key-value pairs: + * + * \code + * [SectionName] + * key0 = value0 + * key1 = value1 + * \endcode + */ + void add_config_file(const std::string &configfile); + + /*! * \brief Returns the configuration options as a string. */ std::string to_string(); @@ -137,7 +165,7 @@ namespace gr { protected: virtual std::vector<std::string> _sys_prefs_filenames(); - virtual void _read_files(); + virtual std::string _read_files(const std::vector<std::string> &filenames); virtual void _convert_to_map(const std::string &conf); virtual char * option_to_env(std::string section, std::string option); diff --git a/gnuradio-runtime/include/gnuradio/rpcbufferedget.h b/gnuradio-runtime/include/gnuradio/rpcbufferedget.h new file mode 100644 index 0000000000..ebd740b1f8 --- /dev/null +++ b/gnuradio-runtime/include/gnuradio/rpcbufferedget.h @@ -0,0 +1,65 @@ +/* -*- 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 RPCBUFFEREDGET_H +#define RPCBUFFEREDGET_H + +#include <boost/thread/condition_variable.hpp> +#include <boost/thread/mutex.hpp> +#include <stdio.h> + +template<typename TdataType> +class rpcbufferedget { +public: + rpcbufferedget(const unsigned int init_buffer_size = 4096) : + d_data_needed(false), d_data_ready(), d_buffer_lock(), d_buffer(init_buffer_size) {;} + + ~rpcbufferedget() { + d_data_ready.notify_all(); + } + + void offer_data(const TdataType& data) { + if (!d_data_needed) + return; + { + boost::mutex::scoped_lock lock(d_buffer_lock); + d_buffer = data; + d_data_needed = false; + } + d_data_ready.notify_one(); + } + + TdataType get() { + d_data_needed = true; + boost::mutex::scoped_lock lock(d_buffer_lock); + d_data_ready.wait(lock); + return d_buffer; + } + +private: + bool d_data_needed; + boost::condition_variable d_data_ready; + boost::mutex d_buffer_lock; + TdataType d_buffer; +}; + +#endif diff --git a/gnuradio-runtime/include/gnuradio/rpcmanager.h b/gnuradio-runtime/include/gnuradio/rpcmanager.h index 5635572a8b..e7ee4c4942 100644 --- a/gnuradio-runtime/include/gnuradio/rpcmanager.h +++ b/gnuradio-runtime/include/gnuradio/rpcmanager.h @@ -54,7 +54,7 @@ class GR_RUNTIME_API rpcmanager : public virtual rpcmanager_base static bool booter_registered; static bool aggregator_registered; static void rpcserver_booter_base_sptr_dest(rpcserver_booter_base* b) {;} - static rpcserver_booter_base* boot; + static std::auto_ptr<rpcserver_booter_base> boot; static std::auto_ptr<rpcserver_booter_aggregator> aggregator; }; diff --git a/gnuradio-runtime/include/gnuradio/rpcpmtconverters_thrift.h b/gnuradio-runtime/include/gnuradio/rpcpmtconverters_thrift.h new file mode 100644 index 0000000000..6523165a11 --- /dev/null +++ b/gnuradio-runtime/include/gnuradio/rpcpmtconverters_thrift.h @@ -0,0 +1,74 @@ +/* + * Copyright 2014,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 RPCPMTCONVERTERS_THRIFT_H +#define RPCPMTCONVERTERS_THRIFT_H + +#include <pmt/pmt.h> +#include <boost/noncopyable.hpp> +#include <boost/ptr_container/ptr_map.hpp> +#include "thrift/gnuradio_types.h" + + +namespace rpcpmtconverter +{ + GNURadio::Knob from_pmt(const pmt::pmt_t& knob); + + struct to_pmt_f { + to_pmt_f() {;} + virtual pmt::pmt_t operator()(const GNURadio::Knob& knob); + }; + + struct to_pmt_byte_f : public to_pmt_f { pmt::pmt_t operator()(const GNURadio::Knob& knob); }; + struct to_pmt_short_f : public to_pmt_f { pmt::pmt_t operator()(const GNURadio::Knob& knob); }; + struct to_pmt_int_f : public to_pmt_f { pmt::pmt_t operator()(const GNURadio::Knob& knob); }; + struct to_pmt_long_f : public to_pmt_f { pmt::pmt_t operator()(const GNURadio::Knob& knob); }; + struct to_pmt_double_f : public to_pmt_f { pmt::pmt_t operator()(const GNURadio::Knob& knob); }; + struct to_pmt_string_f : public to_pmt_f { pmt::pmt_t operator()(const GNURadio::Knob& knob); }; + struct to_pmt_bool_f : public to_pmt_f { pmt::pmt_t operator()(const GNURadio::Knob& knob); }; + struct to_pmt_complex_f: public to_pmt_f { pmt::pmt_t operator()(const GNURadio::Knob& knob); }; + struct to_pmt_f32vect_f: public to_pmt_f { pmt::pmt_t operator()(const GNURadio::Knob& knob); }; + struct to_pmt_f64vect_f: public to_pmt_f { pmt::pmt_t operator()(const GNURadio::Knob& knob); }; + struct to_pmt_s64vect_f: public to_pmt_f { pmt::pmt_t operator()(const GNURadio::Knob& knob); }; + struct to_pmt_s32vect_f: public to_pmt_f { pmt::pmt_t operator()(const GNURadio::Knob& knob); }; + struct to_pmt_s16vect_f: public to_pmt_f { pmt::pmt_t operator()(const GNURadio::Knob& knob); }; + struct to_pmt_s8vect_f : public to_pmt_f { pmt::pmt_t operator()(const GNURadio::Knob& knob); }; + struct to_pmt_c32vect_f: public to_pmt_f { pmt::pmt_t operator()(const GNURadio::Knob& knob); }; + + class To_PMT : private boost::noncopyable { + public: + static To_PMT instance; + template<typename TO_PMT_F> friend struct to_pmt_reg; + pmt::pmt_t operator()(const GNURadio::Knob& knob); + + protected: + boost::ptr_map<GNURadio::BaseTypes::type, to_pmt_f> to_pmt_map; + + private: + To_PMT() {;} + }; + + template<typename TO_PMT_F> struct to_pmt_reg { + to_pmt_reg(To_PMT& instance, const GNURadio::BaseTypes::type type); + }; +} + +#endif /* RPCPMTCONVERTERS_THRIFT_H */ diff --git a/gnuradio-runtime/include/gnuradio/rpcregisterhelpers.h b/gnuradio-runtime/include/gnuradio/rpcregisterhelpers.h index 0999dea747..f82f5ed0aa 100644 --- a/gnuradio-runtime/include/gnuradio/rpcregisterhelpers.h +++ b/gnuradio-runtime/include/gnuradio/rpcregisterhelpers.h @@ -672,7 +672,7 @@ struct rpcbasic_register_set : public rpcbasic_base d_minpriv = minpriv_; d_display = display_; d_object = dynamic_cast<T*>(global_block_registry.block_lookup(pmt::intern(block_alias)).get()); -#ifdef RPCSERVER_ENABLED +#ifdef GR_RPCSERVER_ENABLED callbackregister_base::configureCallback_t extractor(new rpcbasic_extractor<T,Tto>(d_object, function), minpriv_, std::string(units_), @@ -726,7 +726,7 @@ struct rpcbasic_register_set : public rpcbasic_base d_minpriv = minpriv_; d_display = display_; d_object = obj; -#ifdef RPCSERVER_ENABLED +#ifdef GR_RPCSERVER_ENABLED callbackregister_base::configureCallback_t extractor(new rpcbasic_extractor<T,Tto>(d_object, function), minpriv_, std::string(units_), @@ -741,7 +741,7 @@ struct rpcbasic_register_set : public rpcbasic_base ~rpcbasic_register_set() { -#ifdef RPCSERVER_ENABLED +#ifdef GR_RPCSERVER_ENABLED rpcmanager::get()->i()->unregisterConfigureCallback(d_id); #endif } @@ -830,7 +830,7 @@ struct rpcbasic_register_trigger : public rpcbasic_base d_desc = desc_; d_minpriv = minpriv_; d_object = dynamic_cast<T*>(global_block_registry.block_lookup(pmt::intern(block_alias)).get()); -#ifdef RPCSERVER_ENABLED +#ifdef GR_RPCSERVER_ENABLED callbackregister_base::configureCallback_t extractor(new rpcbasic_extractor<T,void>(d_object, function), minpriv_, std::string(desc_)); @@ -870,7 +870,7 @@ struct rpcbasic_register_trigger : public rpcbasic_base d_desc = desc_; d_minpriv = minpriv_; d_object = obj; -#ifdef RPCSERVER_ENABLED +#ifdef GR_RPCSERVER_ENABLED callbackregister_base::configureCallback_t extractor(new rpcbasic_extractor<T,void>(d_object, function), minpriv_, std::string(desc_)); @@ -884,7 +884,7 @@ struct rpcbasic_register_trigger : public rpcbasic_base ~rpcbasic_register_trigger() { -#ifdef RPCSERVER_ENABLED +#ifdef GR_RPCSERVER_ENABLED rpcmanager::get()->i()->unregisterConfigureCallback(d_id); #endif } @@ -988,7 +988,7 @@ public: d_minpriv = minpriv_; d_display = display_; d_object = dynamic_cast<T*>(global_block_registry.block_lookup(pmt::intern(block_alias)).get()); -#ifdef RPCSERVER_ENABLED +#ifdef GR_RPCSERVER_ENABLED callbackregister_base::queryCallback_t inserter(new rpcbasic_inserter<T,Tfrom>(d_object, function), minpriv_, std::string(units_), display_, std::string(desc_), min, max, def); @@ -1022,7 +1022,7 @@ public: d_minpriv = minpriv_; d_display = display_; d_object = dynamic_cast<T*>(global_block_registry.block_lookup(pmt::intern(block_alias)).get()); -#ifdef RPCSERVER_ENABLED +#ifdef GR_RPCSERVER_ENABLED callbackregister_base::queryCallback_t inserter(new rpcbasic_inserter<T,Tfrom>(d_object, (Tfrom (T::*)())function), minpriv_, std::string(units_), display_, std::string(desc_), min, max, def); @@ -1076,7 +1076,7 @@ public: d_minpriv = minpriv_; d_display = display_; d_object = obj; -#ifdef RPCSERVER_ENABLED +#ifdef GR_RPCSERVER_ENABLED callbackregister_base::queryCallback_t inserter(new rpcbasic_inserter<T,Tfrom>(d_object, function), minpriv_, std::string(units_), display_, std::string(desc_), min, max, def); @@ -1111,7 +1111,7 @@ public: d_minpriv = minpriv_; d_display = display_; d_object = obj; -#ifdef RPCSERVER_ENABLED +#ifdef GR_RPCSERVER_ENABLED callbackregister_base::queryCallback_t inserter(new rpcbasic_inserter<T,Tfrom>(d_object, (Tfrom (T::*)())function), minpriv_, std::string(units_), display_, std::string(desc_), min, max, def); @@ -1125,7 +1125,7 @@ public: ~rpcbasic_register_get() { -#ifdef RPCSERVER_ENABLED +#ifdef GR_RPCSERVER_ENABLED rpcmanager::get()->i()->unregisterQueryCallback(d_id); #endif } diff --git a/gnuradio-runtime/include/gnuradio/rpcserver_booter_thrift.h b/gnuradio-runtime/include/gnuradio/rpcserver_booter_thrift.h new file mode 100644 index 0000000000..28900a4670 --- /dev/null +++ b/gnuradio-runtime/include/gnuradio/rpcserver_booter_thrift.h @@ -0,0 +1,52 @@ +/* -*- 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 RPCSERVER_BOOTER_THRIFT_H +#define RPCSERVER_BOOTER_THRIFT_H + +#include <gnuradio/rpcserver_booter_base.h> +#include <gnuradio/thrift_server_template.h> +#include "thrift/ControlPort.h" + +class rpcserver_base; +class rpcserver_thrift; + +class rpcserver_booter_thrift + : public virtual rpcserver_booter_base, + public virtual thrift_server_template<rpcserver_base, + rpcserver_thrift, + rpcserver_booter_thrift, + boost::shared_ptr<GNURadio::ControlPortIf> > +{ + public: + rpcserver_booter_thrift(); + ~rpcserver_booter_thrift(); + + rpcserver_base* i(); + const std::string & type() {return d_type;} + const std::vector<std::string> endpoints(); + + private: + std::string d_type; +}; + +#endif /* RPCSERVER_BOOTER_THRIFT_H */ diff --git a/gnuradio-runtime/include/gnuradio/rpcserver_selector.h b/gnuradio-runtime/include/gnuradio/rpcserver_selector.h index 8a14f78d99..31ab6cea0b 100644 --- a/gnuradio-runtime/include/gnuradio/rpcserver_selector.h +++ b/gnuradio-runtime/include/gnuradio/rpcserver_selector.h @@ -23,10 +23,12 @@ #ifndef RPCSERVER_SELECTOR #define RPCSERVER_SELECTOR -//#define RPCSERVER_ENABLED +#include <gnuradio/config.h> -//#define RPCSERVER_ICE -//#define RPCSERVER_ERLANG -//#define RPCSERVER_XMLRPC +//#define GR_RPCSERVER_ENABLED +//#define GR_RPCSERVER_ICE +//#define GR_RPCSERVER_THRIFT +//#define GR_RPCSERVER_ERLANG +//#define GR_RPCSERVER_XMLRPC #endif diff --git a/gnuradio-runtime/include/gnuradio/rpcserver_thrift.h b/gnuradio-runtime/include/gnuradio/rpcserver_thrift.h new file mode 100644 index 0000000000..027a9ea75e --- /dev/null +++ b/gnuradio-runtime/include/gnuradio/rpcserver_thrift.h @@ -0,0 +1,230 @@ +/* -*- c++ -*- */ +/* + * Copyright 2014,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 RPCSERVER_THRIFT_H +#define RPCSERVER_THRIFT_H + +#include <gnuradio/rpcserver_base.h> +#include <gnuradio/rpcpmtconverters_thrift.h> +#include <string> +#include <iostream> +#include <sstream> +#include <map> +#include "thrift/ControlPort.h" +#include "thrift/gnuradio_types.h" +#include <boost/format.hpp> + +#define S(x) #x +#define S_(x) S(x) +#define S__LINE__ S_(__LINE__) + +class rpcserver_thrift : public virtual rpcserver_base, public GNURadio::ControlPortIf +{ +public: + rpcserver_thrift(); + virtual ~rpcserver_thrift(); + + void registerConfigureCallback(const std::string &id, + const configureCallback_t callback); + void unregisterConfigureCallback(const std::string &id); + + void registerQueryCallback(const std::string &id, + const queryCallback_t callback); + void unregisterQueryCallback(const std::string &id); + + void setKnobs(const GNURadio::KnobMap&); + void getKnobs(GNURadio::KnobMap&, + const GNURadio::KnobIDList&); + void getRe(GNURadio::KnobMap&, + const GNURadio::KnobIDList&); + void properties(GNURadio::KnobPropMap&, + const GNURadio::KnobIDList& knobs); + virtual void shutdown(); + + private: + typedef std::map<std::string, configureCallback_t> ConfigureCallbackMap_t; + ConfigureCallbackMap_t d_setcallbackmap; + + typedef std::map<std::string, queryCallback_t> QueryCallbackMap_t; + QueryCallbackMap_t d_getcallbackmap; + + template<typename T, typename TMap> struct set_f + : public std::unary_function<T,void> + { + set_f(TMap &_setcallbackmap, const priv_lvl_t &_cur_priv) + : d_setcallbackmap(_setcallbackmap), cur_priv(_cur_priv) + { + ; + } + + void operator()(const T& p) + { + ConfigureCallbackMap_t::const_iterator iter(d_setcallbackmap.find(p.first)); + if(iter != d_setcallbackmap.end()) { + if(cur_priv <= iter->second.priv) { + (*iter->second.callback).post(pmt::PMT_NIL, rpcpmtconverter::To_PMT::instance(p.second)); + } + else { + std::cout << "Key " << p.first << " requires PRIVLVL <= " + << iter->second.priv << " to set, currently at: " + << cur_priv << std::endl; + } + } + else { + throw apache::thrift::TApplicationException(__FILE__ " " S__LINE__); + } + } + + TMap& d_setcallbackmap; + const priv_lvl_t& cur_priv; + }; + + template<typename T, typename TMap> + struct get_f : public std::unary_function<T,void> + { + get_f(TMap &_getcallbackmap, const priv_lvl_t &_cur_priv, GNURadio::KnobMap &_outknobs) : + d_getcallbackmap(_getcallbackmap), cur_priv(_cur_priv), outknobs(_outknobs) + {} + + void operator()(const T& p) + { + QueryCallbackMap_t::const_iterator iter(d_getcallbackmap.find(p)); + if(iter != d_getcallbackmap.end()) { + if(cur_priv <= iter->second.priv) { + outknobs[p] = rpcpmtconverter::from_pmt((*iter->second.callback).retrieve()); + } + else { + std::cout << "Key " << iter->first << " requires PRIVLVL: <= " + << iter->second.priv << " to get, currently at: " + << cur_priv << std::endl; + } + } + else { + std::stringstream ss; + ss << "Ctrlport Key called with unregistered key (" << p << ")\n"; + std::cout << ss.str(); + throw apache::thrift::TApplicationException(__FILE__ " " S__LINE__); + } + } + + TMap& d_getcallbackmap; + const priv_lvl_t& cur_priv; + GNURadio::KnobMap& outknobs; + }; + + template<typename T, typename TMap, typename TKnobMap> + struct get_all_f : public std::unary_function<T,void> + { + get_all_f(TMap &_getcallbackmap, const priv_lvl_t &_cur_priv, TKnobMap &_outknobs) : + d_getcallbackmap(_getcallbackmap), cur_priv(_cur_priv), outknobs(_outknobs) + {;} + + void operator()(const T& p) + { + if(cur_priv <= p.second.priv) { + outknobs[p.first] = rpcpmtconverter::from_pmt(p.second.callback->retrieve()); + } + else { + std::cout << "Key " << p.first << " requires PRIVLVL <= " + << p.second.priv << " to get, currently at: " + << cur_priv << std::endl; + } + } + + TMap& d_getcallbackmap; + const priv_lvl_t& cur_priv; + TKnobMap& outknobs; + }; + + template<typename T, typename TMap, typename TKnobMap> + struct properties_all_f : public std::unary_function<T,void> + { + properties_all_f(QueryCallbackMap_t &_getcallbackmap, + const priv_lvl_t &_cur_priv, + GNURadio::KnobPropMap &_outknobs) + : d_getcallbackmap(_getcallbackmap), + cur_priv(_cur_priv), + outknobs(_outknobs) + {;} + + void operator()(const T& p) + { + if(cur_priv <= p.second.priv) { + GNURadio::KnobProp prop; + prop.type = GNURadio::KnobType::KNOBDOUBLE; + prop.units = p.second.units; + prop.description = p.second.description; + prop.min = rpcpmtconverter::from_pmt(p.second.min); + prop.max = rpcpmtconverter::from_pmt(p.second.max); + prop.display = static_cast<uint32_t>(p.second.display); + outknobs[p.first] = prop; + } + else { + std::cout << "Key " << p.first << " requires PRIVLVL <= " + << p.second.priv << " to get, currently at: " + << cur_priv << std::endl; + } + } + + TMap& d_getcallbackmap; + const priv_lvl_t& cur_priv; + TKnobMap& outknobs; + }; + + template<class T, typename TMap, typename TKnobMap> + struct properties_f : public std::unary_function<T,void> + { + properties_f(TMap &_getcallbackmap, const priv_lvl_t &_cur_priv, TKnobMap &_outknobs) : + d_getcallbackmap(_getcallbackmap), cur_priv(_cur_priv), outknobs(_outknobs) + {;} + + void operator()(const T& p) + { + typename TMap::const_iterator iter(d_getcallbackmap.find(p)); + if(iter != d_getcallbackmap.end()) { + if(cur_priv <= iter->second.priv) { + GNURadio::KnobProp prop; + prop.type = GNURadio::KnobType::KNOBDOUBLE; + prop.units = iter->second.units; + prop.description = iter->second.description; + prop.min = rpcpmtconverter::from_pmt(iter->second.min); + prop.max = rpcpmtconverter::from_pmt(iter->second.max); + prop.display = static_cast<uint32_t>(iter->second.display); + outknobs[p] = prop; + } + else { + std::cout << "Key " << iter->first << " requires PRIVLVL: <= " + << iter->second.priv << " to get, currently at: " << cur_priv << std::endl; + } + } + else { + throw apache::thrift::TApplicationException(__FILE__ " " S__LINE__); + } + } + + TMap& d_getcallbackmap; + const priv_lvl_t& cur_priv; + TKnobMap& outknobs; + }; +}; + +#endif /* RPCSERVER_THRIFT_H */ 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 diff --git a/gnuradio-runtime/include/gnuradio/thrift_server_template.h b/gnuradio-runtime/include/gnuradio/thrift_server_template.h new file mode 100644 index 0000000000..1e9059d920 --- /dev/null +++ b/gnuradio-runtime/include/gnuradio/thrift_server_template.h @@ -0,0 +1,160 @@ +/* -*- 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_SERVER_TEMPLATE_H +#define THRIFT_SERVER_TEMPLATE_H + +#include <gnuradio/prefs.h> +#include <gnuradio/logger.h> +#include <gnuradio/rpcserver_thrift.h> +#include <gnuradio/thrift_application_base.h> +#include <iostream> + +#include <thrift/server/TSimpleServer.h> +#include <thrift/server/TThreadPoolServer.h> +#include <thrift/concurrency/ThreadManager.h> +#include <thrift/concurrency/PlatformThreadFactory.h> +#include <thrift/transport/TServerSocket.h> +#include <thrift/transport/TBufferTransports.h> +#include "thrift/ControlPort.h" + +using namespace apache; + +template<typename TserverBase, typename TserverClass, typename TImplClass, typename TThriftClass> +class thrift_server_template : public thrift_application_base<TserverBase, TImplClass> +{ +public: + thrift_server_template(TImplClass* _this); + ~thrift_server_template(); + +protected: + TserverBase* i_impl(); + friend class thrift_application_base<TserverBase, TImplClass>; + + TserverBase* d_server; + +private: + /** + * Custom TransportFactory that allows you to override the default Thrift buffer size + * of 512 bytes. + * + */ + class TBufferedTransportFactory : public thrift::transport::TTransportFactory + { + public: + TBufferedTransportFactory(const unsigned int _bufferSize) : bufferSize(_bufferSize) {;} + + virtual ~TBufferedTransportFactory() {} + + virtual boost::shared_ptr<thrift::transport::TTransport> getTransport( + boost::shared_ptr<thrift::transport::TTransport> trans) + { + return boost::shared_ptr<thrift::transport::TTransport> + (new thrift::transport::TBufferedTransport(trans, bufferSize)); + } + private: + unsigned int bufferSize; + }; +}; + +template<typename TserverBase, typename TserverClass, typename TImplClass, typename TThriftClass> +thrift_server_template<TserverBase, TserverClass, TImplClass, TThriftClass>::thrift_server_template +(TImplClass* _this) : thrift_application_base<TserverBase, TImplClass>(_this) +{ + gr::logger_ptr logger, debug_logger; + gr::configure_default_loggers(logger, debug_logger, "controlport"); + + unsigned int port, nthreads, buffersize; + std::string thrift_config_file = gr::prefs::singleton()->get_string("ControlPort", "config", ""); + + if(thrift_config_file.length() > 0) { + gr::prefs::singleton()->add_config_file(thrift_config_file); + } + + // Collect configuration options from the Thrift config file; + // defaults if the config file doesn't exist or list the specific + // options. + port = static_cast<unsigned int>(gr::prefs::singleton()->get_long("thrift", "port", + thrift_application_base<TserverBase, TImplClass>::d_default_thrift_port)); + nthreads = static_cast<unsigned int>(gr::prefs::singleton()->get_long("thrift", "nthreads", + thrift_application_base<TserverBase, TImplClass>::d_default_num_thrift_threads)); + buffersize = static_cast<unsigned int>(gr::prefs::singleton()->get_long("thrift", "buffersize", + thrift_application_base<TserverBase, TImplClass>::d_default_thrift_buffer_size)); + + boost::shared_ptr<TserverClass> handler(new TserverClass()); + + boost::shared_ptr<thrift::TProcessor> + processor(new GNURadio::ControlPortProcessor(handler)); + + boost::shared_ptr<thrift::transport::TServerTransport> + serverTransport(new thrift::transport::TServerSocket(port)); + + boost::shared_ptr<thrift::transport::TTransportFactory> + transportFactory(new thrift_server_template::TBufferedTransportFactory(buffersize)); + + boost::shared_ptr<thrift::protocol::TProtocolFactory> + protocolFactory(new thrift::protocol::TBinaryProtocolFactory()); + + + if(nthreads <= 1) { + // "Thrift: Single-threaded server" + //std::cout << "Thrift Single-threaded server" << std::endl; + thrift_application_base<TserverBase, TImplClass>::d_thriftserver.reset( + new thrift::server::TSimpleServer(processor, serverTransport, + transportFactory, protocolFactory)); + } + else { + //std::cout << "Thrift Multi-threaded server : " << nthreads << std::endl; + boost::shared_ptr<thrift::concurrency::ThreadManager> threadManager + (thrift::concurrency::ThreadManager::newSimpleThreadManager(nthreads)); + + boost::shared_ptr<thrift::concurrency::PlatformThreadFactory> threadFactory + (boost::shared_ptr<thrift::concurrency::PlatformThreadFactory> + (new thrift::concurrency::PlatformThreadFactory())); + + threadManager->threadFactory(threadFactory); + + threadManager->start(); + + thrift_application_base<TserverBase, TImplClass>::d_thriftserver.reset( + new thrift::server::TThreadPoolServer(processor, serverTransport, + transportFactory, protocolFactory, + threadManager)); + } + + d_server = handler.get(); +} + +template<typename TserverBase, typename TserverClass, typename TImplClass, typename TThriftClass> +thrift_server_template<TserverBase, TserverClass,TImplClass, TThriftClass>::~thrift_server_template() +{ +} + +template<typename TserverBase, typename TserverClass, typename TImplClass, typename TThriftClass> +TserverBase* thrift_server_template<TserverBase, TserverClass, TImplClass, TThriftClass>::i_impl() +{ + //std::cerr << "thrift_server_template: i_impl" << std::endl; + + return d_server; +} + +#endif /* THRIFT_SERVER_TEMPLATE_H */ |