Skip to content
This repository was archived by the owner on Jul 8, 2022. It is now read-only.

Commit 85057ac

Browse files
authored
Merge pull request #702 from mliszcz/backport-fix-496-blind-event-clients-after-dev-restart
Backport fix for #496 and #361 - event clients lost after dev restart
2 parents 4f8a0ba + 6a0ee49 commit 85057ac

File tree

7 files changed

+374
-12
lines changed

7 files changed

+374
-12
lines changed

cpp_test_suite/new_tests/cxx_dserver_misc.cpp

+84
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,27 @@ using namespace std;
1414
#undef SUITE_NAME
1515
#define SUITE_NAME DServerMiscTestSuite
1616

17+
template <typename TEvent>
18+
struct EventCallback : public Tango::CallBack
19+
{
20+
EventCallback()
21+
: num_of_all_events(0)
22+
, num_of_error_events(0)
23+
{}
24+
25+
void push_event(TEvent* event)
26+
{
27+
num_of_all_events++;
28+
if (event->err)
29+
{
30+
num_of_error_events++;
31+
}
32+
}
33+
34+
int num_of_all_events;
35+
int num_of_error_events;
36+
};
37+
1738
class DServerMiscTestSuite: public CxxTest::TestSuite
1839
{
1940
protected:
@@ -211,6 +232,69 @@ cout << "str = " << str << endl;
211232
TS_ASSERT(dserver->info().server_id == full_ds_name);
212233
TS_ASSERT(dserver->info().server_version == server_version);
213234
}
235+
236+
/* Tests that subscriber can receive events immediately after
237+
* a device restart without a need to wait for re-subscription.
238+
*/
239+
void test_event_subscription_recovery_after_device_restart()
240+
{
241+
EventCallback<Tango::EventData> callback{};
242+
243+
std::string attribute_name = "event_change_tst";
244+
245+
TS_ASSERT_THROWS_NOTHING(device1->subscribe_event(
246+
attribute_name,
247+
Tango::USER_EVENT,
248+
&callback));
249+
250+
TS_ASSERT_THROWS_NOTHING(device1->command_inout("IOPushEvent"));
251+
Tango_sleep(2);
252+
TS_ASSERT_EQUALS(2, callback.num_of_all_events);
253+
TS_ASSERT_EQUALS(0, callback.num_of_error_events);
254+
255+
{
256+
Tango::DeviceData input{};
257+
input << device1_name;
258+
TS_ASSERT_THROWS_NOTHING(dserver->command_inout("DevRestart", input));
259+
}
260+
261+
TS_ASSERT_THROWS_NOTHING(device1->command_inout("IOPushEvent"));
262+
Tango_sleep(2);
263+
TS_ASSERT_EQUALS(3, callback.num_of_all_events);
264+
TS_ASSERT_EQUALS(0, callback.num_of_error_events);
265+
}
266+
267+
/* Tests that attribute configuration change event
268+
* is sent to all subscribers after device restart.
269+
*/
270+
void test_attr_conf_change_event_after_device_restart()
271+
{
272+
EventCallback<Tango::AttrConfEventData> callback{};
273+
274+
const std::string attribute_name = "event_change_tst";
275+
276+
int subscription = 0;
277+
TS_ASSERT_THROWS_NOTHING(subscription = device1->subscribe_event(
278+
attribute_name,
279+
Tango::ATTR_CONF_EVENT,
280+
&callback));
281+
282+
Tango_sleep(1);
283+
TS_ASSERT_EQUALS(1, callback.num_of_all_events);
284+
TS_ASSERT_EQUALS(0, callback.num_of_error_events);
285+
286+
{
287+
Tango::DeviceData input{};
288+
input << device1_name;
289+
TS_ASSERT_THROWS_NOTHING(dserver->command_inout("DevRestart", input));
290+
}
291+
292+
Tango_sleep(1);
293+
TS_ASSERT_EQUALS(2, callback.num_of_all_events);
294+
TS_ASSERT_EQUALS(0, callback.num_of_error_events);
295+
296+
TS_ASSERT_THROWS_NOTHING(device1->unsubscribe_event(subscription));
297+
}
214298
};
215299
#undef cout
216300
#endif // DServerMiscTestSuite_h

cppapi/server/device.cpp

+34
Original file line numberDiff line numberDiff line change
@@ -6148,6 +6148,25 @@ void DeviceImpl::get_event_param(vector<EventPar> &eve)
61486148
}
61496149
}
61506150

6151+
void DeviceImpl::get_event_param(vector<EventSubscriptionState> &eve)
6152+
{
6153+
ZmqEventSupplier *event_supplier_zmq = Util::instance()->get_zmq_event_supplier();
6154+
6155+
if (event_supplier_zmq->any_dev_intr_client(this) == true)
6156+
{
6157+
EventSubscriptionState ep;
6158+
6159+
ep.notifd = false;
6160+
ep.zmq = true;
6161+
ep.attribute_name = "";
6162+
ep.quality = false;
6163+
ep.data_ready = false;
6164+
ep.dev_intr_change = true;
6165+
6166+
eve.push_back(ep);
6167+
}
6168+
}
6169+
61516170
//+-----------------------------------------------------------------------------------------------------------------
61526171
//
61536172
// method :
@@ -6177,6 +6196,21 @@ void DeviceImpl::set_event_param(vector<EventPar> &eve)
61776196
}
61786197
}
61796198

6199+
void DeviceImpl::set_event_param(vector<EventSubscriptionState> &eve)
6200+
{
6201+
for (size_t loop = 0; loop < eve.size(); loop++)
6202+
{
6203+
if (eve[loop].attribute_name.empty())
6204+
{
6205+
if (eve[loop].dev_intr_change == true)
6206+
{
6207+
set_event_intr_change_subscription(time(NULL));
6208+
}
6209+
break;
6210+
}
6211+
}
6212+
}
6213+
61806214
//+-----------------------------------------------------------------------------------------------------------------
61816215
//
61826216
// method :

cppapi/server/device.h

+4-2
Original file line numberDiff line numberDiff line change
@@ -3414,8 +3414,10 @@ class DeviceImpl : public virtual POA_Tango::Device
34143414
void disable_intr_change_ev() {intr_change_ev = false;}
34153415
bool is_intr_change_ev_enable() {return intr_change_ev;}
34163416

3417-
void get_event_param(vector<EventPar> &);
3418-
void set_event_param(vector<EventPar> &);
3417+
void get_event_param(vector<EventPar> &); // Deprecated, use EventSubscriptionState overload
3418+
void set_event_param(vector<EventPar> &); // Deprecated, use EventSubscriptionState overload
3419+
void get_event_param(vector<EventSubscriptionState>&);
3420+
void set_event_param(vector<EventSubscriptionState>&);
34193421

34203422
void set_client_lib(int _l) {if (count(client_lib.begin(),client_lib.end(),_l)==0)client_lib.push_back(_l);}
34213423

cppapi/server/dserver.cpp

+55-6
Original file line numberDiff line numberDiff line change
@@ -861,7 +861,7 @@ void DServer::restart(string &d_name)
861861

862862
vector<PollObj *> &p_obj = dev_to_del->get_poll_obj_list();
863863
vector<Pol> dev_pol;
864-
vector<EventPar> eve;
864+
vector<EventSubscriptionState> eve;
865865

866866
for (i = 0;i < p_obj.size();i++)
867867
{
@@ -1098,6 +1098,16 @@ void DServer::restart(string &d_name)
10981098
event_supplier_zmq->push_dev_intr_change_event(new_dev,false,cmds_list,atts_list);
10991099
}
11001100
}
1101+
1102+
// Attribute properties may have changed after the restart.
1103+
// Push an attribute configuration event to all registered subscribers.
1104+
1105+
vector<Tango::Attribute*>& dev_att_list = new_dev->get_device_attr()->get_attribute_list();
1106+
vector<Tango::Attribute*>::iterator ite_att;
1107+
for (ite_att = dev_att_list.begin(); ite_att != dev_att_list.end() ; ++ite_att)
1108+
{
1109+
new_dev->push_att_conf_event(*ite_att);
1110+
}
11011111
}
11021112

11031113
//+-----------------------------------------------------------------------------------------------------------------
@@ -1172,7 +1182,7 @@ void ServRestartThread::run(void *ptr)
11721182
// Memorize event parameters and devices interface
11731183
//
11741184

1175-
map<string,vector<EventPar> > map_events;
1185+
map<string,vector<EventSubscriptionState> > map_events;
11761186
map<string,DevIntr> map_dev_inter;
11771187

11781188
dev->mem_event_par(map_events);
@@ -1204,22 +1214,22 @@ void ServRestartThread::run(void *ptr)
12041214
dev->set_poll_th_pool_size(DEFAULT_POLLING_THREADS_POOL_SIZE);
12051215

12061216
tg->set_svr_starting(true);
1207-
1217+
12081218
vector<DeviceClass *> empty_class;
12091219
tg->set_class_list(&empty_class);
1210-
1220+
12111221
{
12121222
AutoPyLock PyLo;
12131223
dev->init_device();
12141224
}
1215-
1225+
12161226
//
12171227
// Set the class list pointer in the Util class and add the DServer object class
12181228
//
12191229

12201230
tg->set_class_list(&(dev->get_class_list()));
12211231
tg->add_class_to_list(dev->get_device_class());
1222-
1232+
12231233
tg->set_svr_starting(false);
12241234

12251235
//
@@ -1975,6 +1985,25 @@ void DServer::mem_event_par(map<string,vector<EventPar> > &_map)
19751985
}
19761986
}
19771987

1988+
void DServer::mem_event_par(map<string,vector<EventSubscriptionState> > &_map)
1989+
{
1990+
for (size_t i = 0;i < class_list.size();i++)
1991+
{
1992+
vector<DeviceImpl *> &dev_list = class_list[i]->get_device_list();
1993+
for (size_t j = 0;j < dev_list.size();j++)
1994+
{
1995+
vector<EventSubscriptionState> eve;
1996+
dev_list[j]->get_device_attr()->get_event_param(eve);
1997+
dev_list[j]->get_event_param(eve);
1998+
1999+
if (eve.size() != 0)
2000+
{
2001+
_map.insert(make_pair(dev_list[j]->get_name(),eve));
2002+
}
2003+
}
2004+
}
2005+
}
2006+
19782007
//+-----------------------------------------------------------------------------------------------------------------
19792008
//
19802009
// method :
@@ -2009,6 +2038,26 @@ void DServer::apply_event_par(map<string,vector<EventPar> > &_map)
20092038
}
20102039
}
20112040

2041+
void DServer::apply_event_par(map<string,vector<EventSubscriptionState> > &_map)
2042+
{
2043+
for (size_t i = 0;i < class_list.size();i++)
2044+
{
2045+
vector<DeviceImpl *> &dev_list = class_list[i]->get_device_list();
2046+
for (size_t j = 0;j < dev_list.size();j++)
2047+
{
2048+
string &dev_name = dev_list[j]->get_name();
2049+
map<string,vector<EventSubscriptionState> >::iterator ite;
2050+
ite = _map.find(dev_name);
2051+
2052+
if (ite != _map.end())
2053+
{
2054+
dev_list[j]->get_device_attr()->set_event_param(ite->second);
2055+
dev_list[j]->set_event_param(ite->second);
2056+
}
2057+
}
2058+
}
2059+
}
2060+
20122061
//+-----------------------------------------------------------------------------------------------------------------
20132062
//
20142063
// method :

cppapi/server/dserver.h

+5-2
Original file line numberDiff line numberDiff line change
@@ -127,8 +127,10 @@ public :
127127
void _create_cpp_class(const char *c1,const char *c2) {this->create_cpp_class(c1,c2);}
128128

129129
void mcast_event_for_att(string &,string &,vector<string> &);
130-
void mem_event_par(map<string, vector<EventPar> > &);
131-
void apply_event_par(map<string,vector<EventPar> > &);
130+
void mem_event_par(map<string, vector<EventPar> > &); // Deprecated, use EventSubscriptionState overload
131+
void apply_event_par(map<string,vector<EventPar> > &); // Deprecated, use EventSubscriptionState overload
132+
void mem_event_par(map<string, vector<EventSubscriptionState> >&);
133+
void apply_event_par(map<string,vector<EventSubscriptionState> >&);
132134

133135
void mem_devices_interface(map<string,DevIntr> &);
134136
void changed_devices_interface(map<string,DevIntr> &);
@@ -158,6 +160,7 @@ protected :
158160
static ClassFactoryFuncPtr class_factory_func_ptr;
159161

160162
private:
163+
161164
#if ((defined _TG_WINDOWS_) && (defined TANGO_HAS_DLL) && !(defined _TANGO_LIB))
162165
__declspec(dllexport) void class_factory();
163166
#else

0 commit comments

Comments
 (0)