libxcoder  3.5.4
ni_rsrc_mon_logan.c
Go to the documentation of this file.
1 /*******************************************************************************
2  *
3  * Copyright (C) 2022 NETINT Technologies
4  *
5  * Permission is hereby granted, free of charge, to any person obtaining a copy
6  * of this software and associated documentation files (the "Software"), to deal
7  * in the Software without restriction, including without limitation the rights
8  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9  * copies of the Software, and to permit persons to whom the Software is
10  * furnished to do so, subject to the following conditions:
11  *
12  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
13  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
14  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
15  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
16  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
17  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
18  * SOFTWARE.
19  *
20  ******************************************************************************/
21 
22 /*!*****************************************************************************
23  *
24  * \file ni_rsrc_mon_logan.c
25  *
26  * @date April 1, 2018
27  *
28  * \brief NETINT T4XX resource monitor utility program
29  *
30  * @author
31  *
32  ******************************************************************************/
33 
34 #if defined(__linux__) || defined(__APPLE__)
35 #include <unistd.h>
36 #include <signal.h>
37 #include <sys/file.h> /* For flock constants */
38 #endif
39 
40 #include <stdio.h>
41 #include <stdlib.h>
42 
43 #include <errno.h>
44 #include <time.h>
45 #include <ctype.h>
46 #include <string.h>
47 #include "ni_defs_logan.h"
48 #include "ni_device_api_logan.h"
49 #include "ni_rsrc_api_logan.h"
50 #include "ni_rsrc_priv_logan.h"
51 #include "ni_util_logan.h"
52 
53 #ifdef __ANDROID__
54 #include <cutils/properties.h>
55 
56 #define LOG_TAG "ni_rsrc_mon_logan"
57 
58 #endif
59 
60 #ifdef _WIN32
61 #include "ni_getopt_logan.h"
62 
63 static BOOL WINAPI console_ctrl_handler(DWORD ctrl_type)
64 {
66  return TRUE;
87 }
88 
89 #elif defined(__linux__)
90 void setup_signal_handler(void);
91 
92 
93 /*!******************************************************************************
94  * \brief
95  *
96  * \param
97  *
98  * \return
99  *******************************************************************************/
100 void sig_handler(int sig)
101 {
102  if (sig == SIGTERM || sig == SIGINT)
103  {
105  }
106  else if (sig == SIGHUP)
107  {
108  printf("SIGHUP, reloading p_config ? ");
109  setup_signal_handler();
110  }
111 }
112 
113 /*!******************************************************************************
114  * \brief
115  *
116  * \param
117  *
118  * \return
119  *******************************************************************************/
120 void setup_signal_handler(void)
121 {
122  if (signal(SIGTERM, sig_handler) == SIG_ERR ||
123  signal(SIGHUP, sig_handler) == SIG_ERR ||
124  signal(SIGINT, sig_handler) == SIG_ERR)
125  {
126  fprintf(stderr, "Error %d: signal handler setup\n", NI_ERRNO);
127  }
128 }
129 
130 /*!******************************************************************************
131  * \brief get linux numa_node
132  *
133  * \param[in] const char *device_name
134  *
135  * \return int atoi(cmd_ret)
136  *******************************************************************************/
137 int get_numa_node(const char *device_name)
138 {
139  int ret = -1;
140  FILE *cmd_fp;
141  char *ptr = NULL;
142  char cmd[128] = {0};
143  char cmd_ret[64] = {0};
144 
145  if(!device_name)
146  {
147  return ret;
148  }
149  ptr = (char *)(device_name + 5);
150  snprintf(cmd, sizeof(cmd) - 1, "cat /sys/block/%s/device/*/numa_node",ptr);
151  cmd_fp = popen(cmd, "r");
152  if (!cmd_fp)
153  {
154  return ret;
155  }
156  if (fgets(cmd_ret, sizeof(cmd_ret)/sizeof(cmd_ret[0]), cmd_fp) == NULL)
157  {
158  LRETURN;
159  }
160  ret = atoi(cmd_ret);
161 
162 END:
163  pclose(cmd_fp);
164  return ret;
165 }
166 
167 #endif //defined(__linux__)
168 
169 
170 /*!******************************************************************************
171  * \brief convert number from argv input to integer if safe
172  *
173  * \param char *numArray
174  *
175  * \return int atoi(numArray)
176  *******************************************************************************/
177 int argToI(char *numArray)
178 {
179  int i;
180 
181  if( !numArray )
182  {
183  return 0;
184  }
185 
186  const size_t len = strlen(numArray);
187 
188  for (i = 0; i < len; i++)
189  {
190  if (!isdigit(numArray[i]))
191  {
192  fprintf(stderr, "invalid, ABORTING\n");
193  abort();
194  }
195  }
196 
197  return len == i ? atoi(numArray) : 0;
198 }
199 
200 /*!******************************************************************************
201  * \brief compare two int32_t for qsort
202  *
203  * \param[in] const void *a
204  * \param[in] const void *b
205  *
206  * \return int atoi(numArray)
207  *******************************************************************************/
208 int compareInt32_t(const void *a, const void *b)
209 {
210  if ( *(int32_t*)a < *(int32_t*)b ) return -1;
211  if ( *(int32_t*)a == *(int32_t*)b ) return 0;
212  if ( *(int32_t*)a > *(int32_t*)b ) return 1;
213  return 0;
214 }
215 
216 unsigned int get_modules(ni_logan_device_type_t module_type,
217  ni_logan_device_queue_t *coders,
218  char *module_name,
219  int32_t **module_ids,
220  int32_t *best_load_module_id)
221 {
222  unsigned int module_count;
223 
224  if (module_type == NI_LOGAN_DEVICE_TYPE_DECODER)
225  {
226  module_count = coders->decoders_cnt;
227  snprintf(module_name, sizeof(module_name), "decoder");
228  *module_ids = (int32_t *)malloc(sizeof(int32_t) * module_count);
229  if(!(*module_ids))
230  {
231  fprintf(stderr, "ERROR %d: Failed to allocate memory for ni_rsrc_mon print_perf()",
232  NI_ERRNO);
233  return 0;
234  }
235  memcpy(*module_ids, coders->decoders, sizeof(int32_t) * module_count);
236  }
237  else if (module_type == NI_LOGAN_DEVICE_TYPE_ENCODER)
238  {
239  module_count = coders->encoders_cnt;
240  snprintf(module_name, sizeof(module_name), "encoder");
241  *module_ids = (int32_t *)malloc(sizeof(int32_t) * module_count);
242  if(!(*module_ids))
243  {
244  fprintf(stderr, "ERROR %d: Failed to allocate memory for ni_rsrc_mon print_perf()",
245  NI_ERRNO);
246  return 0;
247  }
248  memcpy(*module_ids, coders->encoders, sizeof(int32_t) * module_count);
249  }
250  else
251  {
252  fprintf(stderr, "ERROR: wrong module type %d", module_type);
253  return 0;
254  }
255  // First module ID in coders->decoders/encoders is of lowest load
256  if (best_load_module_id)
257  {
258  memcpy((void*)best_load_module_id, *module_ids, sizeof(int32_t));
259  }
260 
261  // sort module IDs used
262  qsort(*module_ids, module_count, sizeof(int32_t), compareInt32_t);
263 
264  return module_count;
265 }
266 
267 /*!******************************************************************************
268  * \brief print performance data for either decoder or encoder
269  *
270  * \param[in] ni_logan_device_type_t module_type
271  * \param[in] ni_logan_device_queue_t *coders
272  * \param[in] ni_logan_session_context_t *sessionCtxt
273  *
274  * \return ni_logan_retcode_t rc
275  *******************************************************************************/
277  ni_logan_device_queue_t *coders,
278  ni_logan_session_context_t *sessionCtxt,
279  int outformattype)
280 {
281  int i; // used in later FOR-loop when compiled without c99
282  int module_count = 0;
283  char module_name[8]={0};
284  int *module_id_arr = NULL;
285  int best_load_module_id = -1;
286  ni_logan_device_context_t *p_device_context = NULL;
287 
288  module_count = get_modules(module_type, coders, module_name, &module_id_arr, &best_load_module_id);
289 
290  if (outformattype == 0)
291  {
292  printf("Num %ss: %d\n", module_name, module_count);
293  }
294 
295  // Print performance info headings
296  if (outformattype == 0)
297  {
298  printf("%-4s %-5s %-4s %-10s %-4s %-4s %-14s %-20s\n", "BEST", "INDEX",
299  "LOAD", "MODEL_LOAD", "MEM", "INST", "DEVICE", "NAMESPACE");
300  }
301  else if (outformattype == 2 || outformattype == 3)
302  {
303  if (module_type == NI_LOGAN_DEVICE_TYPE_DECODER)
304  {
305  printf("{\n \"decoders\": [\n");
306  }
307  else if (module_type == NI_LOGAN_DEVICE_TYPE_ENCODER)
308  {
309  printf(" \"encoders\": [\n");
310  }
311  }
313  for (i = 0; i < module_count; i++)
314  {
315  p_device_context = ni_logan_rsrc_get_device_context(module_type, module_id_arr[i]);
316 
318  if (p_device_context)
319  {
320  sessionCtxt->blk_io_handle = ni_logan_device_open(p_device_context->p_device_info->blk_name,
321  &sessionCtxt->max_nvme_io_size);
322  sessionCtxt->device_handle = sessionCtxt->blk_io_handle;
323 
324  // Check device can be opened
325  if (NI_INVALID_DEVICE_HANDLE == sessionCtxt->device_handle)
326  {
327  fprintf(stderr, "Error open device %s, blk device %s\n",
328  p_device_context->p_device_info->dev_name,
329  p_device_context->p_device_info->blk_name);
330  ni_logan_rsrc_free_device_context(p_device_context);
331  continue;
332  }
333 
334 #ifdef _WIN32
335  sessionCtxt->event_handle = ni_logan_create_event();
336  if (NI_INVALID_EVENT_HANDLE == sessionCtxt->event_handle)
337  {
338  ni_logan_rsrc_free_device_context(p_device_context);
339  ni_logan_device_close(sessionCtxt->device_handle);
340  fprintf(stderr, "ERROR %d: print_perf() create envet\n", NI_ERRNO);
341  continue;
342  }
343 #endif
344 
345  // Check dec/enc can be queried
346  sessionCtxt->hw_id = p_device_context->p_device_info->hw_id;
347  if (NI_LOGAN_RETCODE_SUCCESS != ni_logan_device_session_query(sessionCtxt, module_type))
348  {
349  ni_logan_device_close(sessionCtxt->device_handle);
350 #ifdef _WIN32
351  ni_logan_close_event(sessionCtxt->event_handle);
352 #endif
353  fprintf(stderr, "Error query %s %s %s.%d\n", module_name,
354  p_device_context->p_device_info->dev_name,
355  p_device_context->p_device_info->blk_name,
356  p_device_context->p_device_info->hw_id);
357  ni_logan_rsrc_free_device_context(p_device_context);
358  continue;
359  }
360  ni_logan_device_close(sessionCtxt->device_handle);
361 #ifdef _WIN32
362  ni_logan_close_event(sessionCtxt->event_handle);
363 #endif
364 
365  if (0 == sessionCtxt->load_query.total_contexts)
366  {
367  sessionCtxt->load_query.current_load = 0;
368  }
369 
370  // Evaluate if module is of best load
371  char best_load_print[2] = " ";
372  if (best_load_module_id == p_device_context->p_device_info->module_id)
373  {
374  strncpy(best_load_print, "L", 1);
375  }
376 
377  // Print performance info row
378  if(outformattype == 0)
379  {
380  printf("%s%s%s %-5d %-4d %-10d %-4d %-4d %-14s %-20s\n", best_load_print, " ", " ",
381  p_device_context->p_device_info->module_id,
382  sessionCtxt->load_query.current_load,
383  sessionCtxt->load_query.fw_model_load,
384  sessionCtxt->load_query.fw_video_mem_usage,
385  sessionCtxt->load_query.total_contexts,
386  p_device_context->p_device_info->dev_name,
387  p_device_context->p_device_info->blk_name);
388  }
389  else if (outformattype == 1)
390  {
391  printf("{\n"
392  " \"%s\" : [\n"
393  " {\n"
394  " \"%s\" : %d,\n"
395  " \"%s\" : \"%s\",\n"
396  " \"%s\" : %d,\n"
397  " \"%s\" : %d,\n"
398  " \"%s\" : %d,\n"
399  " \"%s\" : %d,\n"
400  " \"%s\" : %d,\n"
401  " \"%s\" : \"%s\",\n"
402  " \"%s\" : \"%s\",\n"
403 #ifdef __linux__
404  " \"%s\" : %d\n"
405 #endif
406  " }\n"
407  " ]\n"
408  "}\n",
409  module_name, "NUMBER", module_count, "BEST", best_load_print,
410  "INDEX", p_device_context->p_device_info->module_id,
411  "LOAD", sessionCtxt->load_query.current_load,
412  "MODEL_LOAD", sessionCtxt->load_query.fw_model_load,
413  "MEM", sessionCtxt->load_query.fw_video_mem_usage,
414  "INST", sessionCtxt->load_query.total_contexts,
415  "DEVICE", p_device_context->p_device_info->dev_name,
416  "NAMESPACE", p_device_context->p_device_info->blk_name
417 #ifdef __linux__
418  ,"NUMA_NODE",get_numa_node(p_device_context->p_device_info->blk_name)
419 #endif
420  );
421  }
422  else if (outformattype == 3)
423  {
424  printf( " {\n"
425  " \"%s\" : %d,\n"
426  " \"%s\" : \"%s\",\n"
427  " \"%s\" : %d,\n"
428  " \"%s\" : %d,\n"
429  " \"%s\" : %d,\n"
430  " \"%s\" : %d,\n"
431  " \"%s\" : %d,\n"
432  " \"%s\" : \"%s\",\n"
433  " \"%s\" : \"%s\",\n"
434 #ifdef __linux__
435  " \"%s\" : %d,\n"
436 #endif
437  " \"%s\" : %d,\n"
438  " \"%s\" : \"%s\"\n"
439  " }",
440  "NUMBER", module_count, "BEST", best_load_print,
441  "INDEX", p_device_context->p_device_info->module_id,
442  "LOAD", sessionCtxt->load_query.current_load,
443  "MODEL_LOAD", sessionCtxt->load_query.fw_model_load,
444  "MEM", sessionCtxt->load_query.fw_video_mem_usage,
445  "INST", sessionCtxt->load_query.total_contexts,
446  "DEVICE", p_device_context->p_device_info->dev_name,
447  "NAMESPACE", p_device_context->p_device_info->blk_name
448 #ifdef __linux__
449  ,"NUMA_NODE",get_numa_node(p_device_context->p_device_info->blk_name)
450 #endif
451  ,"TEMP", sessionCtxt->composite_temperature,
452  "POWER", "N/A"
453  );
454  if (i < module_count - 1)
455  {
456  printf(",\n");
457  }
458  else
459  {
460  printf("\n");
461  }
462  }
463  else
464  {
465  printf( " {\n"
466  " \"%s\" : %d,\n"
467  " \"%s\" : \"%s\",\n"
468  " \"%s\" : %d,\n"
469  " \"%s\" : %d,\n"
470  " \"%s\" : %d,\n"
471  " \"%s\" : %d,\n"
472  " \"%s\" : %d,\n"
473  " \"%s\" : \"%s\",\n"
474  " \"%s\" : \"%s\",\n"
475 #ifdef __linux__
476  " \"%s\" : %d\n"
477 #endif
478  " }",
479  "NUMBER", module_count, "BEST", best_load_print,
480  "INDEX", p_device_context->p_device_info->module_id,
481  "LOAD", sessionCtxt->load_query.current_load,
482  "MODEL_LOAD", sessionCtxt->load_query.fw_model_load,
483  "MEM", sessionCtxt->load_query.fw_video_mem_usage,
484  "INST", sessionCtxt->load_query.total_contexts,
485  "DEVICE", p_device_context->p_device_info->dev_name,
486  "NAMESPACE", p_device_context->p_device_info->blk_name
487 #ifdef __linux__
488  ,"NUMA_NODE",get_numa_node(p_device_context->p_device_info->blk_name)
489 #endif
490  );
491  if (i < module_count - 1)
492  {
493  printf(",\n");
494  }
495  else
496  {
497  printf("\n");
498  }
499  }
500  ni_logan_rsrc_free_device_context(p_device_context);
501  }
502  }
503 
504  if (outformattype == 2 || outformattype == 3)
505  {
506  if (module_type == NI_LOGAN_DEVICE_TYPE_DECODER)
507  {
508  printf(" ],\n");
509  }
510  else if (module_type == NI_LOGAN_DEVICE_TYPE_ENCODER)
511  {
512  printf(" ]\n}\n");
513  }
514  }
515  free(module_id_arr);
516  return;
517 }
518 
520  ni_logan_session_context_t *p_session_context,
521  void** p_log_buffer,
522  bool gen_log_file)
523 {
525  if (!p_device_context)
526  return false;
527 
528  p_session_context->device_handle =
529  ni_logan_device_open(p_device_context->p_device_info->blk_name,
530  &p_session_context->max_nvme_io_size);
531  if (p_session_context->device_handle == NI_INVALID_DEVICE_HANDLE)
532  {
533  fprintf(stderr,
534  "ERROR: ni_device_open() failed for %s, errno %d\n",
535  p_device_context->p_device_info->blk_name,
536  NI_ERRNO);
537  ni_logan_rsrc_free_device_context(p_device_context);
538  return false;
539  }
540 #ifdef _WIN32
541  p_session_context->event_handle = ni_logan_create_event();
542  if (NI_INVALID_EVENT_HANDLE == p_session_context->event_handle)
543  {
544  ni_logan_rsrc_free_device_context(p_device_context);
545  ni_logan_device_close(p_session_context->device_handle);
546  fprintf(stderr, "ERROR %d: open_and_get_log() create envet\n",
547  NI_ERRNO);
548  return false;
549  }
550 #endif
551  p_session_context->blk_io_handle =
552  p_session_context->device_handle;
553  p_session_context->hw_id =
554  p_device_context->p_device_info->module_id;
555 
556  return_code = ni_logan_alloc_and_get_fw_logs(p_session_context, p_log_buffer, gen_log_file);
557 
558 #ifdef _WIN32
559  ni_logan_close_event(p_session_context->event_handle);
560 #endif
561  ni_logan_device_close(p_session_context->device_handle);
562  return return_code ? false : true;
563 }
564 
565 void dump_fw_log(ni_logan_device_queue_t *coders, ni_logan_session_context_t *sessionCtxt, int devid)
566 {
567  int i;
568  unsigned int module_count;
569  int32_t *module_id_arr = NULL;
570  char module_name[8] = {0};
571  ni_logan_device_context_t *p_device_context = NULL;
573 
574  module_count = get_modules(module_type, coders, module_name, &module_id_arr, NULL);
575  if (!module_count) {
576  printf("Error: module not found!\n");
577  return;
578  }
579 
580  bool gen_log_file = true; // dump and write fw logs to runtime dir
581 
582  void* p_log_buffer = NULL;
583  if (devid >= 0)
584  {
585  // dump fw logs of specified card
586  p_device_context = ni_logan_rsrc_get_device_context(module_type, devid);
587  if (!p_device_context)
588  {
589  printf("Error: get device context failed, devid %d\n", devid);
590  free(module_id_arr);
591  return;
592  }
593  if (p_device_context->p_device_info->module_id == devid)
594  {
595  if (!open_and_get_log(p_device_context, sessionCtxt, &p_log_buffer, gen_log_file)) {
596  printf("Error: failed to dump fw log of card:%d blk_name:%s\n",
597  devid, p_device_context->p_device_info->blk_name);
598  } else {
599  printf("Success: dumped fw log of card:%d blk_name:%s\n",
600  devid, p_device_context->p_device_info->blk_name);
601  }
602  ni_logan_rsrc_free_device_context(p_device_context);
603  }
604  }
605  else
606  {
607  // dump fw logs of all quadra cards
608  for (i = 0; i < module_count; i++)
609  {
610  p_device_context = ni_logan_rsrc_get_device_context(module_type, module_id_arr[i]);
611  if (!open_and_get_log(p_device_context, sessionCtxt, &p_log_buffer, gen_log_file)) {
612  printf("Error: failed to dump fw log of card:%d blk_name:%s\n",
613  p_device_context->p_device_info->module_id,
614  p_device_context->p_device_info->blk_name);
615  } else {
616  printf("Success: dumped fw log of card:%d blk_name:%s\n",
617  p_device_context->p_device_info->module_id,
618  p_device_context->p_device_info->blk_name);
619  }
620  ni_logan_rsrc_free_device_context(p_device_context);
621  }
622  }
623 
624  free(module_id_arr);
625 }
626 
627 /*!******************************************************************************
628  * \brief
629  *
630  * \param
631  *
632  * \return
633  * 0 on success
634  * 1 on failure
635  *******************************************************************************/
636 int main(int argc, char *argv[])
637 {
638  int rc = 0;
639  int checkInterval;
640  int should_match_rev = 1;
641  int init_no_compat_check = 0;
642  int init_only_if_full_compat = 0;
643  enum outFormat
644  {
645  text,
646  json,
647  json1,
648  json2
649  } printFormat;
650  ni_logan_device_pool_t *p_device_pool = NULL;
651  ni_logan_device_queue_t *coders = NULL;
652  ni_logan_device_context_t *p_device_context = NULL;
653  ni_logan_session_context_t xCtxt = { 0 };
654  ni_log_level_t loglevel = NI_LOG_INFO;
655  time_t startTime = { 0 }, now = { 0 };
656  int timeout_seconds = 0;
657  struct tm *ltime = NULL;
658  char buf[64] = { 0 };
659  long long time_diff_hours, time_diff_minutes, time_diff_seconds;
660  int opt;
661  printFormat = text;
662  checkInterval = 0;
663  int refresh = 1;
664  bool fw_log_dump = false;
665  int devid = -1;
666 
667 #ifdef _WIN32
668  SetConsoleCtrlHandler(console_ctrl_handler, TRUE);
669 #elif defined(__linux__)
670  setup_signal_handler();
671 #endif
672 
673  // arg handling
674  while ((opt = getopt(argc, argv, "hvrcn:o:t:D:k:l:i")) != -1)
675  {
676  switch (opt)
677  {
678  case 'o':
679  // Output print format
680  if (!strcmp(optarg, "json"))
681  {
682  printFormat = json;
683  }
684  else if (!strcmp(optarg, "text"))
685  {
686  printFormat = text;
687  }
688  else if (!strcmp(optarg, "json1"))
689  {
690  printFormat = json1;
691  }
692  else if (!strcmp(optarg, "json2"))
693  {
694  printFormat = json2;
695  }
696  else
697  {
698  fprintf(stderr, "Error: unknown selection for outputFormat: %s\n", optarg);
699  return 1;
700  }
701  break;
702  case 'n':
703  // Output interval
704  checkInterval = atoi(optarg);
705  break;
706  case 'r':
707  init_no_compat_check = 1;
708  break;
709  case 'c':
710  init_only_if_full_compat = 1;
711  break;
712  case 't':
713  timeout_seconds = atoi(optarg);
714  printf("Timeout will be set %d\n", timeout_seconds);
715  break;
716  case 'D':
717  fw_log_dump = atoi(optarg);
718  break;
719  case 'k':
720  devid = atoi(optarg);
721  break;
722  case 'l':
723  if (!strcmp(optarg, "none")) {
724  loglevel = NI_LOG_NONE;
725  } else if (!strcmp(optarg, "fatal")) {
726  loglevel = NI_LOG_FATAL;
727  } else if (!strcmp(optarg, "error")) {
728  loglevel = NI_LOG_ERROR;
729  } else if (!strcmp(optarg, "info")) {
730  loglevel = NI_LOG_INFO;
731  } else if (!strcmp(optarg, "debug")) {
732  loglevel = NI_LOG_DEBUG;
733  } else if (!strcmp(optarg, "trace")) {
734  loglevel = NI_LOG_TRACE;
735  } else {
736  fprintf(stderr, "unknown log level selected: %s", optarg);
737  return 1;
738  }
739  ni_log_set_level(loglevel);
740  break;
741  case 'i':
742  refresh = 0;
743  break;
744  case 'v':
745  printf("%s\n", NI_LOGAN_XCODER_REVISION);
746  return 0;
747  case 'h':
748  // help message
749  printf("-------- ni_rsrc_mon_logan v%s --------\n"
750  "The ni_rsrc_mon_logan program provides a real-time view of NETINT Logan T4XX \n"
751  "resources running on the system.\n"
752  "return 0 on success\n"
753  "return 1 on failure\n"
754  "Usage: sudo ni_rsrc_mon_logan [OPTIONS]\n"
755  "-o Output print format: text|json||json2\n"
756  "-n Specify reporting interval in one second interval.\n"
757  " If 0 or no selection, report only once.\n Default: 0\n"
758  "-r Init transcoder card resource regardless firmware release \n"
759  " version to libxcoder_logan version compatibility.\n"
760  " Default: only init cards with compatible firmware version.\n"
761  "-c Only init if all cards are fully compatible. Default is to init as many \n"
762  " fully and partially cards as possible."
763  "-t Set timeout time in seconds for device polling. Program will \n"
764  " exit with failure if timeout is reached without finding at \n"
765  " least one device. If 0 or no selection, poll indefinitely \n"
766  " until a T4XX device is found.\n"
767  " Default: 0\n"
768  "-D Dump firmware logs to current directory. Default: 0(not dump fw log).\n"
769  "-k Specify to dump which card's firmware logs.\n"
770  " Default: -1(dump fw log of all cards).\n"
771  "-l Set loglevel of libxcoder_logan API.\n"
772  " [none, fatal, error, info, debug, trace]\n"
773  " Default: info\n"
774  "-v Show libxcoder_logan version.\n"
775  "-i Do not refresh the devices list.\n"
776  "-h Open this help message.\n"
777  "\n"
778  "Reporting columns\n"
779  "BEST flag showing card of lowest realtime load and to be selected for \n"
780  " next auto allocated job\n"
781  "INDEX index number used by resource manager to identify the resource\n"
782  "LOAD realtime load\n"
783  "MODEL_LOAD estimated load based on framerate and resolution\n"
784  "INST number of job instances\n"
785  "DEVICE path to NVMe device file handle\n"
786  "NAMESPACE path to NVMe namespace file handle\n", NI_LOGAN_XCODER_REVISION);
787  return 0;
788  case '?':
789 #ifdef _WIN32
790  fprintf(stderr, "Option -o, -n, or -l require an argument, use option -h for help, "
791  "all other options are not supported.\n");
792  return 1;
793 #elif defined(__linux__)
794  if ((optopt == 'o') || (optopt == 'n') || (optopt == 'l'))
795  {
796  fprintf(stderr, "Option -%c requires an argument.\n", optopt);
797  return 1;
798  }
799  else if (isprint(optopt))
800  {
801  fprintf(stderr, "Unknown option `-%c'.\n", optopt);
802  return 1;
803  }
804  else
805  {
806  fprintf(stderr, "Unknown option character `\\x%x'.\n", optopt);
807  return 1;
808  }
809 #endif
810  break;
811  default:
812  fprintf(stderr, "ABORTING\n");
813  abort();
814  }
815  }
816 
817  if (init_no_compat_check && init_only_if_full_compat)
818  {
819  fprintf(stderr, "Error: -r option cannot be used with -c option\n");
820  return 1;
821  }
822  if (init_no_compat_check)
823  {
824  should_match_rev = 0;
825  }
826  else if (init_only_if_full_compat)
827  {
828  should_match_rev = 2;
829  }
830 
831  if ((argc <= 2) && (optind == 1))
832  {
833  for (; optind < argc; optind++)
834  {
835  checkInterval = argToI(argv[optind]);
836  }
837  }
838 
839 #ifdef __ANDROID__
840  ni_log_set_log_tag(LOG_TAG);
841 #endif
842 
843  if (ni_logan_rsrc_init(should_match_rev,timeout_seconds) < 0)
844  {
845  fprintf(stderr, "Error access NI resource, quit ..\n");
846  return 1;
847  }
848 
849  p_device_pool = ni_logan_rsrc_get_device_pool();
850  if (!p_device_pool)
851  {
852  fprintf(stderr, "Error get Coders info ..\n");
853  return 1;
854  }
855 
857 
858  if (loglevel >= NI_LOG_INFO)
859  {
860  printf("**************************************************\n");
861  }
862 
863  startTime = time(NULL);
865  {
866  now = time(NULL);
867  ltime = localtime(&now);
868  if (ltime)
869  {
870  strftime(buf, sizeof(buf), "%c", ltime);
871  }
872  time_diff_seconds = (long long)difftime(now, startTime);
873  time_diff_minutes = time_diff_seconds / 60;
874  time_diff_hours = time_diff_minutes / 60;
875 
876  if (refresh)
877  {
878  if (NI_LOGAN_RETCODE_SUCCESS != ni_logan_rsrc_refresh(should_match_rev))
879  {
880  printf("Error: resource pool records might be corrupted!!\n");
881  return 1;
882  }
883  }
884 
885  if (loglevel >= NI_LOG_INFO)
886  {
887  printf("%s up %02lld" ":%02lld" ":%02lld" " v%s\n", buf, time_diff_hours, time_diff_minutes % 60, time_diff_seconds % 60,
889  }
890 
893 #ifdef _WIN32
894  if (WAIT_ABANDONED == WaitForSingleObject(p_device_pool->lock, INFINITE)) // no time-out interval)
895  {
896  fprintf(stderr, "ERROR: Failed to obtain mutex: %p\n", p_device_pool->lock);
897  return 1;
898  }
899 #elif defined(__linux__)
900  if ( flock(p_device_pool->lock, LOCK_EX) )
901  {
902  fprintf(stderr, "Error flock() failed\n");
903  }
904 #endif
905 
906  coders = p_device_pool->p_device_queue;
907 
908 #ifdef _WIN32
909  ReleaseMutex((HANDLE)p_device_pool->lock);
910 #elif defined(__linux__)
911  if ( flock(p_device_pool->lock, LOCK_UN) )
912  {
913  fprintf(stderr, "Error flock() failed\n");
914  }
915 #endif
916 
917  print_perf(NI_LOGAN_DEVICE_TYPE_DECODER, coders, &xCtxt, printFormat);
918  print_perf(NI_LOGAN_DEVICE_TYPE_ENCODER, coders, &xCtxt, printFormat);
919 
920  if (loglevel >= NI_LOG_INFO)
921  {
922  printf("**************************************************\n");
923  }
924 
925  fflush(stderr);
926 
927  if (checkInterval == 0)
928  {
929  // run once
930  break;
931  }
932  ni_logan_usleep((int64_t)checkInterval * 1000 * 1000);
933  }
934 
935  if (fw_log_dump)
936  {
937  // dump fw log
938 #ifdef _WIN32
939  if (WAIT_ABANDONED == WaitForSingleObject(p_device_pool->lock, INFINITE)) // no time-out interval)
940  {
941  fprintf(stderr, "ERROR: Failed to obtain mutex: %p\n", p_device_pool->lock);
942  }
943 #elif __linux__
944  if ( lockf(p_device_pool->lock, F_LOCK, 0) )
945  {
946  perror("ERROR: cannot lock p_device_pool");
947  }
948 #endif
949  coders = p_device_pool->p_device_queue;
950 #ifdef _WIN32
951  ReleaseMutex((HANDLE)p_device_pool->lock);
952 #elif __linux__
953  if ( lockf(p_device_pool->lock, F_ULOCK, 0) )
954  {
955  perror("ERROR: cannot unlock p_device_pool");
956  }
957 #endif
958  dump_fw_log(coders, &xCtxt, devid);
959  }
960 
962  ni_logan_rsrc_free_device_pool(p_device_pool);
963 #ifdef __ANDROID__
964  system("chmod -R 777 /dev/shm_netint/");
965  system("chmod 777 /dev/block/nvme* 2>/dev/null");
966  system("chmod 777 /dev/nvme* 2>/dev/null");
967  property_set("ni_rsrc_init_logan_completed", "yes");
968 #endif
969 
970  return 0;
971 }
Common NETINT definitions used by all modules.
ni_logan_retcode_t
@ NI_LOGAN_RETCODE_SUCCESS
#define END
#define NI_LOGAN_XCODER_REVISION
Definition: ni_defs_logan.h:62
#define NI_ERRNO
ni_logan_device_type_t
@ NI_LOGAN_DEVICE_TYPE_ENCODER
@ NI_LOGAN_DEVICE_TYPE_DECODER
#define LRETURN
ni_device_handle_t ni_logan_device_open(const char *p_dev, uint32_t *p_max_io_size_out)
Opens device and returnes device device_handle if successful.
ni_logan_retcode_t ni_logan_device_session_query(ni_logan_session_context_t *p_ctx, ni_logan_device_type_t device_type)
Query session data from the device - Currently not implemented If device_type is NI_LOGAN_DEVICE_TYPE...
void ni_logan_device_session_context_init(ni_logan_session_context_t *p_ctx)
Initialize already allocated session context to a known state.
void ni_logan_close_event(ni_event_handle_t event_handle)
Closes event and releases resources.
#define atoi(p_str)
void ni_logan_device_session_context_clear(ni_logan_session_context_t *p_ctx)
Clear already allocated session context to all zeros.
ni_logan_retcode_t ni_logan_alloc_and_get_fw_logs(ni_logan_session_context_t *p_ctx, void **p_log_buffer, bool gen_log_file)
Allocate log buffer if needed and retrieve firmware logs from device.
ni_event_handle_t ni_logan_create_event(void)
Create event and returnes event handle if successful.
void ni_logan_device_close(ni_device_handle_t device_handle)
Closes device and releases resources.
Main NETINT device API header file provides the ability to communicate with NI T-408 type hardware tr...
int getopt(int argc, char *argv[], const char *optstring)
int optopt
int optind
char * optarg
void ni_log_set_level(ni_log_level_t level)
Set ni_log_level.
Definition: ni_log_logan.c:138
ni_log_level_t
Definition: ni_log_logan.h:60
@ NI_LOG_NONE
Definition: ni_log_logan.h:62
@ NI_LOG_DEBUG
Definition: ni_log_logan.h:66
@ NI_LOG_TRACE
Definition: ni_log_logan.h:67
@ NI_LOG_FATAL
Definition: ni_log_logan.h:63
@ NI_LOG_ERROR
Definition: ni_log_logan.h:64
@ NI_LOG_INFO
Definition: ni_log_logan.h:65
#define LOG_TAG
ni_logan_device_context_t * ni_logan_rsrc_get_device_context(ni_logan_device_type_t device_type, int guid)
Allocates and returns a pointer to ni_logan_device_context_t struct based on provided device_type and...
void ni_logan_rsrc_free_device_pool(ni_logan_device_pool_t *p_device_pool)
Free all resources taken by the device pool.
void ni_logan_rsrc_free_device_context(ni_logan_device_context_t *p_device_context)
Free previously allocated device context.
int ni_logan_rsrc_init(int should_match_rev, int timeout_seconds)
Initialize and create all resources required to work with NETINT NVMe transcoder devices....
ni_logan_retcode_t ni_logan_rsrc_refresh(int should_match_rev)
Scan and refresh all resources on the host, taking into account hot-plugged and pulled out cards.
ni_logan_device_pool_t * ni_logan_rsrc_get_device_pool(void)
Create and return the allocated ni_logan_device_pool_t struct.
Exported definitions related to resource management of NI T-408 devices.
int main(int argc, char *argv[])
int compareInt32_t(const void *a, const void *b)
compare two int32_t for qsort
void dump_fw_log(ni_logan_device_queue_t *coders, ni_logan_session_context_t *sessionCtxt, int devid)
int argToI(char *numArray)
convert number from argv input to integer if safe
void print_perf(ni_logan_device_type_t module_type, ni_logan_device_queue_t *coders, ni_logan_session_context_t *sessionCtxt, int outformattype)
print performance data for either decoder or encoder
unsigned int get_modules(ni_logan_device_type_t module_type, ni_logan_device_queue_t *coders, char *module_name, int32_t **module_ids, int32_t *best_load_module_id)
bool open_and_get_log(ni_logan_device_context_t *p_device_context, ni_logan_session_context_t *p_session_context, void **p_log_buffer, bool gen_log_file)
uint32_t g_logan_xcoder_stop_process
Private definitions related to resource management of NI T-408 devices.
void ni_logan_usleep(int64_t usec)
Exported utility routines definition.
ni_logan_device_info_t * p_device_info
char dev_name[NI_LOGAN_MAX_DEVICE_NAME_LEN]
char blk_name[NI_LOGAN_MAX_DEVICE_NAME_LEN]
ni_logan_device_queue_t * p_device_queue
int32_t decoders[LOGAN_MAX_DEVICE_CNT]
int32_t encoders[LOGAN_MAX_DEVICE_CNT]
ni_logan_load_query_t load_query
ni_device_handle_t device_handle
ni_device_handle_t blk_io_handle