1 /*
2    Copyright (c) 2005, 2019, Oracle and/or its affiliates. All rights reserved.
3 
4    This program is free software; you can redistribute it and/or modify
5    it under the terms of the GNU General Public License, version 2.0,
6    as published by the Free Software Foundation.
7 
8    This program is also distributed with certain software (including
9    but not limited to OpenSSL) that is licensed under separate terms,
10    as designated in a particular file or component or in included license
11    documentation.  The authors of MySQL hereby grant you an additional
12    permission to link the program and your derivative works with the
13    separately licensed software that they have included with MySQL.
14 
15    This program is distributed in the hope that it will be useful,
16    but WITHOUT ANY WARRANTY; without even the implied warranty of
17    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18    GNU General Public License, version 2.0, for more details.
19 
20    You should have received a copy of the GNU General Public License
21    along with this program; if not, write to the Free Software
22    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301  USA
23 */
24 
25 #include <ndb_global.h>
26 #include <mgmapi.h>
27 #include <mgmapi_internal.h>
28 
29 #include <NdbOut.hpp>
30 #include <Properties.hpp>
31 #include <InputStream.hpp>
32 #include <NdbTick.h>
33 
34 #include <debugger/EventLogger.hpp>
35 #include <kernel/NodeBitmask.hpp>
36 
37 #include "ndb_logevent.hpp"
38 
39 extern
40 int ndb_mgm_listen_event_internal(NdbMgmHandle, const int filter[],
41                                   int, NDB_SOCKET_TYPE*);
42 
43 struct ndb_logevent_error_msg {
44   enum ndb_logevent_handle_error code;
45   const char *msg;
46 };
47 
48 struct ndb_logevent_error_msg ndb_logevent_error_messages[]= {
49   { NDB_LEH_READ_ERROR,              "Read error" },
50   { NDB_LEH_MISSING_EVENT_SPECIFIER, "Missing event specifier" },
51   { NDB_LEH_UNKNOWN_EVENT_VARIABLE,  "Unknown event variable" },
52   { NDB_LEH_UNKNOWN_EVENT_TYPE,      "Unknown event type" },
53   { NDB_LEH_INTERNAL_ERROR,          "Unknown internal error" },
54   { NDB_LEH_NO_ERROR,0}
55 };
56 
57 struct ndb_logevent_handle {
58   NDB_SOCKET_TYPE socket;
59   enum ndb_logevent_handle_error m_error;
60 };
61 
62 /*
63   Create a new NdbLogEventHandle for reading events from
64   the same socket as the NdbMgmHandle
65 */
66 
67 NdbLogEventHandle
ndb_mgm_create_logevent_handle_same_socket(NdbMgmHandle mh)68 ndb_mgm_create_logevent_handle_same_socket(NdbMgmHandle mh)
69 {
70   NdbLogEventHandle h=
71     (NdbLogEventHandle)malloc(sizeof(ndb_logevent_handle));
72   if (!h)
73     return NULL;
74 
75   h->socket= _ndb_mgm_get_socket(mh);
76 
77   return h;
78 }
79 
80 extern "C"
81 NdbLogEventHandle
ndb_mgm_create_logevent_handle(NdbMgmHandle mh,const int filter[])82 ndb_mgm_create_logevent_handle(NdbMgmHandle mh,
83 			       const int filter[])
84 {
85   NdbLogEventHandle h=
86     (NdbLogEventHandle)malloc(sizeof(ndb_logevent_handle));
87   if (!h)
88     return NULL;
89 
90   NDB_SOCKET_TYPE sock;
91   if(ndb_mgm_listen_event_internal(mh, filter, 1, &sock) < 0)
92   {
93     free(h);
94     return 0;
95   }
96 
97   h->socket= sock;
98 
99   return h;
100 }
101 
102 extern "C"
103 ndb_native_socket_t
ndb_logevent_get_fd(const NdbLogEventHandle h)104 ndb_logevent_get_fd(const NdbLogEventHandle h)
105 {
106   return ndb_socket_get_native(h->socket);
107 }
108 
109 extern "C"
ndb_mgm_destroy_logevent_handle(NdbLogEventHandle * h)110 void ndb_mgm_destroy_logevent_handle(NdbLogEventHandle * h)
111 {
112   if( !h )
113     return;
114 
115   if ( *h )
116     ndb_socket_close((*h)->socket);
117 
118   free(*h);
119   * h = 0;
120 }
121 
122 #define ROW(a,b,c,d) \
123 { NDB_LE_ ## a,  b, c, 0, offsetof(struct ndb_logevent, a.d), \
124   sizeof(((struct ndb_logevent *)0)->a.d) }
125 
126 #define ROW_FN(a,b,c,d,e) \
127 { NDB_LE_ ## a,  b, c, e, offsetof(struct ndb_logevent, a.d), \
128   sizeof(((struct ndb_logevent *)0)->a.d) }
129 
ref_to_node(int ref)130 static int ref_to_node(int ref){
131   return ref & 0xFFFF;
132 }
133 
134 struct Ndb_logevent_body_row ndb_logevent_body[]= {
135 
136   // Connection
137   ROW( Connected,           "node",          1, node),
138 
139   ROW( Disconnected,        "node",          1, node),
140 
141   ROW( CommunicationClosed, "node",          1, node),
142 
143   ROW( CommunicationOpened, "node",          1, node),
144 
145   ROW( ConnectedApiVersion, "node",          1, node),
146   ROW( ConnectedApiVersion, "version",       2, version),
147 
148       /* CHECKPOINT */
149 
150   ROW( GlobalCheckpointStarted, "gci", 1, gci),
151 
152   ROW( GlobalCheckpointCompleted, "gci", 1, gci),
153 
154   ROW( LocalCheckpointStarted, "lci",         1, lci),
155   ROW( LocalCheckpointStarted, "keep_gci",    2, keep_gci),
156   ROW( LocalCheckpointStarted, "restore_gci", 3, restore_gci),
157 
158   ROW( LocalCheckpointCompleted, "lci", 1, lci),
159 
160   ROW( LCPStoppedInCalcKeepGci, "data", 1, data),
161 
162   ROW( LCPFragmentCompleted, "node",        1, node),
163   ROW( LCPFragmentCompleted, "table_id",    2, table_id),
164   ROW( LCPFragmentCompleted, "fragment_id", 3, fragment_id),
165 
166   ROW( UndoLogBlocked, "acc_count", 1, acc_count),
167   ROW( UndoLogBlocked, "tup_count", 2, tup_count),
168 
169       /* STARTUP */
170   ROW( NDBStartStarted, "version", 1, version),
171 
172   ROW( NDBStartCompleted, "version", 1, version),
173 
174 //  ROW( STTORRYRecieved),
175 
176   ROW( StartPhaseCompleted, "phase",     1, phase),
177   ROW( StartPhaseCompleted, "starttype", 2, starttype),
178 
179   ROW( CM_REGCONF, "own_id",       1, own_id),
180   ROW( CM_REGCONF, "president_id", 2, president_id),
181   ROW( CM_REGCONF, "dynamic_id",   3, dynamic_id),
182 
183   ROW( CM_REGREF, "own_id",   1, own_id),
184   ROW( CM_REGREF, "other_id", 2, other_id),
185   ROW( CM_REGREF, "cause",    3, cause),
186 
187   ROW( FIND_NEIGHBOURS, "own_id",     1, own_id),
188   ROW( FIND_NEIGHBOURS, "left_id",    3, left_id),
189   ROW( FIND_NEIGHBOURS, "right_id",   3, right_id),
190   ROW( FIND_NEIGHBOURS, "dynamic_id", 4, dynamic_id),
191 
192   ROW( NDBStopStarted, "stoptype", 1, stoptype),
193 
194   ROW( NDBStopCompleted, "action",         1, action),
195   ROW( NDBStopCompleted, "signum",         2, signum),
196 
197   ROW( NDBStopForced, "action",         1, action),
198   ROW( NDBStopForced, "signum",         2, signum),
199   ROW( NDBStopForced, "error",          3, error),
200   ROW( NDBStopForced, "sphase",         4, sphase),
201   ROW( NDBStopForced, "extra",          5, extra),
202 
203 //  ROW( NDBStopAborted),
204 
205   ROW( LCPRestored, "restored_lcp_id", 1, restored_lcp_id),
206 
207   ROW( StartREDOLog, "node",           1, node),
208   ROW( StartREDOLog, "keep_gci",       2, keep_gci),
209   ROW( StartREDOLog, "completed_gci",  3, completed_gci),
210   ROW( StartREDOLog, "restorable_gci", 4, restorable_gci),
211 
212   ROW( StartLog, "log_part", 1, log_part),
213   ROW( StartLog, "start_mb", 2, start_mb),
214   ROW( StartLog, "stop_mb",  3, stop_mb),
215   ROW( StartLog, "gci",      4, gci),
216 
217   ROW( UNDORecordsExecuted, "block", 1, block),
218   ROW( UNDORecordsExecuted, "data1", 2, data1),
219   ROW( UNDORecordsExecuted, "data2", 3, data2),
220   ROW( UNDORecordsExecuted, "data3", 4, data3),
221   ROW( UNDORecordsExecuted, "data4", 5, data4),
222   ROW( UNDORecordsExecuted, "data5", 6, data5),
223   ROW( UNDORecordsExecuted, "data6", 7, data6),
224   ROW( UNDORecordsExecuted, "data7", 8, data7),
225   ROW( UNDORecordsExecuted, "data8", 9, data8),
226   ROW( UNDORecordsExecuted, "data9", 10, data9),
227   ROW( UNDORecordsExecuted, "data10", 11, data10),
228 
229       /* NODERESTART */
230 //  ROW( NR_CopyDict),
231 
232 //  ROW( NR_CopyDistr),
233 
234   ROW( NR_CopyFragsStarted, "dest_node", 1, dest_node),
235 
236   ROW( NR_CopyFragDone, "dest_node",   1, dest_node),
237   ROW( NR_CopyFragDone, "table_id",    2, table_id),
238   ROW( NR_CopyFragDone, "fragment_id", 3, fragment_id),
239 
240   ROW( NR_CopyFragsCompleted, "dest_node", 1, dest_node),
241 
242   ROW( NodeFailCompleted, "block",           1, block), /* 0 = all */
243   ROW( NodeFailCompleted, "failed_node",     2, failed_node),
244   ROW( NodeFailCompleted, "completing_node", 3, completing_node), /* 0 = all */
245 
246   ROW( NODE_FAILREP, "failed_node",   1, failed_node),
247   ROW( NODE_FAILREP, "failure_state", 2, failure_state),
248 
249 	/* TODO */
250   ROW( ArbitState,   "code",          1, code),
251   ROW( ArbitState,   "arbit_node",    2, arbit_node),
252   ROW( ArbitState,   "ticket_0",      3, ticket_0),
253   ROW( ArbitState,   "ticket_1",      4, ticket_1),
254 
255 	/* TODO */
256   ROW( ArbitResult,  "code",          1, code),
257   ROW( ArbitResult,  "arbit_node",    2, arbit_node),
258   ROW( ArbitResult,  "ticket_0",      3, ticket_0),
259   ROW( ArbitResult,  "ticket_1",      4, ticket_1),
260 
261 //  ROW( GCP_TakeoverStarted),
262 
263 //  ROW( GCP_TakeoverCompleted),
264 
265 //  ROW( LCP_TakeoverStarted),
266 
267   ROW( LCP_TakeoverCompleted, "state", 1, state),
268 
269       /* STATISTIC */
270   ROW( TransReportCounters, "trans_count",       1, trans_count),
271   ROW( TransReportCounters, "commit_count",      2, commit_count),
272   ROW( TransReportCounters, "read_count",        3, read_count),
273   ROW( TransReportCounters, "simple_read_count", 4, simple_read_count),
274   ROW( TransReportCounters, "write_count",       5, write_count),
275   ROW( TransReportCounters, "attrinfo_count",    6, attrinfo_count),
276   ROW( TransReportCounters, "conc_op_count",     7, conc_op_count),
277   ROW( TransReportCounters, "abort_count",       8, abort_count),
278   ROW( TransReportCounters, "scan_count",        9, scan_count),
279   ROW( TransReportCounters, "range_scan_count", 10, range_scan_count),
280 
281   ROW( OperationReportCounters, "ops", 1, ops),
282 
283   ROW( TableCreated, "table_id", 1, table_id),
284 
285   ROW( JobStatistic, "mean_loop_count", 1, mean_loop_count),
286 
287   ROW( SendBytesStatistic, "to_node",         1, to_node),
288   ROW( SendBytesStatistic, "mean_sent_bytes", 2, mean_sent_bytes),
289 
290   ROW( ReceiveBytesStatistic, "from_node",           1, from_node),
291   ROW( ReceiveBytesStatistic, "mean_received_bytes", 2, mean_received_bytes),
292 
293   ROW( MemoryUsage, "gth",          1, gth),
294   ROW( MemoryUsage, "page_size_bytes", 2, page_size_bytes),
295   ROW( MemoryUsage, "pages_used",   3, pages_used),
296   ROW( MemoryUsage, "pages_total",  4, pages_total),
297   ROW( MemoryUsage, "block",        5, block),
298 
299   ROW( MTSignalStatistics, "mt_deliver_thread", 1, thr_no),
300   ROW( MTSignalStatistics, "mt_prioa_count", 2, prioa_count),
301   ROW( MTSignalStatistics, "mt_prioa_size", 3, prioa_size),
302   ROW( MTSignalStatistics, "mt_priob_count", 4, priob_count),
303   ROW( MTSignalStatistics, "mt_priob_size", 5, priob_size),
304 
305       /* ERROR */
306   ROW( TransporterError, "to_node", 1, to_node),
307   ROW( TransporterError, "code",    2, code),
308 
309   ROW( TransporterWarning, "to_node", 1, to_node),
310   ROW( TransporterWarning, "code",    2, code),
311 
312   ROW( MissedHeartbeat, "node",  1, node),
313   ROW( MissedHeartbeat, "count", 2, count),
314 
315   ROW( DeadDueToHeartbeat, "node", 1, node),
316 
317 	/* TODO */
318 //  ROW( WarningEvent),
319 
320       /* INFO */
321   ROW( SentHeartbeat, "node", 1, node),
322 
323   ROW( CreateLogBytes, "node", 1, node),
324 
325 	/* TODO */
326 //  ROW( InfoEvent),
327 
328   ROW( EventBufferStatus, "usage",        1, usage),
329   ROW( EventBufferStatus, "alloc",        2, alloc),
330   ROW( EventBufferStatus, "max",          3, max),
331   ROW( EventBufferStatus, "apply_gci_l",  4, apply_gci_l),
332   ROW( EventBufferStatus, "apply_gci_h",  5, apply_gci_h),
333   ROW( EventBufferStatus, "latest_gci_l", 6, latest_gci_l),
334   ROW( EventBufferStatus, "latest_gci_h", 7, latest_gci_h),
335 
336   // Backup
337   ROW_FN( BackupStarted,    "starting_node", 1, starting_node, ref_to_node),
338   ROW( BackupStarted,       "backup_id",     2, backup_id),
339 
340   ROW_FN(BackupFailedToStart,"starting_node",1, starting_node, ref_to_node),
341   ROW( BackupFailedToStart, "error",         2, error),
342 
343   ROW_FN( BackupCompleted,  "starting_node", 1, starting_node, ref_to_node),
344   ROW( BackupCompleted,     "backup_id",     2, backup_id),
345   ROW( BackupCompleted,     "start_gci",     3, start_gci),
346   ROW( BackupCompleted,     "stop_gci",      4, stop_gci),
347   ROW( BackupCompleted,     "n_bytes",       5, n_bytes),
348   ROW( BackupCompleted,     "n_records",     6, n_records),
349   ROW( BackupCompleted,     "n_log_bytes",   7, n_log_bytes),
350   ROW( BackupCompleted,     "n_log_records", 8, n_log_records),
351   ROW( BackupCompleted,     "n_bytes_hi",    11, n_bytes_hi),
352   ROW( BackupCompleted,     "n_records_hi", 12, n_records_hi),
353   ROW( BackupCompleted,     "n_log_bytes_hi",   13, n_log_bytes_hi),
354   ROW( BackupCompleted,     "n_log_records_hi", 14, n_log_records_hi),
355 
356   ROW_FN( BackupStatus,     "starting_node",    1, starting_node, ref_to_node),
357   ROW( BackupStatus,        "backup_id",        2, backup_id),
358   ROW( BackupStatus,        "n_bytes_lo",       3, n_bytes_lo),
359   ROW( BackupStatus,        "n_bytes_hi",       4, n_bytes_hi),
360   ROW( BackupStatus,        "n_records_lo",     5, n_records_lo),
361   ROW( BackupStatus,        "n_records_hi",     6, n_records_hi),
362   ROW( BackupStatus,        "n_log_bytes_lo",   7, n_log_bytes_lo),
363   ROW( BackupStatus,        "n_log_bytes_hi",   8, n_log_bytes_hi),
364   ROW( BackupStatus,        "n_log_records_lo", 9, n_log_records_lo),
365   ROW( BackupStatus,        "n_log_records_hi",10, n_log_records_hi),
366 
367   ROW_FN( BackupAborted,    "starting_node", 1, starting_node, ref_to_node),
368   ROW( BackupAborted,       "backup_id",     2, backup_id),
369   ROW( BackupAborted,       "error",         3, error),
370 
371   ROW( RestoreStarted,      "backup_id",     1, backup_id),
372   ROW( RestoreStarted,      "node_id",       2, node_id),
373 
374   ROW( RestoreMetaData,     "backup_id",     1, backup_id),
375   ROW( RestoreMetaData,     "node_id",       2, node_id),
376   ROW( RestoreMetaData,     "n_tables",      3, n_tables),
377   ROW( RestoreMetaData,     "n_tablespaces", 4, n_tablespaces),
378   ROW( RestoreMetaData,     "n_logfilegroups", 5, n_logfilegroups),
379   ROW( RestoreMetaData,     "n_datafiles",   6, n_datafiles),
380   ROW( RestoreMetaData,     "n_undofiles",   7, n_undofiles),
381 
382   ROW( RestoreData,         "backup_id",     1, backup_id),
383   ROW( RestoreData,         "node_id",       2, node_id),
384   ROW( RestoreData,         "n_records_lo",  3, n_records_lo),
385   ROW( RestoreData,         "n_records_hi",  4, n_records_hi),
386   ROW( RestoreData,         "n_bytes_lo",    5, n_bytes_lo),
387   ROW( RestoreData,         "n_bytes_hi",    6, n_bytes_hi),
388 
389   ROW( RestoreLog,          "backup_id",     1, backup_id),
390   ROW( RestoreLog,          "node_id",       2, node_id),
391   ROW( RestoreLog,          "n_records_lo",  3, n_records_lo),
392   ROW( RestoreLog,          "n_records_hi",  4, n_records_hi),
393   ROW( RestoreLog,          "n_bytes_lo",    5, n_bytes_lo),
394   ROW( RestoreLog,          "n_bytes_hi",    6, n_bytes_hi),
395 
396   ROW( RestoreCompleted,    "backup_id",     1, backup_id),
397   ROW( RestoreCompleted,    "node_id",       2, node_id),
398 
399   ROW( SingleUser,          "type",	     1, type),
400   ROW( SingleUser,          "node_id",	     2, node_id),
401 
402   ROW( LogFileInitStatus,   "node_id",       1, node_id ),
403   ROW( LogFileInitStatus,   "total_files",   2, total_files),
404   ROW( LogFileInitStatus,   "file_done",     3, file_done),
405   ROW( LogFileInitStatus,   "total_mbytes",  4, total_mbytes),
406   ROW( LogFileInitStatus,   "mbytes_done",   5, mbytes_done),
407 
408 
409   ROW( RedoStatus,          "log_part",      1, log_part),
410   ROW( RedoStatus,          "head_file_no",  2, head_file_no),
411   ROW( RedoStatus,          "head_mbyte",    3, head_mbyte),
412   ROW( RedoStatus,          "tail_file_no",  4, tail_file_no),
413   ROW( RedoStatus,          "tail_mbyte",    5, tail_mbyte),
414   ROW( RedoStatus,          "total_hi",      6, total_hi),
415   ROW( RedoStatus,          "total_lo",      7, total_lo),
416   ROW( RedoStatus,          "free_hi",       8, free_hi),
417   ROW( RedoStatus,          "free_lo",       9, free_lo),
418   ROW( RedoStatus,          "no_logfiles",  10, no_logfiles),
419   ROW( RedoStatus,          "logfilesize",  11, logfilesize),
420 
421   ROW( EventBufferStatus2, "usage",        1, usage),
422   ROW( EventBufferStatus2, "alloc",        2, alloc),
423   ROW( EventBufferStatus2, "max",          3, max),
424   ROW( EventBufferStatus2, "latest_consumed_epoch_l", 4, latest_consumed_epoch_l),
425   ROW( EventBufferStatus2, "latest_consumed_epoch_h", 5, latest_consumed_epoch_h),
426   ROW( EventBufferStatus2, "latest_buffered_epoch_l",  6, latest_buffered_epoch_l),
427   ROW( EventBufferStatus2, "latest_buffered_epoch_h",  7, latest_buffered_epoch_h),
428   ROW( EventBufferStatus2, "ndb_reference", 8, ndb_reference),
429   ROW( EventBufferStatus2, "report_reason", 9, report_reason),
430 
431   { NDB_LE_ILLEGAL_TYPE, 0, 0, 0, 0, 0}
432 };
433 
434 struct Ndb_logevent_header_row {
435   const char            *token;    // token to use for text transfer
436   int                    offset;   // offset into struct ndb_logevent
437   int                    size;
438 };
439 
440 #define ROW2(a,b) \
441 { a, offsetof(struct ndb_logevent, b), \
442   sizeof(((struct ndb_logevent *)0)->b) }
443 
444 struct Ndb_logevent_header_row ndb_logevent_header[]= {
445   ROW2( "type",          type),
446   ROW2( "time",          time),
447   ROW2( "source_nodeid", source_nodeid),
448   { 0, 0, 0 }
449 };
450 
451 static int
insert_row(const char * pair,Properties & p)452 insert_row(const char * pair, Properties & p){
453   BaseString tmp(pair);
454 
455   tmp.trim(" \t\n\r");
456   Vector<BaseString> split;
457   tmp.split(split, ":=", 2);
458   if(split.size() != 2)
459     return -1;
460   p.put(split[0].trim().c_str(), split[1].trim().c_str());
461 
462   return 0;
463 }
464 
465 static
memcpy_atoi(void * dst,const char * str,int sz)466 int memcpy_atoi(void *dst, const char *str, int sz)
467 {
468   switch (sz)
469   {
470   case 1:
471   {
472     Int8 val= atoi(str);
473     memcpy(dst,&val,sz);
474     return 0;
475   }
476   case 2:
477   {
478     Int16 val= atoi(str);
479     memcpy(dst,&val,sz);
480     return 0;
481   }
482   case 4:
483   {
484     Int32 val= atoi(str);
485     memcpy(dst,&val,sz);
486     return 0;
487   }
488   case 8:
489   {
490     Int64 val= atoi(str);
491     memcpy(dst,&val,sz);
492     return 0;
493   }
494   default:
495   {
496     return -1;
497   }
498   }
499 }
500 
501 extern "C"
ndb_logevent_get_next(const NdbLogEventHandle h,struct ndb_logevent * dst,unsigned timeout_in_milliseconds)502 int ndb_logevent_get_next(const NdbLogEventHandle h,
503                            struct ndb_logevent *dst,
504                            unsigned timeout_in_milliseconds)
505 {
506   int rc = ndb_logevent_get_next2(h,
507                                   dst,
508                                   timeout_in_milliseconds);
509   if (rc == 1)
510   {
511     /**
512      * Undo effect of bug#16723708 fix to maintain
513      * backwards compatibility
514      */
515     Uint32 category = (Uint32) dst->category;
516     switch(category)
517     {
518     case (Uint32) NDB_MGM_ILLEGAL_EVENT_CATEGORY:
519       category = (Uint32) LogLevel::llInvalid;
520       break;
521     default:
522       category -= CFG_MIN_LOGLEVEL;
523     }
524     dst->category = (enum ndb_mgm_event_category) category;
525   }
526 
527   return rc;
528 }
529 
530 extern "C"
ndb_logevent_get_next2(const NdbLogEventHandle h,struct ndb_logevent * dst,unsigned timeout_in_milliseconds)531 int ndb_logevent_get_next2(const NdbLogEventHandle h,
532                            struct ndb_logevent *dst,
533                            unsigned timeout_in_milliseconds)
534 {
535   if (timeout_in_milliseconds == 0)
536   {
537     int res;
538     while ((res = ndb_logevent_get_next2(h, dst, 60000))==0);
539     return res;
540   }
541 
542   SocketInputStream in(h->socket, timeout_in_milliseconds);
543 
544   /*
545     Read log event header until header received
546     or timeout expired. The MGM server will continusly
547     send <PING>'s that should be ignored.
548   */
549   char buf[1024];
550   const NDB_TICKS start = NdbTick_getCurrentTicks();
551   while(1)
552   {
553     if (in.gets(buf,sizeof(buf)) == 0)
554     {
555       h->m_error= NDB_LEH_READ_ERROR;
556       return -1;
557     }
558     if ( buf[0] == 0 )
559     {
560       // timed out
561       return 0;
562     }
563 
564     if ( strcmp("log event reply\n", buf) == 0 )
565       break;
566 
567     if ( strcmp("<PING>\n", buf) )
568       ndbout_c("skipped: %s", buf);
569 
570     if(in.timedout())
571       return 0;
572 
573     const NDB_TICKS now = NdbTick_getCurrentTicks();
574     if ((NdbTick_Elapsed(start,now)).milliSec() > timeout_in_milliseconds)
575       return 0;
576 
577   };
578 
579   /* Read name-value pairs until empty new line */
580   Properties p;
581   while (1)
582   {
583     if (in.gets(buf,sizeof(buf)) == 0)
584     {
585       h->m_error= NDB_LEH_READ_ERROR;
586       return -1;
587     }
588     if (in.timedout())
589       return 0;
590 
591     if ( buf[0] == '\n' )
592     {
593       break;
594     }
595     if (insert_row(buf,p))
596     {
597       h->m_error= NDB_LEH_READ_ERROR;
598       return -1;
599     }
600   }
601 
602   int i;
603   const char *val;
604 
605   dst->type= (enum Ndb_logevent_type)-1;
606   /* fill in header info from p*/
607   for (i= 0; ndb_logevent_header[i].token; i++)
608   {
609     if ( p.get(ndb_logevent_header[i].token, &val) == 0 )
610     {
611       ndbout_c("missing: %s\n", ndb_logevent_header[i].token);
612       h->m_error= NDB_LEH_MISSING_EVENT_SPECIFIER;
613       return -1;
614     }
615     if ( memcpy_atoi((char *)dst+ndb_logevent_header[i].offset, val,
616 		     ndb_logevent_header[i].size) )
617     {
618       h->m_error= NDB_LEH_INTERNAL_ERROR;
619       return -1;
620     }
621   }
622 
623   Uint32                             level;
624   LogLevel::EventCategory            category;
625   Logger::LoggerLevel                severity;
626   EventLoggerBase::EventTextFunction text_fn;
627 
628   /* fill in rest of header info event_lookup */
629   if (EventLoggerBase::event_lookup(dst->type,category,level,severity,text_fn))
630   {
631     ndbout_c("unknown type: %d\n", dst->type);
632     h->m_error= NDB_LEH_UNKNOWN_EVENT_TYPE;
633     return -1;
634   }
635 
636   /* convert LogLevel::EventCategory enum values to ndb_mgm_event_category
637    * enum values and store in dst->category
638    */
639   enum ndb_mgm_event_category mgm_category;
640   if(category == LogLevel::llInvalid)
641       mgm_category= NDB_MGM_ILLEGAL_EVENT_CATEGORY;
642   else
643       mgm_category= (enum ndb_mgm_event_category)(category + CFG_MIN_LOGLEVEL);
644 
645   dst->category= mgm_category;
646   dst->severity= (enum ndb_mgm_event_severity)severity;
647   dst->level=    level;
648 
649   /* fill in header info from p */
650   for (i= 0; ndb_logevent_body[i].token; i++)
651   {
652     if ( ndb_logevent_body[i].type == dst->type )
653       break;
654   }
655 
656   if (ndb_logevent_body[i].token)
657   {
658     do {
659 
660       if ( p.get(ndb_logevent_body[i].token, &val) == 0 )
661       {
662         h->m_error= NDB_LEH_UNKNOWN_EVENT_VARIABLE;
663         return -1;
664       }
665       if ( memcpy_atoi((char *)dst+ndb_logevent_body[i].offset, val,
666                        ndb_logevent_body[i].size) )
667       {
668         h->m_error= NDB_LEH_INTERNAL_ERROR;
669         return -1;
670       }
671     } while (ndb_logevent_body[++i].type == dst->type);
672   }
673   else
674   {
675     if (!p.get("data", &val))
676     {
677       h->m_error= NDB_LEH_UNKNOWN_EVENT_VARIABLE;
678       return -1;
679     }
680     BaseString tmp(val);
681     Vector<BaseString> list;
682     tmp.split(list);
683     for (unsigned j = 0; j<list.size(); j++)
684     {
685       dst->Data[j] = (unsigned)atoll(list[j].c_str());
686     }
687   }
688   return 1;
689 }
690 
691 extern "C"
ndb_logevent_get_latest_error(const NdbLogEventHandle h)692 int ndb_logevent_get_latest_error(const NdbLogEventHandle h)
693 {
694   return h->m_error;
695 }
696 
697 extern "C"
ndb_logevent_get_latest_error_msg(const NdbLogEventHandle h)698 const char *ndb_logevent_get_latest_error_msg(const NdbLogEventHandle h)
699 {
700   for (int i= 0; ndb_logevent_error_messages[i].msg; i++)
701     if (ndb_logevent_error_messages[i].code == h->m_error)
702       return ndb_logevent_error_messages[i].msg;
703   return "<unknown error msg>";
704 }
705