automotive-dlt
dlt-logstorage-ctrl.c
Go to the documentation of this file.
1 
23 /*******************************************************************************
24 ** **
25 ** SRC-MODULE: dlt-logstorage-ctrl.c **
26 ** **
27 ** TARGET : linux **
28 ** **
29 ** PROJECT : DLT **
30 ** **
31 ** AUTHOR : Syed Hameed shameed@jp.adit-jv.com **
32 ** Christoph Lipka clipka@jp.adit-jv.com **
33 ** AnithaAmmaji.baggam@in.bosch.com **
34 ** Frederic Berat fberat@de.adit-jv.com **
35 ** PURPOSE : **
36 ** **
37 ** REMARKS : **
38 ** **
39 ** PLATFORM DEPENDANT [yes/no]: yes **
40 ** **
41 ** TO BE CHANGED BY USER [yes/no]: no **
42 ** **
43 *******************************************************************************/
44 
45 /*******************************************************************************
46 ** Author Identity **
47 ********************************************************************************
48 ** Initials Name Company **
49 ** -------- ------------------------- ---------------------------------- **
50 ** sh Syed Hameed ADIT **
51 ** cl Christoph Lipka ADIT **
52 ** BA Anitha BA ADIT **
53 ** fb Frederic Berat ADIT **
54 *******************************************************************************/
55 
56 #define pr_fmt(fmt) "Logstorage control: "fmt
57 
58 #include <ctype.h>
59 #include <errno.h>
60 #include <stdio.h>
61 #include <stdlib.h>
62 #include <signal.h>
63 #include <string.h>
64 #include <getopt.h>
65 
66 #include <sys/epoll.h>
67 
68 #include "sd-daemon.h"
69 
70 #include "dlt_protocol.h"
71 #include "dlt_client.h"
72 #include "dlt-control-common.h"
73 #include "dlt-logstorage-common.h"
74 #include "dlt-logstorage-ctrl.h"
75 
76 #define EPOLL_MAX_EVENTS 10
77 #define EPOLL_TIME_OUT 500
78 
79 #define DLT_LOGSTORAGE_CTRL_EXIT 1
80 static int must_exit;
81 static int efd;
82 
88 {
90 }
91 
97 {
98  return must_exit;
99 }
100 
107 static void catch_signal(int signo)
108 {
109  if (signo)
110  {
111  pr_error("Signal %d received, exiting.", signo);
113  }
114 }
115 
121 static void install_signal_handler(void)
122 {
123  int signals[] = { SIGINT, SIGQUIT, SIGTERM, 0 };
124  unsigned int i;
125  struct sigaction sa;
126 
127  pr_verbose("Installing signal handler.\n");
128 
129  /* install a signal handler for the above listed signals */
130  for (i = 0 ; signals[i] ; i++)
131  {
132  memset(&sa, 0, sizeof(sa));
133  sa.sa_handler = catch_signal;
134 
135  if (sigaction(signals[i], &sa, NULL) < 0)
136  {
137  pr_error("Failed to install signal %u handler. Error: %s\n",
138  signals[i], strerror(errno));
139  }
140  }
141 }
142 
143 #define MAX_RESPONSE_LENGTH 32
144 
154 static int analyze_response(char *data, void *payload, int len)
155 {
156  int ret = -1;
157  char resp_ok[MAX_RESPONSE_LENGTH] = { 0 };
158 
159  if (data == NULL || payload == NULL)
160  {
161  return -1;
162  }
163 
164  /* satisfy compiler */
165  payload = payload;
166  len = len;
167 
168  snprintf(resp_ok,
170  "service(%u), ok",
172 
173  if (strncmp(data, resp_ok, strlen(resp_ok)) == 0)
174  {
175  ret = 0;
176  }
177 
178  pr_verbose("Response received: '%s'\n", data);
179  pr_verbose("Response expected: '%s'\n", resp_ok);
180 
181  return ret;
182 }
183 
195 static int dlt_logstorage_ctrl_add_event(int fd, void *cb)
196 {
197  struct epoll_event event;
198 
199  if ((fd < 0) || !cb)
200  {
201  pr_error("Wrong parameter to add event (%d %p)\n", fd, cb);
202  return -1;
203  }
204 
205  pr_verbose("Setting up the event handler with (%d, %p).\n", fd, cb);
206 
207  event.data.ptr = cb;
208  event.events = EPOLLIN | EPOLLET;
209 
210  return epoll_ctl(efd, EPOLL_CTL_ADD, fd, &event);
211 }
212 
221 {
222  struct epoll_event *events;
223  int i;
224  int ret = 0;
225  int n = 0;
226 
227  events = calloc(10, sizeof(struct epoll_event));
228 
229  if (!events)
230  {
231  pr_error("No memory available for events.\n");
232  return -1;
233  }
234 
235  n = epoll_wait(efd, events, EPOLL_MAX_EVENTS, EPOLL_TIME_OUT);
236 
237  if (n < 0)
238  {
239  pr_error("epoll_wait error: %s\n", strerror(errno));
240 
241  if (errno == EINTR)
242  {
243  /* Only exit if the daemon has received QUIT/INT/TERM */
244  free(events);
245  return 0;
246  }
247 
248  free(events);
249  return -1;
250  }
251 
252  for (i = 0 ; i < n ; i++)
253  {
254  int (*callback)() = events[i].data.ptr;
255 
256  if (!(events[i].events & (EPOLLIN | EPOLLET)))
257  {
258  pr_error("Error while polling. Event received: 0x%x\n",
259  events[i].events);
260  /* We only support one event producer.
261  * Error means that this producer died.
262  */
263  pr_error("Now closing fd and exiting.\n");
264  close(events[i].data.fd);
266  ret = -1;
267  break;
268  }
269 
270  if (!callback)
271  {
272  pr_error("Callback not found, exiting.\n");
274  ret = -1;
275  break;
276  }
277 
278  pr_verbose("Got new event, calling %p.\n", callback);
279 
280  if (callback() < 0)
281  {
282  pr_error("Error while calling the callback, exiting.\n");
284  ret = -1;
285  break;
286  }
287  }
288 
289  free(events);
290  return ret;
291 }
292 
302 {
303  int ret = 0;
304 
306 
307  pr_verbose("Creating epoll instance.\n");
308  efd = epoll_create1(0);
309 
310  if (efd == -1)
311  {
312  pr_error("epoll_create error: %s\n", strerror(errno));
314  return -errno;
315  }
316 
317  /* Initializing the communication with the daemon */
320  {
321  pr_error("Failed to initialize connection with the daemon.\n");
322  pr_error("Retrying to connect in %lds.\n", get_timeout());
323  sleep(get_timeout());
324  }
325 
327  {
328  pr_verbose("Exiting.\n");
329  return 0;
330  }
331 
332  pr_verbose("Initializing event generator.\n");
333 
334  if (dlt_logstorage_init_handler() < 0)
335  {
336  pr_error("Failed to initialize handler.\n");
338  return -1;
339  }
340 
343  {
344  pr_error("epoll_ctl error: %s\n", strerror(errno));
346  }
347 
348  while (!dlt_logstorage_must_exit() && (ret == 0))
349  {
351  }
352 
353  /* Clean up */
354  close(efd);
355 
358 
359  return ret;
360 }
361 
367 {
368  int ret = 0;
369 
370  /* in case sync all caches, an empty path is given */
372  {
373  /* Check if a 'CONF_NAME' file is present at the given path */
375  {
376  pr_error("No '%s' file available at: %s\n",
377  CONF_NAME,
378  get_default_path());
379  return -1;
380  }
381 
383  {
384  pr_error("'%s' is not writable\n", get_default_path());
385  return -1;
386  }
387  }
388 
389  /* Initializing the communication with the daemon */
392  {
393  pr_error("Failed to initialize connection with the daemon.\n");
394  pr_error("Retrying to connect in %lds.\n", get_timeout());
395  sleep(get_timeout());
396  }
397 
398  pr_verbose("event type is [%d]\t device path is [%s]\n",
400  get_default_path());
401 
403  get_default_path());
404 
406 
407  return ret;
408 }
409 
412 static void usage(void)
413 {
414  printf("Usage: dlt-logstorage-ctrl [options]\n");
415  printf("Send a trigger to DLT daemon to connect/disconnect"
416  "a certain logstorage device\n");
417  printf("\n");
418  printf("Options:\n");
419  printf(" -c --command Connection type: connect = 1, disconnect = 0\n");
420  printf(" -d[prop] --daemonize=prop Run as daemon: prop = use proprietary handler\n");
421  printf(" 'prop' may be replaced by any meaningful word\n");
422  printf(" If prop is not specified, udev will be used\n");
423  printf(" -e --ecuid Set ECU ID (Default: %s)\n", DLT_CTRL_DEFAULT_ECUID);
424  printf(" -h --help Usage\n");
425  printf(" -p --path Mount point path\n");
426  printf(" -s[path] --snapshot=path Sync Logstorage cache\n");
427  printf(" Don't use -s together with -d and -c\n");
428  printf(" -t Specify connection timeout (Default: %ds)\n",
430  printf(" -v --verbose Set verbose flag (Default:%d)\n", get_verbosity());
431 }
432 
433 static struct option long_options[] = {
434  {"command", required_argument, 0, 'c'},
435  {"daemonize", optional_argument, 0, 'd'},
436  {"ecuid", required_argument, 0, 'e'},
437  {"help", no_argument, 0, 'h'},
438  {"path", required_argument, 0, 'p'},
439  {"snapshot", optional_argument, 0, 's'},
440  {"timeout", required_argument, 0, 't'},
441  {"verbose", no_argument, 0, 'v'},
442  {0, 0, 0, 0}
443 };
444 
454 static int parse_args(int argc, char *argv[])
455 {
456  int c = -1;
457  int long_index = 0;
458 
459  while ((c = getopt_long(argc,
460  argv,
461  ":s::t:he:p:d::c:v",
462  long_options,
463  &long_index)) != -1)
464  {
465  switch (c)
466  {
467  case 's':
469 
470  if (optarg != NULL && strlen(optarg) >= DLT_MOUNT_PATH_MAX)
471  {
472  pr_error("Mount path '%s' too long\n", optarg);
473  return -1;
474  }
475 
476  set_default_path(optarg);
477  break;
478  case 't':
479  set_timeout(strtol(optarg, NULL, 10));
480  break;
481  case 'h':
482  usage();
483  return -1;
484  case 'e':
485  set_ecuid(optarg);
486  break;
487  case 'd':
488  pr_verbose("Choosing handler.\n");
489  set_handler_type(optarg);
490  pr_verbose("Handler chosen: %d.\n", get_handler_type());
491  break;
492  case 'p':
493 
494  if (strlen(optarg) >= DLT_MOUNT_PATH_MAX)
495  {
496  pr_error("Mount path '%s' too long\n", optarg);
497  return -1;
498  }
499 
500  set_default_path(optarg);
501  break;
502  case 'c':
503  set_default_event_type(strtol(optarg, NULL, 10));
504  break;
505  case 'v':
506  set_verbosity(1);
507  pr_verbose("Now in verbose mode.\n");
508  break;
509  case ':':
510  pr_error("Option -%c requires an argument.\n", optopt);
511  usage();
512  return -1;
513  case '?':
514 
515  if (isprint(optopt))
516  {
517  pr_error("Unknown option -%c.\n", optopt);
518  }
519  else
520  {
521  pr_error("Unknown option character \\x%x.\n", optopt);
522  }
523 
524  usage();
525  return -1;
526  default:
527  pr_error("Try %s -h for more information.\n", argv[0]);
528  return -1;
529  }
530  }
531 
534  {
535  pr_error("Sync caches not available in daemon mode\n");
536  return -1;
537  }
538 
539  return 0;
540 }
541 
551 int main(int argc, char *argv[])
552 {
553  int ret = 0;
554 
555  set_ecuid(NULL);
557 
558  /* Get command line arguments */
559  if (parse_args(argc, argv) != 0)
560  {
561  return -1;
562  }
563 
564  /* all parameter valid, start communication with daemon or setup
565  * communication with control daemon */
567  {
568  pr_verbose("One shot.\n");
569 
571  if (ret < 0)
572  {
573  pr_error("Message failed to be send. Please check DLT config.\n");
574  }
575  }
576  else
577  {
578  pr_verbose("Entering in daemon mode.\n");
579 
580  /* Let's daemonize */
581  if (sd_notify(0, "READY=1") <= 0)
582  {
583  pr_verbose("SD notify failed, manually daemonizing.\n");
584 
585  /* No message can be sent or Systemd is not available.
586  * Daemonizing manually.
587  */
588  if (daemon(1, 1))
589  {
590  pr_error("Failed to daemonize: %s\n", strerror(errno));
591  return EXIT_FAILURE;
592  }
593  }
594 
595  pr_verbose("Executing the event loop\n");
597  }
598 
599  pr_verbose("Exiting.\n");
600  return ret;
601 }
#define CONF_NAME
#define DLT_LOGSTORAGE_CTRL_EXIT
int dlt_logstorage_get_handler_fd(void)
void set_default_path(char *path)
static void catch_signal(int signo)
Signal handler.
void set_verbosity(int v)
static void install_signal_handler(void)
Install a handler for some signals.
#define MAX_RESPONSE_LENGTH
#define DLT_CTRL_TIMEOUT
#define EVENT_SYNC_CACHE
static int dlt_logstorage_ctrl_single_request()
Send a single command to DLT daemon and wait for response.
#define DLT_SERVICE_ID_OFFLINE_LOGSTORAGE
Definition: dlt_protocol.h:201
DltLogstorageHandler get_handler_type(void)
int dlt_control_deinit(void)
Control communication clean-up.
void set_timeout(long t)
int dlt_logstorage_check_config_file(char *mnt_point)
Search for config file in given mount point.
void * dlt_logstorage_get_handler_cb(void)
#define DLT_MOUNT_PATH_MAX
Definition: dlt_common.h:332
static int parse_args(int argc, char *argv[])
Parses the application arguments.
void set_handler_type(char *type)
char * get_default_path(void)
static char data[kDataSize]
Definition: city-test.cc:40
int dlt_logstorage_must_exit(void)
Check if the application must exit.
static int dlt_logstorage_ctrl_setup_event_loop(void)
Start event loop and receive messages from DLT.
static int analyze_response(char *data, void *payload, int len)
Analyze the daemon answer to a request.
char * get_ecuid(void)
static struct option long_options[]
void set_default_event_type(long type)
static void usage(void)
Print out the application help.
int main(int argc, char *argv[])
Entry point.
#define pr_error(fmt,...)
int get_default_event_type(void)
#define EPOLL_TIME_OUT
static int must_exit
static int efd
int dlt_logstorage_send_event(int type, char *mount_point)
Send a logstorage event to DLT.
#define pr_verbose(fmt,...)
int dlt_control_init(int(*response_analyzer)(char *, void *, int), char *ecuid, int verbosity)
Control communication initialization.
#define EPOLL_MAX_EVENTS
int dlt_logstorage_deinit_handler(void)
Clean-up the handler based on configuration.
#define DLT_CTRL_DEFAULT_ECUID
int get_verbosity(void)
long get_timeout(void)
int dlt_logstorage_init_handler(void)
Initialized the handler based on configuration.
void dlt_logstorage_exit(void)
Triggers the application exit.
static int dlt_logstorage_ctrl_execute_event_loop(int efd)
Main execution loop.
int dlt_logstorage_check_directory_permission(char *mnt_point)
Check if given mount point is writable.
static int dlt_logstorage_ctrl_add_event(int fd, void *cb)
Add a new event to watch to the epoll instance.
#define NULL
Definition: dlt_common.h:232
void set_ecuid(char *ecuid)