📄 trace.c
字号:
/* trace.c Subroutines that support tracing of OMAPI wire transactions and provide a mechanism for programs using OMAPI to trace their own transactions... *//* * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC") * Copyright (c) 2001-2003 by Internet Software Consortium * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * * Internet Systems Consortium, Inc. * 950 Charter Street * Redwood City, CA 94063 * <info@isc.org> * http://www.isc.org/ * * This software has been written for Internet Systems Consortium * by Ted Lemon, as part of a project for Nominum, Inc. To learn more * about Internet Systems Consortium, see http://www.isc.org/. To * learn more about Nominum, Inc., see ``http://www.nominum.com''. */#include <omapip/omapip_p.h>#if defined (TRACING)void (*trace_set_time_hook) (u_int32_t);static int tracing_stopped;static int traceoutfile;static int traceindex;static trace_type_t **trace_types;static int trace_type_count;static int trace_type_max;static trace_type_t *new_trace_types;static FILE *traceinfile;static tracefile_header_t tracefile_header;static int trace_playback_flag;trace_type_t trace_time_marker;#if defined (DEBUG_MEMORY_LEAKAGE) || defined (DEBUG_MEMORY_LEAKAGE_ON_EXIT)extern omapi_array_t *trace_listeners;extern omapi_array_t *omapi_connections;void trace_free_all (){ trace_type_t *tp; int i; tp = new_trace_types; while (tp) { new_trace_types = tp -> next; if (tp -> name) { dfree (tp -> name, MDL); tp -> name = (char *)0; } dfree (tp, MDL); tp = new_trace_types; } for (i = 0; i < trace_type_count; i++) { if (trace_types [i]) { if (trace_types [i] -> name) dfree (trace_types [i] -> name, MDL); dfree (trace_types [i], MDL); } } dfree (trace_types, MDL); trace_types = (trace_type_t **)0; trace_type_count = trace_type_max = 0; omapi_array_free (&trace_listeners, MDL); omapi_array_free (&omapi_connections, MDL);}#endifstatic isc_result_t trace_type_record (trace_type_t *, unsigned, const char *, int);int trace_playback (){ return trace_playback_flag;}int trace_record (){ if (traceoutfile && !tracing_stopped) return 1; return 0;}isc_result_t trace_init (void (*set_time) (u_int32_t), const char *file, int line){ trace_type_t *root_type; static int root_setup = 0; if (root_setup) return ISC_R_SUCCESS; trace_set_time_hook = set_time; root_type = trace_type_register ("trace-index-mapping", (void *)0, trace_index_map_input, trace_index_stop_tracing, file, line); if (!root_type) return ISC_R_UNEXPECTED; if (new_trace_types == root_type) new_trace_types = new_trace_types -> next; root_type -> index = 0; trace_type_stash (root_type); root_setup = 1; return ISC_R_SUCCESS;}isc_result_t trace_begin (const char *filename, const char *file, int line){ tracefile_header_t tfh; int status; trace_type_t *tptr, *next; isc_result_t result; if (traceoutfile) { log_error ("%s(%d): trace_begin called twice", file, line); return ISC_R_INVALIDARG; } traceoutfile = open (filename, O_CREAT | O_WRONLY | O_EXCL, 0644); if (traceoutfile < 0) { log_error ("%s(%d): trace_begin: %s: %m", file, line, filename); return ISC_R_UNEXPECTED; }#if defined (HAVE_SETFD) if (fcntl (traceoutfile, F_SETFD, 1) < 0) log_error ("Can't set close-on-exec on %s: %m", filename);#endif tfh.magic = htonl (TRACEFILE_MAGIC); tfh.version = htonl (TRACEFILE_VERSION); tfh.hlen = htonl (sizeof (tracefile_header_t)); tfh.phlen = htonl (sizeof (tracepacket_t)); status = write (traceoutfile, &tfh, sizeof tfh); if (status < 0) { log_error ("%s(%d): trace_begin write failed: %m", file, line); return ISC_R_UNEXPECTED; } else if (status != sizeof tfh) { log_error ("%s(%d): trace_begin: short write (%d:%ld)", file, line, status, (long)(sizeof tfh)); trace_stop (); return ISC_R_UNEXPECTED; } /* Stash all the types that have already been set up. */ if (new_trace_types) { next = new_trace_types; new_trace_types = (trace_type_t *)0; for (tptr = next; tptr; tptr = next) { next = tptr -> next; if (tptr -> index != 0) { result = (trace_type_record (tptr, strlen (tptr -> name), file, line)); if (result != ISC_R_SUCCESS) return status; } } } return ISC_R_SUCCESS;}isc_result_t trace_write_packet (trace_type_t *ttype, unsigned length, const char *buf, const char *file, int line){ trace_iov_t iov; iov.buf = buf; iov.len = length; return trace_write_packet_iov (ttype, 1, &iov, file, line);}isc_result_t trace_write_packet_iov (trace_type_t *ttype, int count, trace_iov_t *iov, const char *file, int line){ tracepacket_t tmp; int status; int i; int length; /* Really shouldn't get called here, but it may be hard to turn off tracing midstream if the trace file write fails or something. */ if (tracing_stopped) return 0; if (!ttype) { log_error ("%s(%d): trace_write_packet with null trace type", file ? file : "<unknown file>", line); return ISC_R_INVALIDARG; } if (!traceoutfile) { log_error ("%s(%d): trace_write_packet with no tracefile.", file ? file : "<unknown file>", line); return ISC_R_INVALIDARG; } /* Compute the total length of the iov. */ length = 0; for (i = 0; i < count; i++) length += iov [i].len; /* We have to swap out the data, because it may be read back on a machine of different endianness. */ tmp.type_index = htonl (ttype -> index); tmp.when = htonl (time ((time_t *)0)); /* XXX */ tmp.length = htonl (length); status = write (traceoutfile, &tmp, sizeof tmp); if (status < 0) { log_error ("%s(%d): trace_write_packet write failed: %m", file, line); return ISC_R_UNEXPECTED; } else if (status != sizeof tmp) { log_error ("%s(%d): trace_write_packet: short write (%d:%ld)", file, line, status, (long)(sizeof tmp)); trace_stop (); } for (i = 0; i < count; i++) { status = write (traceoutfile, iov [i].buf, iov [i].len); if (status < 0) { log_error ("%s(%d): %s write failed: %m", file, line, "trace_write_packet"); return ISC_R_UNEXPECTED; } else if (status != iov [i].len) { log_error ("%s(%d): %s: short write (%d:%d)", file, line, "trace_write_packet", status, length); trace_stop (); } } /* Write padding on the end of the packet to align the next packet to an 8-byte boundary. This is in case we decide to use mmap in some clever way later on. */ if (length % 8) { static char zero [] = { 0, 0, 0, 0, 0, 0, 0 }; unsigned padl = 8 - (length % 8); status = write (traceoutfile, zero, padl); if (status < 0) { log_error ("%s(%d): trace_write_packet write failed: %m", file, line); return ISC_R_UNEXPECTED; } else if (status != padl) { log_error ("%s(%d): trace_write_packet: short write (%d:%d)", file, line, status, padl); trace_stop (); } } return ISC_R_SUCCESS;}void trace_type_stash (trace_type_t *tptr){ trace_type_t **vec; int delta; if (trace_type_max <= tptr -> index) { delta = tptr -> index - trace_type_max + 10; vec = dmalloc (((trace_type_max + delta) * sizeof (trace_type_t *)), MDL); if (!vec) return; memset (&vec [trace_type_max], 0, (sizeof (trace_type_t *)) * delta); trace_type_max += delta; if (trace_types) { memcpy (vec, trace_types, trace_type_count * sizeof (trace_type_t *)); dfree (trace_types, MDL); } trace_types = vec; } trace_types [tptr -> index] = tptr; if (tptr -> index >= trace_type_count) trace_type_count = tptr -> index + 1;}trace_type_t *trace_type_register (const char *name, void *baggage, void (*have_packet) (trace_type_t *, unsigned, char *), void (*stop_tracing) (trace_type_t *), const char *file, int line){ trace_type_t *ttmp, *tptr; unsigned slen = strlen (name); isc_result_t status; ttmp = dmalloc (sizeof *ttmp, file, line); if (!ttmp) return ttmp; ttmp -> index = -1; ttmp -> name = dmalloc (slen + 1, file, line); if (!ttmp -> name) { dfree (ttmp, file, line); return (trace_type_t *)0; } strcpy (ttmp -> name, name); ttmp -> have_packet = have_packet; ttmp -> stop_tracing = stop_tracing; if (traceoutfile) { status = trace_type_record (ttmp, slen, file, line); if (status != ISC_R_SUCCESS) { dfree (ttmp -> name, file, line); dfree (ttmp, file, line); return (trace_type_t *)0; } } else { ttmp -> next = new_trace_types; new_trace_types = ttmp; } return ttmp;} static isc_result_t trace_type_record (trace_type_t *ttmp, unsigned slen, const char *file, int line){ trace_index_mapping_t *tim; isc_result_t status; tim = dmalloc (slen + TRACE_INDEX_MAPPING_SIZE, file, line); if (!tim) return ISC_R_NOMEMORY; ttmp -> index = ++traceindex; trace_type_stash (ttmp); tim -> index = htonl (ttmp -> index); memcpy (tim -> name, ttmp -> name, slen); status = trace_write_packet (trace_types [0],
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -