Skip to content

Commit 2f13706

Browse files
Merge remote-tracking branch 'origin/syslog_telemetry_shared' into remanava_events
2 parents e7f1bca + 33afb9b commit 2f13706

31 files changed

+1076
-59
lines changed

Makefile.am

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
1-
SUBDIRS = common pyext tests
1+
SUBDIRS = common pyext sonic-db-cli tests
22

33
ACLOCAL_AMFLAGS = -I m4

common/Makefile.am

+1
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ libswsscommon_la_SOURCES = \
4747
select.cpp \
4848
selectableevent.cpp \
4949
selectabletimer.cpp \
50+
signalhandlerhelper.cpp \
5051
consumertable.cpp \
5152
consumertablebase.cpp \
5253
consumerstatetable.cpp \

common/configdb.h

+5-1
Original file line numberDiff line numberDiff line change
@@ -94,8 +94,12 @@ class ConfigDBConnector_Native : public SonicV2Connector_Native
9494
if init_data_handler:
9595
init_data_handler(init_callback_data)
9696

97-
while True:
97+
while not SignalHandlerHelper.checkSignal(SIGNAL_INT):
9898
item = self.pubsub.listen_message()
99+
if 'type' not in item:
100+
# When timeout or cancelled, item will not contains 'type'
101+
continue
102+
99103
if item['type'] == 'pmessage':
100104
key = item['channel'].split(':', 1)[1]
101105
try:

common/pubsub.cpp

+20-8
Original file line numberDiff line numberDiff line change
@@ -79,20 +79,29 @@ bool PubSub::hasCachedData()
7979

8080
map<string, string> PubSub::get_message(double timeout)
8181
{
82-
map<string, string> ret;
82+
return get_message_internal(timeout).second;
83+
}
84+
85+
MessageResultPair PubSub::get_message_internal(double timeout)
86+
{
87+
MessageResultPair ret;
88+
8389
if (!m_subscribe)
8490
{
91+
ret.first = Select::ERROR;
8592
return ret;
8693
}
8794

8895
Selectable *selected;
8996
int rc = m_select.select(&selected, int(timeout));
97+
ret.first = rc;
9098
switch (rc)
9199
{
92100
case Select::ERROR:
93101
throw RedisError("Failed to select", m_subscribe->getContext());
94102

95103
case Select::TIMEOUT:
104+
case Select::SIGNALINT:
96105
return ret;
97106

98107
case Select::OBJECT:
@@ -110,10 +119,10 @@ map<string, string> PubSub::get_message(double timeout)
110119
}
111120

112121
auto message = event->getReply<RedisMessage>();
113-
ret["type"] = message.type;
114-
ret["pattern"] = message.pattern;
115-
ret["channel"] = message.channel;
116-
ret["data"] = message.data;
122+
ret.second["type"] = message.type;
123+
ret.second["pattern"] = message.pattern;
124+
ret.second["channel"] = message.channel;
125+
ret.second["data"] = message.data;
117126
return ret;
118127
}
119128

@@ -122,14 +131,17 @@ map<string, string> PubSub::get_message(double timeout)
122131
std::map<std::string, std::string> PubSub::listen_message()
123132
{
124133
const double GET_MESSAGE_INTERVAL = 600.0; // in seconds
134+
MessageResultPair ret;
125135
for (;;)
126136
{
127-
auto ret = get_message(GET_MESSAGE_INTERVAL);
128-
if (!ret.empty())
137+
ret = get_message_internal(GET_MESSAGE_INTERVAL);
138+
if (!ret.second.empty() || ret.first == Select::SIGNALINT)
129139
{
130-
return ret;
140+
break;
131141
}
132142
}
143+
144+
return ret.second;
133145
}
134146

135147
shared_ptr<RedisReply> PubSub::popEventBuffer()

common/pubsub.h

+4
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,16 @@
11
#pragma once
22
#include <map>
33
#include <deque>
4+
#include <utility>
45

56
#include "dbconnector.h"
67
#include "select.h"
78
#include "redisselect.h"
89

910
namespace swss {
1011

12+
typedef std::pair<int, std::map<std::string, std::string> > MessageResultPair;
13+
1114
// This class is to emulate python redis-py class PubSub
1215
// After SWIG wrapping, it should be used in the same way
1316
class PubSub : protected RedisSelect
@@ -29,6 +32,7 @@ class PubSub : protected RedisSelect
2932
private:
3033
/* Pop keyspace event from event buffer. Caller should free resources. */
3134
std::shared_ptr<RedisReply> popEventBuffer();
35+
MessageResultPair get_message_internal(double timeout = 0.0);
3236

3337
DBConnector *m_parentConnector;
3438
Select m_select;

common/rediscommand.cpp

+10
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,16 @@ void RedisCommand::formatArgv(int argc, const char **argv, const size_t *argvlen
4949
}
5050
}
5151

52+
void RedisCommand::format(const vector<string> &commands)
53+
{
54+
vector<const char*> args;
55+
for (auto& command : commands)
56+
{
57+
args.push_back(command.c_str());
58+
}
59+
formatArgv(static_cast<int>(args.size()), args.data(), NULL);
60+
}
61+
5262
/* Format HMSET key multiple field value command */
5363
void RedisCommand::formatHMSET(const std::string &key,
5464
const std::vector<FieldValueTuple> &values)

common/rediscommand.h

+1
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ class RedisCommand {
2525

2626
void format(const char *fmt, ...);
2727
void formatArgv(int argc, const char **argv, const size_t *argvlen);
28+
void format(const std::vector<std::string> &commands);
2829

2930
/* Format HMSET key multiple field value command */
3031
#ifndef SWIG

common/redisreply.cpp

+42-1
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
#include <stdint.h>
33
#include <vector>
44
#include <iostream>
5+
#include <sstream>
56
#include <system_error>
67
#include <functional>
78

@@ -158,7 +159,7 @@ void RedisReply::checkReplyType(int expectedType)
158159
const char *err = (m_reply->type == REDIS_REPLY_STRING || m_reply->type == REDIS_REPLY_ERROR) ?
159160
m_reply->str : "NON-STRING-REPLY";
160161

161-
string errmsg = "Expected to get redis type " + to_string(expectedType) + " got type " + to_string(m_reply->type) + ", err: " + err;
162+
string errmsg = "Expected to get redis type " + std::to_string(expectedType) + " got type " + std::to_string(m_reply->type) + ", err: " + err;
162163
SWSS_LOG_ERROR("%s", errmsg.c_str());
163164
throw system_error(make_error_code(errc::io_error), errmsg);
164165
}
@@ -225,4 +226,44 @@ template<> RedisMessage RedisReply::getReply<RedisMessage>()
225226
return ret;
226227
}
227228

229+
230+
string RedisReply::to_string()
231+
{
232+
return to_string(getContext());
233+
}
234+
235+
string RedisReply::to_string(redisReply *reply)
236+
{
237+
switch(reply->type)
238+
{
239+
case REDIS_REPLY_INTEGER:
240+
return std::to_string(reply->integer);
241+
242+
case REDIS_REPLY_STRING:
243+
case REDIS_REPLY_ERROR:
244+
case REDIS_REPLY_STATUS:
245+
case REDIS_REPLY_NIL:
246+
return string(reply->str, reply->len);
247+
248+
case REDIS_REPLY_ARRAY:
249+
{
250+
stringstream result;
251+
for (size_t i = 0; i < reply->elements; i++)
252+
{
253+
result << to_string(reply->element[i]);
254+
255+
if (i < reply->elements - 1)
256+
{
257+
result << endl;
258+
}
259+
}
260+
return result.str();
261+
}
262+
263+
default:
264+
SWSS_LOG_ERROR("invalid type %d for message", reply->type);
265+
return string();
266+
}
267+
}
268+
228269
}

common/redisreply.h

+4
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,10 @@ class RedisReply
9292
/* Check that the status is QUEUED, throw exception otherwise */
9393
void checkStatusQueued();
9494

95+
std::string to_string();
96+
97+
static std::string to_string(redisReply *reply);
98+
9599
private:
96100
void checkStatus(const char *status);
97101
void checkReply();

common/select.cpp

+12-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
#include "common/selectable.h"
22
#include "common/logger.h"
33
#include "common/select.h"
4+
#include "common/signalhandlerhelper.h"
45
#include <algorithm>
56
#include <stdio.h>
67
#include <sys/time.h>
@@ -9,6 +10,7 @@
910
#include <unistd.h>
1011
#include <string.h>
1112

13+
1214
using namespace std;
1315

1416
namespace swss {
@@ -97,7 +99,13 @@ int Select::poll_descriptors(Selectable **c, unsigned int timeout)
9799
{
98100
ret = ::epoll_wait(m_epoll_fd, events.data(), sz_selectables, timeout);
99101
}
100-
while(ret == -1 && errno == EINTR); // Retry the select if the process was interrupted by a signal
102+
while(ret == -1 && errno == EINTR && !SignalHandlerHelper::checkSignal(Signals::SIGNAL_INT)); // Retry the select if the process was interrupted by a signal
103+
104+
if (SignalHandlerHelper::checkSignal(Signals::SIGNAL_INT))
105+
{
106+
// Return if the epoll_wait was interrupted by SIGTERM
107+
return Select::SIGNALINT;
108+
}
101109

102110
if (ret < 0)
103111
return Select::ERROR;
@@ -190,6 +198,9 @@ std::string Select::resultToString(int result)
190198
case swss::Select::TIMEOUT:
191199
return "TIMEOUT";
192200

201+
case swss::Select::SIGNALINT:
202+
return "SIGNALINT";
203+
193204
default:
194205
SWSS_LOG_WARN("unknown select result: %d", result);
195206
return "UNKNOWN";

common/select.h

+1
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ class Select
3030
OBJECT = 0,
3131
ERROR = 1,
3232
TIMEOUT = 2,
33+
SIGNALINT = 3,// Read operation interrupted by SIGINT
3334
};
3435

3536
int select(Selectable **c, int timeout = -1);

common/selectabletimer.cpp

+27-8
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ SelectableTimer::SelectableTimer(const timespec& interval, int pri)
2121
SWSS_LOG_THROW("failed to create timerfd, errno: %s", strerror(errno));
2222
}
2323
setInterval(interval);
24+
m_running = false;
2425
}
2526

2627
SelectableTimer::~SelectableTimer()
@@ -36,22 +37,40 @@ SelectableTimer::~SelectableTimer()
3637

3738
void SelectableTimer::start()
3839
{
39-
// Set the timer interval and the timer is automatically started
40-
int rc = timerfd_settime(m_tfd, 0, &m_interval, NULL);
41-
if (rc == -1)
40+
m_mutex.lock();
41+
if (!m_running)
4242
{
43-
SWSS_LOG_THROW("failed to set timerfd, errno: %s", strerror(errno));
43+
// Set the timer interval and the timer is automatically started
44+
int rc = timerfd_settime(m_tfd, 0, &m_interval, NULL);
45+
if (rc == -1)
46+
{
47+
SWSS_LOG_THROW("failed to set timerfd, errno: %s", strerror(errno));
48+
}
49+
else
50+
{
51+
m_running = true;
52+
}
4453
}
54+
m_mutex.unlock();
4555
}
4656

4757
void SelectableTimer::stop()
4858
{
49-
// Set the timer interval and the timer is automatically started
50-
int rc = timerfd_settime(m_tfd, 0, &m_zero, NULL);
51-
if (rc == -1)
59+
m_mutex.lock();
60+
if (m_running)
5261
{
53-
SWSS_LOG_THROW("failed to set timerfd to zero, errno: %s", strerror(errno));
62+
// Set the timer interval and the timer is automatically started
63+
int rc = timerfd_settime(m_tfd, 0, &m_zero, NULL);
64+
if (rc == -1)
65+
{
66+
SWSS_LOG_THROW("failed to set timerfd to zero, errno: %s", strerror(errno));
67+
}
68+
else
69+
{
70+
m_running = false;
71+
}
5472
}
73+
m_mutex.unlock();
5574
}
5675

5776
void SelectableTimer::reset()

common/selectabletimer.h

+3
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
#include <string>
44
#include <vector>
55
#include <limits>
6+
#include <mutex>
67
#include <sys/timerfd.h>
78
#include "selectable.h"
89

@@ -22,6 +23,8 @@ class SelectableTimer : public Selectable
2223
uint64_t readData() override;
2324

2425
private:
26+
std::mutex m_mutex;
27+
bool m_running;
2528
int m_tfd;
2629
itimerspec m_interval;
2730
itimerspec m_zero;

0 commit comments

Comments
 (0)