Skip to content

Commit e2f8c02

Browse files
author
Lukasz Baj
committed
[SRC] Implement new writer - write metadata to file
1 parent c926390 commit e2f8c02

File tree

6 files changed

+378
-6
lines changed

6 files changed

+378
-6
lines changed

CMakeLists.txt

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,12 @@ if (ZEROMQ_WRITER)
6767
add_definitions("-DZEROMQ_SUPPORT_WRITER")
6868
endif()
6969

70+
if (FILE)
71+
set(SOURCE ${SOURCE}
72+
metadata_writer_file.c)
73+
add_definitions("-DFILE_SUPPORT")
74+
endif()
75+
7076
if (ZEROMQ_INPUT)
7177
set(LIBS ${LIBS} zmq)
7278
set(SOURCE ${SOURCE}

metadata_exporter.c

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,10 +71,15 @@
7171
#include "metadata_writer_neat.h"
7272
#endif
7373

74+
#ifdef FILE_SUPPORT
75+
#include "metadata_writer_file.h"
76+
#endif
77+
7478
#include "netlink_helpers.h"
7579
#include "backend_event_loop.h"
7680
#include "metadata_exporter_log.h"
7781

82+
struct md_writer_file;
7883
struct md_input_gpsd;
7984
struct md_input_munin;
8085
struct md_input_sysevent;
@@ -882,13 +887,26 @@ int main(int argc, char *argv[])
882887
mde->md_writers[MD_WRITER_ZEROMQ] = calloc(sizeof(struct md_writer_zeromq), 1);
883888

884889
if (mde->md_writers[MD_WRITER_ZEROMQ] == NULL) {
885-
META_PRINT_SYSLOG(mde, LOG_ERR, "Could not allocate SQLite writer\n");
890+
META_PRINT_SYSLOG(mde, LOG_ERR, "Could not allocate ZMQ writer\n");
886891
exit(EXIT_FAILURE);
887892
}
888893

889894
md_zeromq_writer_setup(mde, (struct md_writer_zeromq*) mde->md_writers[MD_WRITER_ZEROMQ]);
890895
num_writers++;
891896
}
897+
#endif
898+
#ifdef FILE_SUPPORT
899+
else if (!strcmp(key, "file")) {
900+
mde->md_writers[MD_WRITER_FILE] = calloc(sizeof(struct md_writer_file), 1);
901+
902+
if (mde->md_writers[MD_WRITER_FILE] == NULL) {
903+
META_PRINT_SYSLOG(mde, LOG_ERR, "Could not allocate file writer\n");
904+
exit(EXIT_FAILURE);
905+
}
906+
907+
md_file_setup(mde, (struct md_writer_file*) mde->md_writers[MD_WRITER_FILE]);
908+
num_writers++;
909+
}
892910
#endif
893911
else if (!strcmp(key, "test")) {
894912
test_mode = 1;

metadata_exporter.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,7 @@ enum md_writers {
120120
MD_WRITER_ZEROMQ,
121121
MD_WRITER_NNE,
122122
MD_WRITER_NEAT,
123+
MD_WRITER_FILE,
123124
__MD_WRITER_MAX
124125
};
125126

metadata_writer_file.c

Lines changed: 304 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,304 @@
1+
/* Copyright (c) 2017, Celerway, Lukasz Baj <l.baj@radytek.com>
2+
* All rights reserved.
3+
*
4+
* Redistribution and use in source and binary forms, with or without
5+
* modification, are permitted provided that the following conditions are met:
6+
*
7+
* 1. Redistributions of source code must retain the above copyright notice,
8+
* this list of conditions and the following disclaimer.
9+
*
10+
* 2. Redistributions in binary form must reproduce the above copyright notice,
11+
* this list of conditions and the following disclaimer in the documentation
12+
* and/or other materials provided with the distribution.
13+
*
14+
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
15+
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16+
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17+
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
18+
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
19+
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
20+
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
21+
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
22+
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
23+
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
24+
* POSSIBILITY OF SUCH DAMAGE.
25+
*/
26+
27+
#include <stdio.h>
28+
#include <stdlib.h>
29+
#include <unistd.h>
30+
31+
#include "backend_event_loop.h"
32+
#include "metadata_exporter_log.h"
33+
#include "metadata_exporter.h"
34+
#include "metadata_writer_file.h"
35+
36+
static int md_file_add_json_int(struct json_object *obj,
37+
const char *key, int64_t value)
38+
{
39+
struct json_object *value_obj = NULL;
40+
41+
value_obj = json_object_new_int64(value);
42+
if (!value_obj)
43+
return RETVAL_FAILURE;
44+
45+
json_object_object_add(obj, key, value_obj);
46+
return RETVAL_SUCCESS;
47+
}
48+
49+
static int md_file_add_json_string(struct json_object *obj,
50+
const char *key, const char *value)
51+
{
52+
struct json_object *value_obj = NULL;
53+
54+
if (value != NULL)
55+
{
56+
value_obj = json_object_new_string(value);
57+
if (!value_obj)
58+
return RETVAL_FAILURE;
59+
}
60+
61+
json_object_object_add(obj, key, value_obj);
62+
return RETVAL_SUCCESS;
63+
}
64+
65+
static int md_file_save(struct md_writer_file *mwf, int event_type, const char *content)
66+
{
67+
int output_fd;
68+
char dst_filename[256];
69+
FILE *output;
70+
71+
memset(mwf->prefix + mwf->prefix_len, 'X', 6);
72+
73+
output_fd = mkstemp(mwf->prefix);
74+
if (output_fd == -1) {
75+
META_PRINT_SYSLOG(mwf->parent, LOG_ERR, "Could not create temporary filename. Error: %s\n", strerror(errno));
76+
return RETVAL_FAILURE;
77+
}
78+
79+
output = fdopen(output_fd, "w");
80+
81+
if (!output) {
82+
META_PRINT_SYSLOG(mwf->parent, LOG_ERR, "Could not open random file as FILE*. Error: %s\n", strerror(errno));
83+
remove(mwf->prefix);
84+
return RETVAL_FAILURE;
85+
}
86+
87+
fprintf(output, "%s", content);
88+
fclose(output);
89+
90+
snprintf(dst_filename, 256, "%s_%d.json", mwf->prefix, event_type);
91+
META_PRINT_SYSLOG(mwf->parent, LOG_INFO, "Done with tmpfile %s\n", dst_filename);
92+
93+
if (link(mwf->prefix, dst_filename) || unlink(mwf->prefix)) {
94+
META_PRINT_SYSLOG(mwf->parent, LOG_ERR, "Could not link/unlink dump-file: %s\n", strerror(errno));
95+
remove(mwf->prefix);
96+
remove(dst_filename);
97+
return RETVAL_FAILURE;
98+
}
99+
100+
return RETVAL_SUCCESS;
101+
}
102+
103+
static void md_file_handle_iface_event(struct md_writer_file *mwf,
104+
struct md_iface_event *mie)
105+
{
106+
const char *json_string;
107+
struct json_object *obj = json_object_new_object();
108+
109+
if (obj == NULL) {
110+
META_PRINT_SYSLOG(mwf->parent, LOG_ERR, "md_file_handle_iface_event: Can't allocate iface json object!");
111+
return;
112+
}
113+
114+
if (md_file_add_json_int(obj, "timestamp", mie->tstamp) ||
115+
md_file_add_json_int(obj, "event_type", mie->md_type) ||
116+
md_file_add_json_int(obj, "event_param", mie->event_param) ||
117+
md_file_add_json_int(obj, "sequence", mie->sequence) ||
118+
md_file_add_json_string(obj, "iccid", mie->iccid) ||
119+
md_file_add_json_string(obj, "imsi", mie->imsi) ||
120+
md_file_add_json_string(obj, "imei", mie->imei) ||
121+
md_file_add_json_string(obj, "isp_name", mie->isp_name) ||
122+
md_file_add_json_int(obj, "mode", mie->device_mode) ||
123+
md_file_add_json_int(obj, "submode", mie->device_submode) ||
124+
md_file_add_json_int(obj, "cid", mie->cid) ||
125+
md_file_add_json_int(obj, "enodeb_id", mie->enodeb_id) ||
126+
md_file_add_json_int(obj, "lac", mie->lac) ||
127+
md_file_add_json_int(obj, "device_state", mie->device_state)) {
128+
META_PRINT_SYSLOG(mwf->parent, LOG_ERR, "md_file_handle_iface_event: Can't create iface values to object!");
129+
json_object_put(obj);
130+
return;
131+
}
132+
133+
if (mie->device_mode != 5) {
134+
if (md_file_add_json_int(obj, "rssi", mie->rssi) ||
135+
md_file_add_json_int(obj, "rscp", mie->rscp) ||
136+
md_file_add_json_int(obj, "ecio", mie->ecio)) {
137+
META_PRINT_SYSLOG(mwf->parent, LOG_ERR, "md_file_handle_iface_event: Can't add non-LTE values to object!");
138+
json_object_put(obj);
139+
return;
140+
}
141+
} else { // LTE
142+
if (md_file_add_json_int(obj, "lte_rssi", mie->lte_rssi) ||
143+
md_file_add_json_int(obj, "lte_rsrp", mie->lte_rsrp) ||
144+
md_file_add_json_int(obj, "lte_rsrq", mie->lte_rsrq) ||
145+
md_file_add_json_int(obj, "lte_freq", mie->lte_freq) ||
146+
md_file_add_json_int(obj, "lte_pci", mie->lte_pci) ||
147+
md_file_add_json_int(obj, "lte_band", mie->lte_band)) {
148+
META_PRINT_SYSLOG(mwf->parent, LOG_ERR, "md_file_handle_iface_event: Can't add LTE values to object!");
149+
json_object_put(obj);
150+
return;
151+
}
152+
}
153+
154+
json_string = json_object_to_json_string_ext(obj, JSON_C_TO_STRING_PLAIN);
155+
md_file_save(mwf, mie->event_type, json_string);
156+
157+
json_object_put(obj);
158+
}
159+
160+
static void md_file_handle_conn_event(struct md_writer_file *mwf,
161+
struct md_conn_event *mce)
162+
{
163+
const char *json_string;
164+
struct json_object *obj = json_object_new_object();
165+
166+
if (obj == NULL) {
167+
META_PRINT_SYSLOG(mwf->parent, LOG_ERR, "md_file_handle_conn_event: Can't allocate iface json object!");
168+
return;
169+
}
170+
171+
if (md_file_add_json_int(obj, "timestamp", mce->tstamp) ||
172+
md_file_add_json_int(obj, "event_type", mce->md_type) ||
173+
md_file_add_json_int(obj, "event_param", mce->event_param) ||
174+
md_file_add_json_int(obj, "event_value", mce->event_value) ||
175+
md_file_add_json_int(obj, "sequence", mce->sequence) ||
176+
md_file_add_json_string(obj, "imei", mce->imei) ||
177+
md_file_add_json_string(obj, "imsi", mce->imsi) ||
178+
md_file_add_json_int(obj, "interface_type", mce->interface_type) ||
179+
md_file_add_json_int(obj, "network_address_family", mce->network_address_family) ||
180+
md_file_add_json_int(obj, "network_provider_type", mce->network_provider_type) ||
181+
md_file_add_json_int(obj, "signal_strength", mce->signal_strength) ||
182+
md_file_add_json_int(obj, "l3_session_id", mce->l3_session_id) ||
183+
md_file_add_json_int(obj, "l4_session_id", mce->l4_session_id) ||
184+
md_file_add_json_int(obj, "rx_bytes", mce->rx_bytes) ||
185+
md_file_add_json_int(obj, "tx_bytes", mce->tx_bytes) ||
186+
md_file_add_json_string(obj, "interface_id", mce->interface_id) ||
187+
md_file_add_json_string(obj, "interface_name", mce->interface_name) ||
188+
md_file_add_json_int(obj, "network_provider", mce->network_provider) ||
189+
md_file_add_json_string(obj, "network_address", mce->network_address) ||
190+
md_file_add_json_int(obj, "connectivity", mce->connectivity) ||
191+
md_file_add_json_int(obj, "connection_mode", mce->connection_mode) ||
192+
md_file_add_json_int(obj, "quality", mce->quality)) {
193+
META_PRINT_SYSLOG(mwf->parent, LOG_ERR, "md_file_handle_conn_event: Can't add conn values to object!");
194+
json_object_put(obj);
195+
return;
196+
}
197+
198+
json_string = json_object_to_json_string_ext(obj, JSON_C_TO_STRING_PLAIN);
199+
md_file_save(mwf, mce->event_type, json_string);
200+
201+
json_object_put(obj);
202+
}
203+
204+
static const char* md_file_convert_float_to_string(const float number)
205+
{
206+
static char text[32];
207+
208+
memset(text, 0, sizeof(text));
209+
sprintf(text, "%f", number);
210+
return text;
211+
}
212+
213+
static void md_file_handle_gps_event(struct md_writer_file *mwf,
214+
struct md_gps_event *mge)
215+
{
216+
const char *json_string;
217+
struct json_object *obj = json_object_new_object();
218+
219+
if (obj == NULL) {
220+
META_PRINT_SYSLOG(mwf->parent, LOG_ERR, "md_file_handle_gps_event: Can't allocate iface json object!");
221+
return;
222+
}
223+
224+
if (md_file_add_json_int(obj, "timestamp", mge->tstamp) ||
225+
md_file_add_json_int(obj, "event_type", mge->md_type) ||
226+
md_file_add_json_int(obj, "sequence", mge->sequence) ||
227+
md_file_add_json_int(obj, "tstamp_tv.tv_sec", mge->tstamp_tv.tv_sec) ||
228+
md_file_add_json_int(obj, "tstamp_tv.tv_usec", mge->tstamp_tv.tv_usec) ||
229+
md_file_add_json_string(obj, "nmea_raw", mge->nmea_raw) ||
230+
md_file_add_json_int(obj, "time.hours", mge->time.hours) ||
231+
md_file_add_json_int(obj, "time.minutes", mge->time.minutes) ||
232+
md_file_add_json_int(obj, "time.seconds", mge->time.seconds) ||
233+
md_file_add_json_int(obj, "time.microseconds", mge->time.microseconds) ||
234+
md_file_add_json_string(obj, "latitude", md_file_convert_float_to_string(mge->latitude)) ||
235+
md_file_add_json_string(obj, "longitude", md_file_convert_float_to_string(mge->longitude)) ||
236+
md_file_add_json_string(obj, "speed", md_file_convert_float_to_string(mge->speed)) ||
237+
md_file_add_json_string(obj, "altitude", md_file_convert_float_to_string(mge->altitude)) ||
238+
md_file_add_json_int(obj, "time.microseconds", mge->satellites_tracked) ||
239+
md_file_add_json_int(obj, "time.microseconds", mge->minmea_id)) {
240+
META_PRINT_SYSLOG(mwf->parent, LOG_ERR, "md_file_handle_gps_event: Can't add gps values to object!");
241+
json_object_put(obj);
242+
return;
243+
}
244+
245+
json_string = json_object_to_json_string_ext(obj, JSON_C_TO_STRING_PLAIN);
246+
md_file_save(mwf, mge->md_type, json_string);
247+
248+
json_object_put(obj);
249+
}
250+
251+
static int32_t md_file_init(void *ptr, json_object* config)
252+
{
253+
struct md_writer_file *mwf = ptr;
254+
memset(mwf->prefix, 0, 128);
255+
256+
json_object* subconfig;
257+
if (json_object_object_get_ex(config, "file", &subconfig)) {
258+
json_object_object_foreach(subconfig, key, val) {
259+
if (!strcmp(key, "prefix") && json_object_is_type(val, json_type_string)) {
260+
strncpy(mwf->prefix, json_object_get_string(val), json_object_get_string_len(val));
261+
mwf->prefix_len = strlen(mwf->prefix);
262+
return RETVAL_SUCCESS;
263+
}
264+
}
265+
}
266+
267+
META_PRINT_SYSLOG(mwf->parent, LOG_INFO, "md_file_init: Can't initialize writer!");
268+
return RETVAL_FAILURE;
269+
}
270+
271+
static void md_file_handle(struct md_writer *writer, struct md_event *event)
272+
{
273+
struct md_writer_file *mwf = (struct md_writer_file*) writer;
274+
META_PRINT_SYSLOG(mwf->parent, LOG_INFO, "md_file_handle: event type %u\n", event->md_type);
275+
276+
switch (event->md_type) {
277+
case META_TYPE_INTERFACE:
278+
md_file_handle_iface_event(mwf, (struct md_iface_event*) event);
279+
break;
280+
case META_TYPE_CONNECTION:
281+
md_file_handle_conn_event(mwf, (struct md_conn_event*) event);
282+
break;
283+
case META_TYPE_POS:
284+
md_file_handle_gps_event(mwf, (struct md_gps_event*) event);
285+
break;
286+
287+
default:
288+
return;
289+
}
290+
}
291+
292+
void md_file_usage()
293+
{
294+
fprintf(stderr, "\"file\": {\t\tFile writer.\n");
295+
fprintf(stderr, " \"prefix\":\tOutput file name prefix\n");
296+
fprintf(stderr, "}\n");
297+
}
298+
299+
void md_file_setup(struct md_exporter *mde, struct md_writer_file *mwf)
300+
{
301+
mwf->parent = mde;
302+
mwf->init = md_file_init;
303+
mwf->handle = md_file_handle;
304+
}

0 commit comments

Comments
 (0)