Line data Source code
1 : /* Copyright (c) 2017, Stefan.Eilemann@epfl.ch
2 : *
3 : * This file is part of Servus <https://github.com/HBPVIS/Servus>
4 : *
5 : * This library is free software; you can redistribute it and/or modify it under
6 : * the terms of the GNU Lesser General Public License version 3.0 as published
7 : * by the Free Software Foundation.
8 : *
9 : * This library is distributed in the hope that it will be useful, but WITHOUT
10 : * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
11 : * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
12 : * details.
13 : *
14 : * You should have received a copy of the GNU Lesser General Public License
15 : * along with this library; if not, write to the Free Software Foundation, Inc.,
16 : * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
17 : */
18 :
19 : #include <algorithm>
20 : #include <mutex>
21 : #include <set>
22 : #include <iterator>
23 :
24 : namespace servus
25 : {
26 : namespace test
27 : {
28 : class Servus;
29 :
30 : namespace
31 : {
32 : struct
33 10 : {
34 : std::mutex mutex;
35 : std::set<Servus*> instances;
36 5 : } _directory;
37 : }
38 :
39 : class Servus : public servus::Servus::Impl
40 : {
41 : public:
42 3 : Servus()
43 3 : : servus::Servus::Impl(servus::TEST_DRIVER)
44 : {
45 3 : }
46 :
47 6 : virtual ~Servus()
48 6 : {
49 3 : withdraw();
50 3 : endBrowsing();
51 6 : }
52 :
53 0 : std::string getClassName() const { return "test"; }
54 3 : servus::Servus::Result announce(const unsigned short port,
55 : const std::string& instance) final
56 : {
57 6 : std::lock_guard<std::mutex> lock(_directory.mutex);
58 :
59 3 : _port = port;
60 3 : if (instance.empty())
61 0 : _instance = getHostname();
62 : else
63 3 : _instance = instance;
64 3 : _directory.instances.insert(this);
65 3 : _announced = true;
66 6 : return servus::Servus::Result(servus::Result::SUCCESS);
67 : }
68 :
69 4 : void withdraw() final
70 : {
71 8 : std::lock_guard<std::mutex> lock(_directory.mutex);
72 :
73 4 : _announced = false;
74 4 : _directory.instances.erase(this);
75 4 : _port = 0;
76 4 : _instance.clear();
77 4 : }
78 :
79 0 : bool isAnnounced() const final { return _announced; }
80 4 : servus::Servus::Result beginBrowsing(
81 : const ::servus::Servus::Interface) final
82 : {
83 4 : if (_browsing)
84 1 : return servus::Servus::Result(servus::Servus::Result::PENDING);
85 :
86 3 : _instances.clear();
87 3 : _browsing = true;
88 3 : return servus::Servus::Result(servus::Servus::Result::SUCCESS);
89 : }
90 :
91 6 : servus::Servus::Result browse(const int32_t) final
92 : {
93 12 : std::lock_guard<std::mutex> lock(_directory.mutex);
94 :
95 12 : std::vector<Servus*> diff;
96 : std::set_symmetric_difference(_directory.instances.begin(),
97 : _directory.instances.end(),
98 : _instances.begin(), _instances.end(),
99 6 : back_inserter(diff));
100 :
101 6 : _instanceMap.clear();
102 13 : for (auto i : _directory.instances)
103 : {
104 7 : ValueMap& values = _instanceMap[i->_instance];
105 7 : values.clear();
106 7 : values["servus_host"] = "localhost";
107 :
108 18 : for (const auto& j : i->_data)
109 11 : values[j.first] = j.second;
110 : }
111 :
112 11 : for (auto i : diff)
113 : {
114 5 : if (_instances.count(i) == 0)
115 : {
116 4 : _instances.insert(i);
117 4 : for (Listener* listener : _listeners)
118 0 : listener->instanceAdded(i->_instance);
119 : }
120 : else
121 : {
122 1 : for (Listener* listener : _listeners)
123 0 : listener->instanceRemoved(i->_instance);
124 1 : _instances.erase(i);
125 : }
126 : }
127 12 : return servus::Servus::Result(servus::Servus::Result::SUCCESS);
128 : }
129 :
130 6 : void endBrowsing() final
131 : {
132 6 : _browsing = false;
133 6 : _instances.clear();
134 6 : }
135 :
136 5 : bool isBrowsing() const final { return _browsing; }
137 : private:
138 : std::string _instance;
139 : unsigned short _port{0};
140 : bool _announced{false};
141 : bool _browsing{false};
142 :
143 : std::set<Servus*> _instances;
144 :
145 2 : void _updateRecord() final { /*nop*/}
146 : };
147 : }
148 : }
|