1 /*
2    Copyright (c) 2005, 2010, 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 #ifdef NDB_WIN
104 SOCKET
ndb_logevent_get_fd(const NdbLogEventHandle h)105 ndb_logevent_get_fd(const NdbLogEventHandle h)
106 {
107   return h->socket.s;
108 }
109 #else
110 int
111 ndb_logevent_get_fd(const NdbLogEventHandle h)
112 {
113   return h->socket.fd;
114 }
115 #endif
116 
117 extern "C"
ndb_mgm_destroy_logevent_handle(NdbLogEventHandle * h)118 void ndb_mgm_destroy_logevent_handle(NdbLogEventHandle * h)
119 {
120   if( !h )
121     return;
122 
123   if ( *h )
124     my_socket_close((*h)->socket);
125 
126   free(*h);
127   * h = 0;
128 }
129 
130 #define ROW(a,b,c,d) \
131 { NDB_LE_ ## a,  b, c, 0, offsetof(struct ndb_logevent, a.d), \
132   sizeof(((struct ndb_logevent *)0)->a.d) }
133 
134 #define ROW_FN(a,b,c,d,e) \
135 { NDB_LE_ ## a,  b, c, e, offsetof(struct ndb_logevent, a.d), \
136   sizeof(((struct ndb_logevent *)0)->a.d) }
137 
ref_to_node(int ref)138 static int ref_to_node(int ref){
139   return ref & 0xFFFF;
140 }
141 
142 struct Ndb_logevent_body_row ndb_logevent_body[]= {
143 
144   // Connection
145   ROW( Connected,           "node",          1, node),
146 
147   ROW( Disconnected,        "node",          1, node),
148 
149   ROW( CommunicationClosed, "node",          1, node),
150 
151   ROW( CommunicationOpened, "node",          1, node),
152 
153   ROW( ConnectedApiVersion, "node",          1, node),
154   ROW( ConnectedApiVersion, "version",       2, version),
155 
156       /* CHECKPOINT */
157 
158   ROW( GlobalCheckpointStarted, "gci", 1, gci),
159 
160   ROW( GlobalCheckpointCompleted, "gci", 1, gci),
161 
162   ROW( LocalCheckpointStarted, "lci",         1, lci),
163   ROW( LocalCheckpointStarted, "keep_gci",    2, keep_gci),
164   ROW( LocalCheckpointStarted, "restore_gci", 3, restore_gci),
165 
166   ROW( LocalCheckpointCompleted, "lci", 1, lci),
167 
168   ROW( LCPStoppedInCalcKeepGci, "data", 1, data),
169 
170   ROW( LCPFragmentCompleted, "node",        1, node),
171   ROW( LCPFragmentCompleted, "table_id",    2, table_id),
172   ROW( LCPFragmentCompleted, "fragment_id", 3, fragment_id),
173 
174   ROW( UndoLogBlocked, "acc_count", 1, acc_count),
175   ROW( UndoLogBlocked, "tup_count", 2, tup_count),
176 
177       /* STARTUP */
178   ROW( NDBStartStarted, "version", 1, version),
179 
180   ROW( NDBStartCompleted, "version", 1, version),
181 
182 //  ROW( STTORRYRecieved),
183 
184   ROW( StartPhaseCompleted, "phase",     1, phase),
185   ROW( StartPhaseCompleted, "starttype", 2, starttype),
186 
187   ROW( CM_REGCONF, "own_id",       1, own_id),
188   ROW( CM_REGCONF, "president_id", 2, president_id),
189   ROW( CM_REGCONF, "dynamic_id",   3, dynamic_id),
190 
191   ROW( CM_REGREF, "own_id",   1, own_id),
192   ROW( CM_REGREF, "other_id", 2, other_id),
193   ROW( CM_REGREF, "cause",    3, cause),
194 
195   ROW( FIND_NEIGHBOURS, "own_id",     1, own_id),
196   ROW( FIND_NEIGHBOURS, "left_id",    3, left_id),
197   ROW( FIND_NEIGHBOURS, "right_id",   3, right_id),
198   ROW( FIND_NEIGHBOURS, "dynamic_id", 4, dynamic_id),
199 
200   ROW( NDBStopStarted, "stoptype", 1, stoptype),
201 
202   ROW( NDBStopCompleted, "action",         1, action),
203   ROW( NDBStopCompleted, "signum",         2, signum),
204 
205   ROW( NDBStopForced, "action",         1, action),
206   ROW( NDBStopForced, "signum",         2, signum),
207   ROW( NDBStopForced, "error",          3, error),
208   ROW( NDBStopForced, "sphase",         4, sphase),
209   ROW( NDBStopForced, "extra",          5, extra),
210 
211 //  ROW( NDBStopAborted),
212 
213   ROW( StartREDOLog, "node",           1, node),
214   ROW( StartREDOLog, "keep_gci",       2, keep_gci),
215   ROW( StartREDOLog, "completed_gci",  3, completed_gci),
216   ROW( StartREDOLog, "restorable_gci", 4, restorable_gci),
217 
218   ROW( StartLog, "log_part", 1, log_part),
219   ROW( StartLog, "start_mb", 2, start_mb),
220   ROW( StartLog, "stop_mb",  3, stop_mb),
221   ROW( StartLog, "gci",      4, gci),
222 
223   ROW( UNDORecordsExecuted, "block", 1, block),
224   ROW( UNDORecordsExecuted, "data1", 2, data1),
225   ROW( UNDORecordsExecuted, "data2", 3, data2),
226   ROW( UNDORecordsExecuted, "data3", 4, data3),
227   ROW( UNDORecordsExecuted, "data4", 5, data4),
228   ROW( UNDORecordsExecuted, "data5", 6, data5),
229   ROW( UNDORecordsExecuted, "data6", 7, data6),
230   ROW( UNDORecordsExecuted, "data7", 8, data7),
231   ROW( UNDORecordsExecuted, "data8", 9, data8),
232   ROW( UNDORecordsExecuted, "data9", 10, data9),
233   ROW( UNDORecordsExecuted, "data10", 11, data10),
234 
235       /* NODERESTART */
236 //  ROW( NR_CopyDict),
237 
238 //  ROW( NR_CopyDistr),
239 
240   ROW( NR_CopyFragsStarted, "dest_node", 1, dest_node),
241 
242   ROW( NR_CopyFragDone, "dest_node",   1, dest_node),
243   ROW( NR_CopyFragDone, "table_id",    2, table_id),
244   ROW( NR_CopyFragDone, "fragment_id", 3, fragment_id),
245 
246   ROW( NR_CopyFragsCompleted, "dest_node", 1, dest_node),
247 
248   ROW( NodeFailCompleted, "block",           1, block), /* 0 = all */
249   ROW( NodeFailCompleted, "failed_node",     2, failed_node),
250   ROW( NodeFailCompleted, "completing_node", 3, completing_node), /* 0 = all */
251 
252   ROW( NODE_FAILREP, "failed_node",   1, failed_node),
253   ROW( NODE_FAILREP, "failure_state", 2, failure_state),
254 
255 	/* TODO */
256   ROW( ArbitState,   "code",          1, code),
257   ROW( ArbitState,   "arbit_node",    2, arbit_node),
258   ROW( ArbitState,   "ticket_0",      3, ticket_0),
259   ROW( ArbitState,   "ticket_1",      4, ticket_1),
260 
261 	/* TODO */
262   ROW( ArbitResult,  "code",          1, code),
263   ROW( ArbitResult,  "arbit_node",    2, arbit_node),
264   ROW( ArbitResult,  "ticket_0",      3, ticket_0),
265   ROW( ArbitResult,  "ticket_1",      4, ticket_1),
266 
267 //  ROW( GCP_TakeoverStarted),
268 
269 //  ROW( GCP_TakeoverCompleted),
270 
271 //  ROW( LCP_TakeoverStarted),
272 
273   ROW( LCP_TakeoverCompleted, "state", 1, state),
274 
275       /* STATISTIC */
276   ROW( TransReportCounters, "trans_count",       1, trans_count),
277   ROW( TransReportCounters, "commit_count",      2, commit_count),
278   ROW( TransReportCounters, "read_count",        3, read_count),
279   ROW( TransReportCounters, "simple_read_count", 4, simple_read_count),
280   ROW( TransReportCounters, "write_count",       5, write_count),
281   ROW( TransReportCounters, "attrinfo_count",    6, attrinfo_count),
282   ROW( TransReportCounters, "conc_op_count",     7, conc_op_count),
283   ROW( TransReportCounters, "abort_count",       8, abort_count),
284   ROW( TransReportCounters, "scan_count",        9, scan_count),
285   ROW( TransReportCounters, "range_scan_count", 10, range_scan_count),
286 
287   ROW( OperationReportCounters, "ops", 1, ops),
288 
289   ROW( TableCreated, "table_id", 1, table_id),
290 
291   ROW( JobStatistic, "mean_loop_count", 1, mean_loop_count),
292 
293   ROW( SendBytesStatistic, "to_node",         1, to_node),
294   ROW( SendBytesStatistic, "mean_sent_bytes", 2, mean_sent_bytes),
295 
296   ROW( ReceiveBytesStatistic, "from_node",           1, from_node),
297   ROW( ReceiveBytesStatistic, "mean_received_bytes", 2, mean_received_bytes),
298 
299   ROW( MemoryUsage, "gth",          1, gth),
300   ROW( MemoryUsage, "page_size_bytes", 2, page_size_bytes),
301   ROW( MemoryUsage, "pages_used",   3, pages_used),
302   ROW( MemoryUsage, "pages_total",  4, pages_total),
303   ROW( MemoryUsage, "block",        5, block),
304 
305   ROW( MTSignalStatistics, "mt_deliver_thread", 1, thr_no),
306   ROW( MTSignalStatistics, "mt_prioa_count", 2, prioa_count),
307   ROW( MTSignalStatistics, "mt_prioa_size", 3, prioa_size),
308   ROW( MTSignalStatistics, "mt_priob_count", 4, priob_count),
309   ROW( MTSignalStatistics, "mt_priob_size", 5, priob_size),
310 
311       /* ERROR */
312   ROW( TransporterError, "to_node", 1, to_node),
313   ROW( TransporterError, "code",    2, code),
314 
315   ROW( TransporterWarning, "to_node", 1, to_node),
316   ROW( TransporterWarning, "code",    2, code),
317 
318   ROW( MissedHeartbeat, "node",  1, node),
319   ROW( MissedHeartbeat, "count", 2, count),
320 
321   ROW( DeadDueToHeartbeat, "node", 1, node),
322 
323 	/* TODO */
324 //  ROW( WarningEvent),
325 
326       /* INFO */
327   ROW( SentHeartbeat, "node", 1, node),
328 
329   ROW( CreateLogBytes, "node", 1, node),
330 
331 	/* TODO */
332 //  ROW( InfoEvent),
333 
334   ROW( EventBufferStatus, "usage",        1, usage),
335   ROW( EventBufferStatus, "alloc",        2, alloc),
336   ROW( EventBufferStatus, "max",          3, max),
337   ROW( EventBufferStatus, "apply_gci_l",  4, apply_gci_l),
338   ROW( EventBufferStatus, "apply_gci_h",  5, apply_gci_h),
339   ROW( EventBufferStatus, "latest_gci_l", 6, latest_gci_l),
340   ROW( EventBufferStatus, "latest_gci_h", 7, latest_gci_h),
341 
342   // Backup
343   ROW_FN( BackupStarted,    "starting_node", 1, starting_node, ref_to_node),
344   ROW( BackupStarted,       "backup_id",     2, backup_id),
345 
346   ROW_FN(BackupFailedToStart,"starting_node",1, starting_node, ref_to_node),
347   ROW( BackupFailedToStart, "error",         2, error),
348 
349   ROW_FN( BackupCompleted,  "starting_node", 1, starting_node, ref_to_node),
350   ROW( BackupCompleted,     "backup_id",     2, backup_id),
351   ROW( BackupCompleted,     "start_gci",     3, start_gci),
352   ROW( BackupCompleted,     "stop_gci",      4, stop_gci),
353   ROW( BackupCompleted,     "n_bytes",       5, n_bytes),
354   ROW( BackupCompleted,     "n_records",     6, n_records),
355   ROW( BackupCompleted,     "n_log_bytes",   7, n_log_bytes),
356   ROW( BackupCompleted,     "n_log_records", 8, n_log_records),
357   ROW( BackupCompleted,     "n_bytes_hi",    9+NdbNodeBitmask::Size, n_bytes_hi),
358   ROW( BackupCompleted,     "n_records_hi", 10+NdbNodeBitmask::Size, n_records_hi),
359   ROW( BackupCompleted,     "n_log_bytes_hi",   11+NdbNodeBitmask::Size, n_log_bytes_hi),
360   ROW( BackupCompleted,     "n_log_records_hi", 12+NdbNodeBitmask::Size, n_log_records_hi),
361 
362   ROW_FN( BackupStatus,     "starting_node",    1, starting_node, ref_to_node),
363   ROW( BackupStatus,        "backup_id",        2, backup_id),
364   ROW( BackupStatus,        "n_bytes_lo",       3, n_bytes_lo),
365   ROW( BackupStatus,        "n_bytes_hi",       4, n_bytes_hi),
366   ROW( BackupStatus,        "n_records_lo",     5, n_records_lo),
367   ROW( BackupStatus,        "n_records_hi",     6, n_records_hi),
368   ROW( BackupStatus,        "n_log_bytes_lo",   7, n_log_bytes_lo),
369   ROW( BackupStatus,        "n_log_bytes_hi",   8, n_log_bytes_hi),
370   ROW( BackupStatus,        "n_log_records_lo", 9, n_log_records_lo),
371   ROW( BackupStatus,        "n_log_records_hi",10, n_log_records_hi),
372 
373   ROW_FN( BackupAborted,    "starting_node", 1, starting_node, ref_to_node),
374   ROW( BackupAborted,       "backup_id",     2, backup_id),
375   ROW( BackupAborted,       "error",         3, error),
376 
377   ROW( RestoreStarted,      "backup_id",     1, backup_id),
378   ROW( RestoreStarted,      "node_id",       2, node_id),
379 
380   ROW( RestoreMetaData,     "backup_id",     1, backup_id),
381   ROW( RestoreMetaData,     "node_id",       2, node_id),
382   ROW( RestoreMetaData,     "n_tables",      3, n_tables),
383   ROW( RestoreMetaData,     "n_tablespaces", 4, n_tablespaces),
384   ROW( RestoreMetaData,     "n_logfilegroups", 5, n_logfilegroups),
385   ROW( RestoreMetaData,     "n_datafiles",   6, n_datafiles),
386   ROW( RestoreMetaData,     "n_undofiles",   7, n_undofiles),
387 
388   ROW( RestoreData,         "backup_id",     1, backup_id),
389   ROW( RestoreData,         "node_id",       2, node_id),
390   ROW( RestoreData,         "n_records_lo",  3, n_records_lo),
391   ROW( RestoreData,         "n_records_hi",  4, n_records_hi),
392   ROW( RestoreData,         "n_bytes_lo",    5, n_bytes_lo),
393   ROW( RestoreData,         "n_bytes_hi",    6, n_bytes_hi),
394 
395   ROW( RestoreLog,          "backup_id",     1, backup_id),
396   ROW( RestoreLog,          "node_id",       2, node_id),
397   ROW( RestoreLog,          "n_records_lo",  3, n_records_lo),
398   ROW( RestoreLog,          "n_records_hi",  4, n_records_hi),
399   ROW( RestoreLog,          "n_bytes_lo",    5, n_bytes_lo),
400   ROW( RestoreLog,          "n_bytes_hi",    6, n_bytes_hi),
401 
402   ROW( RestoreCompleted,    "backup_id",     1, backup_id),
403   ROW( RestoreCompleted,    "node_id",       2, node_id),
404 
405   ROW( SingleUser,          "type",	     1, type),
406   ROW( SingleUser,          "node_id",	     2, node_id),
407 
408   ROW( LogFileInitStatus,   "node_id",       1, node_id ),
409   ROW( LogFileInitStatus,   "total_files",   2, total_files),
410   ROW( LogFileInitStatus,   "file_done",     3, file_done),
411   ROW( LogFileInitStatus,   "total_mbytes",  4, total_mbytes),
412   ROW( LogFileInitStatus,   "mbytes_done",   5, mbytes_done),
413 
414   { NDB_LE_ILLEGAL_TYPE, 0, 0, 0, 0, 0}
415 };
416 
417 struct Ndb_logevent_header_row {
418   const char            *token;    // token to use for text transfer
419   int                    offset;   // offset into struct ndb_logevent
420   int                    size;
421 };
422 
423 #define ROW2(a,b) \
424 { a, offsetof(struct ndb_logevent, b), \
425   sizeof(((struct ndb_logevent *)0)->b) }
426 
427 struct Ndb_logevent_header_row ndb_logevent_header[]= {
428   ROW2( "type",          type),
429   ROW2( "time",          time),
430   ROW2( "source_nodeid", source_nodeid),
431   { 0, 0, 0 }
432 };
433 
434 static int
insert_row(const char * pair,Properties & p)435 insert_row(const char * pair, Properties & p){
436   BaseString tmp(pair);
437 
438   tmp.trim(" \t\n\r");
439   Vector<BaseString> split;
440   tmp.split(split, ":=", 2);
441   if(split.size() != 2)
442     return -1;
443   p.put(split[0].trim().c_str(), split[1].trim().c_str());
444 
445   return 0;
446 }
447 
448 static
memcpy_atoi(void * dst,const char * str,int sz)449 int memcpy_atoi(void *dst, const char *str, int sz)
450 {
451   switch (sz)
452   {
453   case 1:
454   {
455     Int8 val= atoi(str);
456     memcpy(dst,&val,sz);
457     return 0;
458   }
459   case 2:
460   {
461     Int16 val= atoi(str);
462     memcpy(dst,&val,sz);
463     return 0;
464   }
465   case 4:
466   {
467     Int32 val= atoi(str);
468     memcpy(dst,&val,sz);
469     return 0;
470   }
471   case 8:
472   {
473     Int64 val= atoi(str);
474     memcpy(dst,&val,sz);
475     return 0;
476   }
477   default:
478   {
479     return -1;
480   }
481   }
482 }
483 
484 extern "C"
ndb_logevent_get_next(const NdbLogEventHandle h,struct ndb_logevent * dst,unsigned timeout_in_milliseconds)485 int ndb_logevent_get_next(const NdbLogEventHandle h,
486 			  struct ndb_logevent *dst,
487 			  unsigned timeout_in_milliseconds)
488 {
489   if (timeout_in_milliseconds == 0)
490   {
491     int res;
492     while ((res = ndb_logevent_get_next(h, dst, 60000))==0);
493     return res;
494   }
495 
496   SocketInputStream in(h->socket, timeout_in_milliseconds);
497 
498   /*
499     Read log event header until header received
500     or timeout expired. The MGM server will continusly
501     send <PING>'s that should be ignored.
502   */
503   char buf[1024];
504   NDB_TICKS start = NdbTick_CurrentMillisecond();
505   while(1)
506   {
507     if (in.gets(buf,sizeof(buf)) == 0)
508     {
509       h->m_error= NDB_LEH_READ_ERROR;
510       return -1;
511     }
512     if ( buf[0] == 0 )
513     {
514       // timed out
515       return 0;
516     }
517 
518     if ( strcmp("log event reply\n", buf) == 0 )
519       break;
520 
521     if ( strcmp("<PING>\n", buf) )
522       ndbout_c("skipped: %s", buf);
523 
524     if(in.timedout())
525         return 0;
526 
527     if ((NdbTick_CurrentMillisecond() - start) > timeout_in_milliseconds)
528       return 0;
529 
530   };
531 
532   /* Read name-value pairs until empty new line */
533   Properties p;
534   while (1)
535   {
536     if (in.gets(buf,sizeof(buf)) == 0)
537     {
538       h->m_error= NDB_LEH_READ_ERROR;
539       return -1;
540     }
541     if (in.timedout())
542       return 0;
543 
544     if ( buf[0] == '\n' )
545     {
546       break;
547     }
548     if (insert_row(buf,p))
549     {
550       h->m_error= NDB_LEH_READ_ERROR;
551       return -1;
552     }
553   }
554 
555   int i;
556   const char *val;
557 
558   dst->type= (enum Ndb_logevent_type)-1;
559   /* fill in header info from p*/
560   for (i= 0; ndb_logevent_header[i].token; i++)
561   {
562     if ( p.get(ndb_logevent_header[i].token, &val) == 0 )
563     {
564       ndbout_c("missing: %s\n", ndb_logevent_header[i].token);
565       h->m_error= NDB_LEH_MISSING_EVENT_SPECIFIER;
566       return -1;
567     }
568     if ( memcpy_atoi((char *)dst+ndb_logevent_header[i].offset, val,
569 		     ndb_logevent_header[i].size) )
570     {
571       h->m_error= NDB_LEH_INTERNAL_ERROR;
572       return -1;
573     }
574   }
575 
576   Uint32                             level;
577   LogLevel::EventCategory            category;
578   Logger::LoggerLevel                severity;
579   EventLoggerBase::EventTextFunction text_fn;
580 
581   /* fill in rest of header info event_lookup */
582   if (EventLoggerBase::event_lookup(dst->type,category,level,severity,text_fn))
583   {
584     ndbout_c("unknown type: %d\n", dst->type);
585     h->m_error= NDB_LEH_UNKNOWN_EVENT_TYPE;
586     return -1;
587   }
588   dst->category= (enum ndb_mgm_event_category)category;
589   dst->severity= (enum ndb_mgm_event_severity)severity;
590   dst->level=    level;
591 
592   /* fill in header info from p */
593   for (i= 0; ndb_logevent_body[i].token; i++)
594   {
595     if ( ndb_logevent_body[i].type == dst->type )
596       break;
597   }
598 
599   if (ndb_logevent_body[i].token)
600   {
601     do {
602 
603       if ( p.get(ndb_logevent_body[i].token, &val) == 0 )
604       {
605         h->m_error= NDB_LEH_UNKNOWN_EVENT_VARIABLE;
606         return -1;
607       }
608       if ( memcpy_atoi((char *)dst+ndb_logevent_body[i].offset, val,
609                        ndb_logevent_body[i].size) )
610       {
611         h->m_error= NDB_LEH_INTERNAL_ERROR;
612         return -1;
613       }
614     } while (ndb_logevent_body[++i].type == dst->type);
615   }
616   else
617   {
618     if (!p.get("data", &val))
619     {
620       h->m_error= NDB_LEH_UNKNOWN_EVENT_VARIABLE;
621       return -1;
622     }
623     BaseString tmp(val);
624     Vector<BaseString> list;
625     tmp.split(list);
626     for (size_t j = 0; j<list.size(); j++)
627     {
628       dst->Data[j] = atoi(list[j].c_str());
629     }
630   }
631   return 1;
632 }
633 
634 extern "C"
ndb_logevent_get_latest_error(const NdbLogEventHandle h)635 int ndb_logevent_get_latest_error(const NdbLogEventHandle h)
636 {
637   return h->m_error;
638 }
639 
640 extern "C"
ndb_logevent_get_latest_error_msg(const NdbLogEventHandle h)641 const char *ndb_logevent_get_latest_error_msg(const NdbLogEventHandle h)
642 {
643   for (int i= 0; ndb_logevent_error_messages[i].msg; i++)
644     if (ndb_logevent_error_messages[i].code == h->m_error)
645       return ndb_logevent_error_messages[i].msg;
646   return "<unknown error msg>";
647 }
648