source: nscp/service/plugin_list.hpp @ a44cb15

0.4.00.4.10.4.2
Last change on this file since a44cb15 was a44cb15, checked in by Michael Medin <michael@…>, 22 months ago
  • Implemented registration of channels (so no longer faked)
  • Added settings key to change the NSCAAgent channel name
  • Addded proper channel handling to PythonScript module
  • Improved error handling in channels API
  • Rewrote wrapper API to use templates and classes instead of macros (ish)
  • Improved the internal plugin wrapping API to support multiple plugin load
  • Fixed so PythonScript module supports multiple plugin load (with new argument for plugin_id)
  • Added API for registrying routers and handling routing (almost there now)
  • Fixed issue with messages due to new API
  • Property mode set to 100644
File size: 6.7 KB
Line 
1#pragma once
2
3#include <set>
4
5#include <boost/shared_ptr.hpp>
6#include <boost/foreach.hpp>
7
8#include "NSCPlugin.h"
9#include "logger.hpp"
10
11using namespace nscp::helpers;
12
13namespace nsclient {
14        typedef boost::shared_ptr<NSCPlugin> plugin_type;
15        typedef std::map<unsigned long,plugin_type> plugin_list_type;
16        typedef std::set<unsigned long> plugin_id_type;
17
18        class plugins_list_exception : public std::exception {
19                std::string what_;
20        public:
21                plugins_list_exception(std::wstring error) throw() : what_(to_string(error).c_str()) {}
22                plugins_list_exception(std::string error) throw() : what_(error.c_str()) {}
23                virtual ~plugins_list_exception() throw() {};
24
25                virtual const char* what() const throw() {
26                        return what_.c_str();
27                }
28        };
29
30        template<class parent>
31        struct plugins_list : boost::noncopyable, public parent {
32
33                nsclient::logger *logger_;
34                plugin_list_type plugins_;
35                boost::shared_mutex mutex_;
36
37                plugins_list(nsclient::logger *logger) : logger_(logger) {}
38
39                bool has_valid_lock_log(boost::unique_lock<boost::shared_mutex> &lock, std::wstring key) {
40                        if (!lock.owns_lock()) {
41                                log_error(__FILE__, __LINE__, _T("Failed to get mutex: ") + key);
42                                return false;
43                        }
44                        return true;
45                }
46                bool has_valid_lock_log(boost::shared_lock<boost::shared_mutex> &lock, std::wstring key) {
47                        if (!lock.owns_lock()) {
48                                log_error(__FILE__, __LINE__, _T("Failed to get mutex: ") + key);
49                                return false;
50                        }
51                        return true;
52                }
53                void has_valid_lock_throw(boost::unique_lock<boost::shared_mutex> &lock, std::wstring key) {
54                        if (!lock.owns_lock()) {
55                                log_error(__FILE__, __LINE__, _T("Failed to get mutex: ") + key);
56                                throw plugins_list_exception("Failed to get mutex: " + utf8::cvt<std::string>(key));
57                        }
58                }
59                void has_valid_lock_throw(boost::shared_lock<boost::shared_mutex> &lock, std::wstring key) {
60                        if (!lock.owns_lock()) {
61                                log_error(__FILE__, __LINE__, _T("Failed to get mutex: ") + key);
62                                throw plugins_list_exception("Failed to get mutex: " + utf8::cvt<std::string>(key));
63                        }
64                }
65
66                void add_plugin(plugin_type plugin) {
67                        boost::unique_lock<boost::shared_mutex> writeLock(mutex_, boost::get_system_time() + boost::posix_time::seconds(30));
68                        if (!has_valid_lock_log(writeLock, _T("plugins_list::add_plugin")))
69                                return;
70                        plugins_[plugin->get_id()] = plugin;
71                        parent::add_plugin(plugin);
72                }
73
74                void remove_all() {
75                        boost::unique_lock<boost::shared_mutex> writeLock(mutex_, boost::get_system_time() + boost::posix_time::seconds(30));
76                        if (!has_valid_lock_log(writeLock, _T("plugins_list::remove_all")))
77                                return;
78                        plugins_.clear();
79                        parent::remove_all();
80                }
81
82                void remove_plugin(unsigned long id) {
83                        boost::unique_lock<boost::shared_mutex> writeLock(mutex_, boost::get_system_time() + boost::posix_time::seconds(10));
84                        if (!has_valid_lock_log(writeLock, _T("plugins_list::remove_plugin") + ::to_wstring(id)))
85                                return;
86                        plugin_list_type::iterator pit = plugins_.find(id);
87                        if (pit != plugins_.end())
88                                plugins_.erase(pit);
89                        parent::remove_plugin(id);
90                }
91
92                std::list<std::wstring> list() {
93                        std::list<std::wstring> lst;
94                        boost::shared_lock<boost::shared_mutex> readLock(mutex_, boost::get_system_time() + boost::posix_time::seconds(5));
95                        if (!has_valid_lock_log(readLock, _T("plugins_list::list")))
96                                return lst;
97                        parent::list(lst);
98                        return lst;
99                }
100
101                std::wstring to_wstring() {
102                        std::wstring ret;
103                        BOOST_FOREACH(std::wstring str, list()) {
104                                if (!ret.empty()) ret += _T(", ");
105                                ret += str;
106                        }
107                        return ret + parent::to_wstring();
108                }
109                std::string to_string() {
110                        std::string ret;
111                        BOOST_FOREACH(std::wstring str, list()) {
112                                if (!ret.empty()) ret += ", ";
113                                ret += utf8::cvt<std::string>(str);
114                        }
115                        return ret + parent::to_string();
116                }
117
118                inline std::wstring make_key(std::wstring key) {
119                        return boost::algorithm::to_lower_copy(key);
120                }
121                void log_error(std::string file, int line, std::wstring error) {
122                        if (logger_ != NULL)
123                                logger_->nsclient_log_error(file, line, error);
124                }
125
126                inline bool have_plugin(unsigned long plugin_id) {
127                        return !(plugins_.find(plugin_id) == plugins_.end());
128                }
129        };
130
131
132        struct plugins_list_listeners_impl {
133                typedef std::map<std::wstring,plugin_id_type > listener_list_type;
134                listener_list_type listeners_;
135
136                void add_plugin(plugin_type plugin) {}
137
138                void remove_all() {
139                        listeners_.clear();
140                }
141
142                void remove_plugin(unsigned long id) {
143                        listener_list_type::iterator it = listeners_.begin();
144                        while (it != listeners_.end()) {
145                                if ((*it).second.count(id) > 0) {
146                                        listener_list_type::iterator toerase = it;
147                                        ++it;
148                                        listeners_.erase(toerase);
149                                } else
150                                        ++it;
151                        }
152                }
153
154                void list(std::list<std::wstring> &lst) {
155                        BOOST_FOREACH(listener_list_type::value_type i, listeners_) {
156                                lst.push_back(i.first);
157                        }
158                }
159                std::wstring to_wstring() {
160                        std::wstring ret;
161                        BOOST_FOREACH(listener_list_type::value_type i, listeners_) {
162                                ret += _T(", ");
163                                ret += i.first;
164                        }
165                        return ret;
166                }
167                std::string to_string() {
168                        std::string ret;
169                        BOOST_FOREACH(listener_list_type::value_type i, listeners_) {
170                                ret += ", ";
171                                ret += utf8::cvt<std::string>(i.first);
172                        }
173                        return ret;
174                }
175
176        };
177
178        struct plugins_list_with_listener : plugins_list<plugins_list_listeners_impl> {
179                typedef plugins_list<plugins_list_listeners_impl> parent_type;
180
181                plugins_list_with_listener(nsclient::logger *logger) : parent_type(logger) {}
182
183                void register_listener(unsigned long plugin_id, std::wstring channel) {
184                        boost::unique_lock<boost::shared_mutex> writeLock(mutex_, boost::get_system_time() + boost::posix_time::seconds(10));
185                        if (!writeLock.owns_lock()) {
186                                log_error(__FILE__, __LINE__, _T("Failed to get mutex: ") + channel);
187                                return;
188                        }
189                        std::wstring lc = make_key(channel);
190                        if (!have_plugin(plugin_id)) {
191                                writeLock.release();
192                                throw plugins_list_exception("Failed to find plugin: " + ::to_string(plugin_id) + ", Plugins: " + to_string());
193                        }
194                        listeners_[lc].insert(plugin_id);
195                }
196
197                std::list<plugin_type> get(std::wstring channel) {
198                        boost::shared_lock<boost::shared_mutex> readLock(mutex_, boost::get_system_time() + boost::posix_time::seconds(5));
199                        has_valid_lock_throw(readLock, _T("plugins_list::get:") + channel);
200                        std::wstring lc = make_key(channel);
201                        plugins_list_listeners_impl::listener_list_type::iterator cit = listeners_.find(lc);
202                        if (cit == listeners_.end()) {
203                                return std::list<plugin_type>(); // throw plugins_list_exception("Channel not found: '" + ::to_string(channel) + "'" + to_string());
204                        }
205                        std::list<plugin_type> ret;
206                        BOOST_FOREACH(unsigned long id, cit->second) {
207                                ret.push_back(plugins_[id]);
208                        }
209                        return ret;
210                }
211        };
212
213}
Note: See TracBrowser for help on using the repository browser.