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