corosync-fplay.c 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585
  1. #include <config.h>
  2. #include <sys/types.h>
  3. #include <sys/stat.h>
  4. #include <fcntl.h>
  5. #include <stdio.h>
  6. #include <unistd.h>
  7. #include <string.h>
  8. #include <stdlib.h>
  9. #include <stdint.h>
  10. #include <errno.h>
  11. #include <sys/socket.h>
  12. #include <netinet/in.h>
  13. #include <sys/types.h>
  14. #include <sys/socket.h>
  15. #include <arpa/inet.h>
  16. #include <corosync/engine/logsys.h>
  17. uint32_t flt_data_size;
  18. uint32_t old_format_file;
  19. uint32_t *flt_data;
  20. #define FDHEAD_INDEX (flt_data_size)
  21. #define FDTAIL_INDEX (flt_data_size + 1)
  22. #define TOTEMIP_ADDRLEN (sizeof(struct in6_addr))
  23. struct totem_ip_address {
  24. unsigned int nodeid;
  25. unsigned short family;
  26. unsigned char addr[TOTEMIP_ADDRLEN];
  27. } __attribute__((packed));
  28. struct memb_ring_id {
  29. struct totem_ip_address rep;
  30. unsigned long long seq;
  31. } __attribute__((packed));
  32. static const char *totemip_print(const struct totem_ip_address *addr)
  33. {
  34. static char buf[INET6_ADDRSTRLEN];
  35. return inet_ntop(addr->family, addr->addr, buf, sizeof(buf));
  36. }
  37. static char *print_string_len (const unsigned char *str, unsigned int len)
  38. {
  39. unsigned int i;
  40. static char buf[1024];
  41. memset (buf, 0, sizeof (buf));
  42. for (i = 0; i < len; i++) {
  43. buf[i] = str[i];
  44. }
  45. return (buf);
  46. }
  47. static void sync_printer_confchg_set_sync (const void **record)
  48. {
  49. const unsigned int *my_should_sync = record[0];
  50. printf ("Setting my_should_sync to %d\n", *my_should_sync);
  51. }
  52. static void sync_printer_set_sync_state (const void **record)
  53. {
  54. const unsigned int *my_sync_state = record[0];
  55. printf ("Setting my_sync_state to %d\n", *my_sync_state);
  56. }
  57. static void sync_printer_process_currentstate (const void **record)
  58. {
  59. const unsigned int *my_sync_state = record[0];
  60. printf ("Retrieving my_sync_state %d\n", *my_sync_state);
  61. }
  62. static void sync_printer_process_get_shouldsync (const void **record)
  63. {
  64. const unsigned int *my_should_sync = record[0];
  65. printf ("Getting my_should_sync %d\n", *my_should_sync);
  66. }
  67. static void sync_printer_checkpoint_release (const void **record)
  68. {
  69. const unsigned char *name = record[0];
  70. const uint16_t *name_len = record[1];
  71. const unsigned int *ckpt_id = record[2];
  72. const unsigned int *from = record[3];
  73. printf ("Checkpoint release name=[%s] id=[%d] from=[%d] len=[%d]\n",
  74. print_string_len (name, *name_len),
  75. *ckpt_id,
  76. *from,
  77. *name_len);
  78. }
  79. static void sync_printer_checkpoint_transmit (const void **record)
  80. {
  81. const unsigned char *name = record[0];
  82. const uint16_t *name_len = record[1];
  83. const unsigned int *ckpt_id = record[2];
  84. const unsigned int *xmit_id = record[3];
  85. printf ("xmit_id=[%d] Checkpoint transmit name=[%s] id=[%d]\n",
  86. *xmit_id, print_string_len (name, *name_len),
  87. *ckpt_id);
  88. }
  89. static void sync_printer_section_transmit (const void **record)
  90. {
  91. const unsigned char *ckpt_name = record[0];
  92. const uint16_t *name_len = record[1];
  93. const unsigned int *ckpt_id = record[2];
  94. const unsigned int *xmit_id = record[3];
  95. const unsigned char *section_name = record[4];
  96. const uint16_t *section_name_len = record[5];
  97. printf ("xmit_id=[%d] Section transmit checkpoint name=[%s] id=[%d] ",
  98. *xmit_id, print_string_len (ckpt_name, *name_len),
  99. *ckpt_id);
  100. printf ("section=[%s]\n",
  101. print_string_len (section_name, *section_name_len));
  102. }
  103. static void sync_printer_checkpoint_receive (const void **record)
  104. {
  105. const unsigned char *ckpt_name = record[0];
  106. const uint16_t *name_len = record[1];
  107. const unsigned int *ckpt_id = record[2];
  108. const unsigned int *xmit_id = record[3];
  109. printf ("xmit_id=[%d] Checkpoint receive checkpoint name=[%s] id=[%d]\n",
  110. *xmit_id, print_string_len (ckpt_name, *name_len), *ckpt_id);
  111. }
  112. static void sync_printer_section_receive (const void **record)
  113. {
  114. const unsigned char *ckpt_name = record[0];
  115. const uint16_t *name_len = record[1];
  116. const unsigned int *ckpt_id = record[2];
  117. const unsigned int *xmit_id = record[3];
  118. const unsigned char *section_name = record[4];
  119. const unsigned int *section_name_len = record[5];
  120. printf ("xmit_id=[%d] Section receive checkpoint name=[%s] id=[%d] ",
  121. *xmit_id, print_string_len (ckpt_name, *name_len),
  122. *ckpt_id);
  123. printf ("section=[%s]\n",
  124. print_string_len (section_name, *section_name_len));
  125. }
  126. static void sync_printer_confchg_fn (const void **record)
  127. {
  128. unsigned int i;
  129. const unsigned int *members = record[0];
  130. const unsigned int *member_count = record[1];
  131. const struct memb_ring_id *ring_id = record[2];
  132. struct in_addr addr;
  133. printf ("sync confchg fn ringid [ip=%s seq=%lld]\n",
  134. totemip_print (&ring_id->rep),
  135. ring_id->seq);
  136. printf ("members [%d]:\n", *member_count);
  137. for (i = 0; i < *member_count; i++) {
  138. addr.s_addr = members[i];
  139. printf ("\tmember [%s]\n", inet_ntoa (addr));
  140. }
  141. }
  142. static void printer_totemsrp_mcast (const void **record)
  143. {
  144. const unsigned int *msgid = record[0];
  145. printf ("totemsrp_mcast %d\n", *msgid);
  146. }
  147. static void printer_totemsrp_delv (const void **record)
  148. {
  149. const unsigned int *msgid = record[0];
  150. printf ("totemsrp_delv %d\n", *msgid);
  151. }
  152. static void printer_totempg_mcast_fits (const void **record)
  153. {
  154. const unsigned int *idx = record[0];
  155. const unsigned int *iov_len = record[1];
  156. const unsigned int *copy_len = record[2];
  157. const unsigned int *fragment_size = record[3];
  158. const unsigned int *max_packet_size = record[4];
  159. const unsigned int *copy_base = record[5];
  160. const unsigned char *next_fragment = record[6];
  161. printf ("totempg_mcast index=[%d] iov_len=[%d] copy_len=[%d] fragment_size=[%d] max_packet_size=[%d] copy_base=[%d] next_fragment[%d]\n",
  162. *idx, *iov_len, *copy_len, *fragment_size, *max_packet_size, *copy_base, *next_fragment);
  163. }
  164. static void sync_printer_service_process (const void **record)
  165. {
  166. const struct memb_ring_id *ring_id = record[0];
  167. const struct memb_ring_id *sync_ring_id = record[1];
  168. printf ("sync service process callback ringid [ip=%s seq=%lld] ",
  169. totemip_print (&ring_id->rep),
  170. ring_id->seq);
  171. printf ("sync ringid [ip=%s seq=%lld]\n",
  172. totemip_print (&sync_ring_id->rep),
  173. sync_ring_id->seq);
  174. }
  175. struct printer_subsys_record_print {
  176. int ident;
  177. void (*print_fn)(const void **record);
  178. int record_length;
  179. };
  180. struct printer_subsys {
  181. const char *subsys;
  182. struct printer_subsys_record_print *record_printers;
  183. int record_printers_count;
  184. };
  185. #define LOGREC_ID_SYNC_CONFCHG_FN 0
  186. #define LOGREC_ID_SYNC_SERVICE_PROCESS 1
  187. /*
  188. * CKPT subsystem
  189. */
  190. #define LOGREC_ID_CONFCHG_SETSYNC 0
  191. #define LOGREC_ID_SETSYNCSTATE 1
  192. #define LOGREC_ID_SYNC_PROCESS_CURRENTSTATE 2
  193. #define LOGREC_ID_SYNC_PROCESS_GETSHOULDSYNC 3
  194. #define LOGREC_ID_SYNC_CHECKPOINT_TRANSMIT 4
  195. #define LOGREC_ID_SYNC_SECTION_TRANSMIT 5
  196. #define LOGREC_ID_SYNC_CHECKPOINT_RECEIVE 6
  197. #define LOGREC_ID_SYNC_SECTION_RECEIVE 7
  198. #define LOGREC_ID_SYNC_CHECKPOINT_RELEASE 8
  199. #define LOGREC_ID_TOTEMSRP_MCAST 0
  200. #define LOGREC_ID_TOTEMSRP_DELV 1
  201. #define LOGREC_ID_TOTEMPG_MCAST_FITS 2
  202. static struct printer_subsys_record_print record_print_sync[] = {
  203. {
  204. .ident = LOGREC_ID_SYNC_CONFCHG_FN,
  205. .print_fn = sync_printer_confchg_fn,
  206. .record_length = 28
  207. },
  208. {
  209. .ident = LOGREC_ID_SYNC_SERVICE_PROCESS,
  210. .print_fn = sync_printer_service_process,
  211. .record_length = 28
  212. }
  213. };
  214. static struct printer_subsys_record_print record_print_ckpt[] = {
  215. {
  216. .ident = LOGREC_ID_CONFCHG_SETSYNC,
  217. .print_fn = sync_printer_confchg_set_sync,
  218. .record_length = 28
  219. },
  220. {
  221. .ident = LOGREC_ID_SETSYNCSTATE,
  222. .print_fn = sync_printer_set_sync_state,
  223. .record_length = 28
  224. },
  225. {
  226. .ident = LOGREC_ID_SYNC_PROCESS_CURRENTSTATE,
  227. .print_fn = sync_printer_process_currentstate,
  228. .record_length = 28
  229. },
  230. {
  231. .ident = LOGREC_ID_SYNC_PROCESS_GETSHOULDSYNC,
  232. .print_fn = sync_printer_process_get_shouldsync,
  233. .record_length = 28
  234. },
  235. {
  236. .ident = LOGREC_ID_SYNC_CHECKPOINT_TRANSMIT,
  237. .print_fn = sync_printer_checkpoint_transmit,
  238. .record_length = 28
  239. },
  240. {
  241. .ident = LOGREC_ID_SYNC_SECTION_TRANSMIT,
  242. .print_fn = sync_printer_section_transmit,
  243. .record_length = 28
  244. },
  245. {
  246. .ident = LOGREC_ID_SYNC_CHECKPOINT_RECEIVE,
  247. .print_fn = sync_printer_checkpoint_receive,
  248. .record_length = 28
  249. },
  250. {
  251. .ident = LOGREC_ID_SYNC_SECTION_RECEIVE,
  252. .print_fn = sync_printer_section_receive,
  253. .record_length = 28
  254. },
  255. {
  256. .ident = LOGREC_ID_SYNC_CHECKPOINT_RELEASE,
  257. .print_fn = sync_printer_checkpoint_release,
  258. .record_length = 28
  259. }
  260. };
  261. static struct printer_subsys_record_print record_print_totem[] = {
  262. {
  263. .ident = LOGREC_ID_TOTEMSRP_MCAST,
  264. .print_fn = printer_totemsrp_mcast,
  265. .record_length = 28
  266. },
  267. {
  268. .ident = LOGREC_ID_TOTEMSRP_DELV,
  269. .print_fn = printer_totemsrp_delv,
  270. .record_length = 28
  271. },
  272. {
  273. .ident = LOGREC_ID_TOTEMPG_MCAST_FITS,
  274. .print_fn = printer_totempg_mcast_fits,
  275. .record_length = 28
  276. }
  277. };
  278. static struct printer_subsys printer_subsystems[] = {
  279. {
  280. .subsys = "SYNC",
  281. .record_printers = record_print_sync,
  282. .record_printers_count = sizeof (record_print_sync) / sizeof (struct printer_subsys_record_print)
  283. },
  284. {
  285. .subsys = "CKPT",
  286. .record_printers = record_print_ckpt,
  287. .record_printers_count = sizeof (record_print_ckpt) / sizeof (struct printer_subsys_record_print)
  288. },
  289. {
  290. .subsys = "TOTEM",
  291. .record_printers = record_print_totem,
  292. .record_printers_count = sizeof (record_print_totem) / sizeof (struct printer_subsys_record_print)
  293. }
  294. };
  295. static unsigned int printer_subsys_count =
  296. sizeof (printer_subsystems) / sizeof (struct printer_subsys);
  297. #define G_RECORD_SIZE 10000
  298. /*
  299. * Record must have at least 4 bytes - size, indent, line and record_number
  300. */
  301. #define MINIMUM_RECORD_SIZE 4
  302. static uint32_t g_record[G_RECORD_SIZE];
  303. static int file_rewind = 0;
  304. /*
  305. * Copy record, dealing with wrapping
  306. */
  307. static int logsys_rec_get (int rec_idx) {
  308. uint32_t rec_size;
  309. int firstcopy, secondcopy;
  310. if (rec_idx >= flt_data_size) {
  311. fprintf (stderr, "rec_idx too large. Input file is probably corrupted.\n");
  312. exit (EXIT_FAILURE);
  313. }
  314. rec_size = flt_data[rec_idx];
  315. firstcopy = rec_size;
  316. secondcopy = 0;
  317. if (rec_size > G_RECORD_SIZE || rec_size > flt_data_size) {
  318. fprintf (stderr, "rec_size too large. Input file is probably corrupted.\n");
  319. exit (EXIT_FAILURE);
  320. }
  321. if (rec_size < MINIMUM_RECORD_SIZE) {
  322. fprintf (stderr, "rec_size too small. Input file is probably corrupted.\n");
  323. exit (EXIT_FAILURE);
  324. }
  325. if (firstcopy + rec_idx > flt_data_size) {
  326. if (file_rewind) {
  327. fprintf (stderr, "file rewind for second time (cycle). Input file is probably corrupted.\n");
  328. exit (EXIT_FAILURE);
  329. }
  330. file_rewind = 1;
  331. firstcopy = flt_data_size - rec_idx;
  332. secondcopy -= firstcopy - rec_size;
  333. }
  334. memcpy (&g_record[0], &flt_data[rec_idx], firstcopy * sizeof(uint32_t));
  335. if (secondcopy) {
  336. memcpy (&g_record[firstcopy], &flt_data[0], secondcopy * sizeof(uint32_t));
  337. }
  338. return ((rec_idx + rec_size) % flt_data_size);
  339. }
  340. static void logsys_rec_print (const void *record)
  341. {
  342. const uint32_t *buf_uint32t = record;
  343. uint32_t rec_size;
  344. uint32_t rec_ident;
  345. uint32_t level;
  346. uint32_t line;
  347. uint32_t arg_size_idx;
  348. unsigned int i;
  349. unsigned int j;
  350. unsigned int rec_idx = 0;
  351. uint32_t record_number;
  352. unsigned int words_processed;
  353. unsigned int found;
  354. const char *arguments[64];
  355. time_t timestamp;
  356. struct tm timestamp_tm;
  357. int arg_count = 0;
  358. char ts_buf[132];
  359. rec_size = buf_uint32t[rec_idx++];
  360. rec_ident = buf_uint32t[rec_idx++];
  361. line = buf_uint32t[rec_idx++];
  362. record_number = buf_uint32t[rec_idx++];
  363. if (!old_format_file) {
  364. timestamp = (time_t)(buf_uint32t[rec_idx] | (time_t)(buf_uint32t[rec_idx+1])<<32);
  365. rec_idx += 2;
  366. }
  367. level = LOGSYS_DECODE_LEVEL(rec_ident);
  368. printf ("rec=[%d] ", record_number);
  369. if (!old_format_file) {
  370. localtime_r(&timestamp, &timestamp_tm);
  371. strftime(ts_buf, sizeof(ts_buf), "%F %T", &timestamp_tm);
  372. printf ("time=[%s] ", ts_buf);
  373. }
  374. arg_size_idx = rec_idx;
  375. words_processed = 4;
  376. for (i = 0; words_processed < rec_size; i++) {
  377. arguments[arg_count++] =
  378. (const char *)&buf_uint32t[arg_size_idx + 1];
  379. words_processed += buf_uint32t[arg_size_idx] + 1;
  380. arg_size_idx += buf_uint32t[arg_size_idx] + 1;
  381. }
  382. found = 0;
  383. for (i = 0; i < printer_subsys_count; i++) {
  384. if (strcmp (arguments[0], printer_subsystems[i].subsys) == 0) {
  385. for (j = 0; j < printer_subsystems[i].record_printers_count; j++) {
  386. if (rec_ident == printer_subsystems[i].record_printers[j].ident) {
  387. printer_subsystems[i].record_printers[j].print_fn ((const void **)&arguments[3]);
  388. return;
  389. }
  390. }
  391. }
  392. }
  393. switch(LOGSYS_DECODE_RECID(rec_ident)) {
  394. case LOGSYS_RECID_LOG:
  395. printf ("Log Message=%s\n", arguments[3]);
  396. break;
  397. case LOGSYS_RECID_ENTER:
  398. printf ("ENTERING function [%s] line [%d]\n", arguments[2], line);
  399. break;
  400. case LOGSYS_RECID_LEAVE:
  401. printf ("LEAVING function [%s] line [%d]\n", arguments[2], line);
  402. break;
  403. case LOGSYS_RECID_TRACE1:
  404. printf ("Tracing(1) Messsage=%s\n", arguments[3]);
  405. break;
  406. case LOGSYS_RECID_TRACE2:
  407. printf ("Tracing(2) Messsage=%s\n", arguments[3]);
  408. break;
  409. case LOGSYS_RECID_TRACE3:
  410. printf ("Tracing(3) Messsage=%s\n", arguments[3]);
  411. break;
  412. case LOGSYS_RECID_TRACE4:
  413. printf ("Tracing(4) Messsage=%s\n", arguments[3]);
  414. break;
  415. case LOGSYS_RECID_TRACE5:
  416. printf ("Tracing(5) Messsage=%s\n", arguments[3]);
  417. break;
  418. case LOGSYS_RECID_TRACE6:
  419. printf ("Tracing(6) Messsage=%s\n", arguments[3]);
  420. break;
  421. case LOGSYS_RECID_TRACE7:
  422. printf ("Tracing(7) Messsage=%s\n", arguments[3]);
  423. break;
  424. case LOGSYS_RECID_TRACE8:
  425. printf ("Tracing(8) Messsage=%s\n", arguments[3]);
  426. break;
  427. default:
  428. printf ("Unknown record type found subsys=[%s] ident=[%d]\n",
  429. arguments[0], LOGSYS_DECODE_RECID(rec_ident));
  430. break;
  431. }
  432. #ifdef COMPILE_OUT
  433. printf ("\n");
  434. #endif
  435. }
  436. int main (void)
  437. {
  438. int fd;
  439. int rec_idx;
  440. int end_rec;
  441. int record_count = 1;
  442. ssize_t n_read;
  443. const char *data_file = LOCALSTATEDIR "/lib/corosync/fdata";
  444. size_t n_required;
  445. uint32_t flt_magic;
  446. if ((fd = open (data_file, O_RDONLY)) < 0) {
  447. fprintf (stderr, "failed to open %s: %s\n",
  448. data_file, strerror (errno));
  449. return EXIT_FAILURE;
  450. }
  451. n_required = sizeof (uint32_t);
  452. n_read = read (fd, &flt_magic, n_required);
  453. if (n_read != n_required) {
  454. fprintf (stderr, "Unable to read fdata magic number\n");
  455. return EXIT_FAILURE;
  456. }
  457. /* If the first word is a magic number then this is a new format
  458. * fdata file (with timestamps) and the next word is the length.
  459. * If not, then it's an old file and we just read the length, so use it
  460. */
  461. if (flt_magic == 0xFFFFDABB) {
  462. n_required = sizeof (uint32_t);
  463. n_read = read (fd, &flt_data_size, n_required);
  464. if (n_read != n_required) {
  465. fprintf (stderr, "Unable to read fdata header\n");
  466. return EXIT_FAILURE;
  467. }
  468. old_format_file = 0;
  469. }
  470. else {
  471. flt_data_size = flt_magic;
  472. old_format_file = 1;
  473. }
  474. n_required = ((flt_data_size + 2) * sizeof(uint32_t));
  475. if ((flt_data = malloc (n_required)) == NULL) {
  476. fprintf (stderr, "exhausted virtual memory\n");
  477. return EXIT_FAILURE;
  478. }
  479. n_read = read (fd, flt_data, n_required);
  480. close (fd);
  481. if (n_read < 0) {
  482. fprintf (stderr, "reading %s failed: %s\n",
  483. data_file, strerror (errno));
  484. return EXIT_FAILURE;
  485. }
  486. if (n_read != n_required) {
  487. printf ("Warning: read %zd bytes, but expected %zu\n",
  488. n_read, n_required);
  489. }
  490. rec_idx = flt_data[FDTAIL_INDEX];
  491. end_rec = flt_data[FDHEAD_INDEX];
  492. printf ("Starting replay: head [%d] tail [%d]\n",
  493. flt_data[FDHEAD_INDEX],
  494. flt_data[FDTAIL_INDEX]);
  495. for (;;) {
  496. rec_idx = logsys_rec_get (rec_idx);
  497. logsys_rec_print (g_record);
  498. if (rec_idx == end_rec) {
  499. break;
  500. }
  501. record_count += 1;
  502. }
  503. printf ("Finishing replay: records found [%d]\n", record_count);
  504. return (0);
  505. }