-
Notifications
You must be signed in to change notification settings - Fork 30
/
common_tool.cpp
197 lines (173 loc) · 5.98 KB
/
common_tool.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
#include "common_tool.h"
#include <errno.h>
#include <sys/stat.h>
#include <sys/time.h>
#include <sys/types.h>
#include <unistd.h>
#define __STDC_FORMAT_MACROS 1 // for e.g. %PRIu64
#include <inttypes.h>
#include "la-log.h"
void Common_Tool::init_config()
{
if (config_filename == NULL) {
abort();
}
struct stat buf;
if (stat(config_filename, &buf) == -1) {
if (errno == ENOENT) {
if (! streq(default_config_filename, config_filename)) {
la_log(LOG_CRIT, "Config file (%s) does not exist", config_filename);
exit(1);
}
} else {
la_log(LOG_CRIT, "Failed to stat (%s): %s\n", config_filename, strerror(errno));
exit(1);
}
}
_config = new INIReader(config_filename);
if (_config == NULL) {
la_log(LOG_CRIT, "Failed to create config from (%s)\n", config_filename);
exit(1);
}
if (_config == NULL) {
_config = new INIReader("/dev/null");
}
}
void Common_Tool::check_fds_are_empty_after_select(fd_set &fds_read, fd_set &fds_write, fd_set &fds_err, uint8_t nfds)
{
for (uint8_t i=0; i<nfds; i++) {
if (FD_ISSET(i, &fds_read)) {
la_log(LOG_ERR, "fds_read not empty");
break;
}
if (FD_ISSET(i, &fds_write)) {
la_log(LOG_ERR, "fds_write not empty");
break;
}
if (FD_ISSET(i, &fds_err)) {
la_log(LOG_ERR, "fds_err not empty");
break;
}
}
}
void Common_Tool::pack_select_fds(fd_set &fds_read UNUSED,
fd_set &fds_write UNUSED,
fd_set &fds_err UNUSED,
uint8_t &nfds UNUSED)
{
}
void Common_Tool::handle_select_fds(fd_set &fds_read UNUSED,
fd_set &fds_write UNUSED,
fd_set &fds_err UNUSED,
uint8_t &nfds UNUSED)
{
}
void Common_Tool::sighup_received_tophalf()
{
}
void Common_Tool::sighup_handler(int signal UNUSED)
{
_sighup_received = true;
}
void Common_Tool::do_idle_callbacks()
{
}
uint32_t Common_Tool::select_timeout_us() {
return 200000;
}
void Common_Tool::select_loop()
{
fd_set fds_read;
fd_set fds_write;
fd_set fds_err;
uint8_t nfds;
while (1) {
if (_sighup_received) {
sighup_received_tophalf();
_sighup_received = false;
}
/* Wait for a packet, or time out if no packets arrive so we always
periodically log status and check for new destinations. Downlink
packets are on the order of 100/sec, so the timeout is such that
we don't expect timeouts unless solo stops sending packets. We
almost always get a packet with a 200 msec timeout, but not with
a 100 msec timeout. (Timeouts don't really matter though.) */
struct timeval timeout;
FD_ZERO(&fds_read);
FD_ZERO(&fds_write);
FD_ZERO(&fds_err);
nfds = 0;
pack_select_fds(fds_read, fds_write, fds_err, nfds);
timeout.tv_sec = 0;
timeout.tv_usec = select_timeout_us();
int res = select(nfds, &fds_read, &fds_write, &fds_err, &timeout);
if (res < 0) {
unsigned skipped = 0;
la_log(LOG_ERR, "[%u] select: %s", skipped, strerror(errno));
/* this sleep is to avoid soaking the CPU if select starts
returning immediately for some reason */
/* previous code was not checking errfds; we are now, so
perhaps this usleep can go away -pb20150730 */
usleep(10000);
continue;
}
if (res == 0) {
// select timeout
}
handle_select_fds(fds_read, fds_write, fds_err, nfds);
check_fds_are_empty_after_select(fds_read, fds_write, fds_err, nfds);
do_idle_callbacks();
} /* while (1) */
}
void Common_Tool::parse_fd(Format_Reader *reader, int fd, ssize_t fd_size)
{
char buf[1<<16];
ssize_t buf_start = 0;
size_t total_bytes_read = 0;
const time_t start_time = time(NULL);
uint32_t printed_duration = 1;
while (true) {
ssize_t bytes_read = read(fd, &buf[buf_start], sizeof(buf)-buf_start);
if (bytes_read == -1) {
fprintf(stderr, "Read failed: %s\n", strerror(errno));
exit(1);
}
if (bytes_read == 0) {
while (reader->feed((uint8_t*)buf, buf_start+bytes_read)) {
}
break;
}
total_bytes_read += bytes_read;
if (fd_size != -1) {
const time_t now = time(NULL);
const uint32_t duration = now-start_time;
const uint8_t percent = (100*total_bytes_read/fd_size);
if (duration != 0 && duration != printed_duration) {
const uint64_t rate = total_bytes_read/duration;
const uint64_t remaining_time = (fd_size-total_bytes_read)/rate;
::fprintf(stderr, "\r%u%% %" PRIu64 " bytes/second remaining=%" PRIu64 " seconds ",
percent, rate, remaining_time);
printed_duration = duration;
}
}
bytes_read += buf_start;
ssize_t total_bytes_used = 0;
while (total_bytes_used < bytes_read) {
ssize_t bytes_used = reader->feed((uint8_t*)(&buf[total_bytes_used]), bytes_read-total_bytes_used);
if (bytes_used > bytes_read-total_bytes_used) {
abort();
}
if (bytes_used == 0) {
break;
}
total_bytes_used += bytes_used;
}
// ::fprintf(stderr, "total_bytes_used = %u\n", total_bytes_used);
// ::fprintf(stderr, "bytes_read = %u\n", bytes_read);
memcpy(&buf[0], (uint8_t*)(&(buf[total_bytes_used])), bytes_read-total_bytes_used);
buf_start = bytes_read-total_bytes_used;
}
::fprintf(stderr, "\n");
reader->end_of_log();
// ::fprintf(stderr, "Packet count: %d\n", packet_count);
}