/* +----------------------------------------------------------------------+ | eAccelerator project | +----------------------------------------------------------------------+ | Copyright (c) 2004 - 2006 eAccelerator | | http://eaccelerator.net | +----------------------------------------------------------------------+ | This program is free software; you can redistribute it and/or | | modify it under the terms of the GNU General Public License | | as published by the Free Software Foundation; either version 2 | | of the License, or (at your option) any later version. | | | | This program is distributed in the hope that it will be useful, | | but WITHOUT ANY WARRANTY; without even the implied warranty of | | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | | GNU General Public License for more details. | | | | You should have received a copy of the GNU General Public License | | along with this program; if not, write to the Free Software | | Foundation, Inc., 59 Temple Place - Suite 330, Boston, | | MA 02111-1307, USA. | | | | A copy is availble at http://www.gnu.org/copyleft/gpl.txt | +----------------------------------------------------------------------+ $Id: debug.c 176 2006-03-05 12:18:54Z bart $ */ #include "eaccelerator.h" #ifdef HAVE_EACCELERATOR #include "debug.h" #include #include static FILE *F_fp = NULL; static int file_no = 0; long eaccelerator_debug = 0; /** * Init the debug system. This must be called before any debug * functions are used. */ void ea_debug_init (TSRMLS_D) { F_fp = fopen (EAG (eaccelerator_log_file), "a"); if (!F_fp) F_fp = stderr; file_no = fileno(F_fp); } /** * Close the debug system. */ void ea_debug_shutdown () { fflush (F_fp); if (F_fp != stderr) fclose (F_fp); F_fp = NULL; } /** * Print a log message that will be print when the debug level is * equal to EA_LOG. This function is always called even if ea isn't * compiled with DEBUG and the log level is not equal to EA_LOG. */ void ea_debug_log (char *format, ...) { if (eaccelerator_debug & EA_LOG) { char output_buf[512]; va_list args; va_start (args, format); vsnprintf (output_buf, sizeof (output_buf), format, args); va_end (args); if (F_fp != stderr) { EACCELERATOR_FLOCK(file_no, LOCK_EX); } fputs (output_buf, F_fp); fflush (F_fp); if (F_fp != stderr) { EACCELERATOR_FLOCK(file_no, LOCK_UN); } } } /** * Output an error message to stderr. This message are always printed * no matter what log level is used. */ void ea_debug_error (char *format, ...) { char output_buf[512]; va_list args; va_start (args, format); vsnprintf (output_buf, sizeof (output_buf), format, args); va_end (args); fputs (output_buf, stderr); fflush (stderr); } /* * All these functions aren't compiled when eA isn't compiled with DEBUG. They * are replaced with function with no body, so it's optimized away by the compiler. * Even if the debug level is ok. */ /** * Print a debug message */ void ea_debug_printf (long debug_level, char *format, ...) { if (eaccelerator_debug & debug_level) { char output_buf[512]; va_list args; va_start (args, format); vsnprintf (output_buf, sizeof (output_buf), format, args); va_end (args); if (F_fp != stderr) { EACCELERATOR_FLOCK(file_no, LOCK_EX); } fputs (output_buf, F_fp); fflush (F_fp); if (F_fp != stderr) { EACCELERATOR_FLOCK(file_no, LOCK_UN); } } } /** * Put a debug message */ void ea_debug_put (long debug_level, char *message) { if (debug_level & eaccelerator_debug) { if (F_fp != stderr) { EACCELERATOR_FLOCK(file_no, LOCK_EX); } fputs (message, F_fp); fflush (F_fp); if (F_fp != stderr) { EACCELERATOR_FLOCK(file_no, LOCK_UN); } } } /** * Print a binary message */ void ea_debug_binary_print (long debug_level, char *p, int len) { if (eaccelerator_debug & debug_level) { if (F_fp != stderr) { EACCELERATOR_FLOCK(file_no, LOCK_EX); } while (len--) { fputc (*p++, F_fp); } fputc ('\n', F_fp); fflush (F_fp); if (F_fp != stderr) { EACCELERATOR_FLOCK(file_no, LOCK_UN); } } } /** * Log a hashkey */ void ea_debug_log_hashkeys (char *p, HashTable * ht) { if (eaccelerator_debug & EA_LOG_HASHKEYS) { Bucket *b; int i = 0; b = ht->pListHead; if (F_fp != stderr) { EACCELERATOR_FLOCK(file_no, LOCK_EX); } fputs(p, F_fp); fflush(F_fp); while (b) { fprintf (F_fp, "[%d] ", i); ea_debug_binary_print (EA_LOG_HASHKEYS, b->arKey, b->nKeyLength); b = b->pListNext; i++; } if (F_fp != stderr) { EACCELERATOR_FLOCK(file_no, LOCK_UN); } } } /** * Pad the message with the current pad level. */ void ea_debug_pad (long debug_level TSRMLS_DC) { #ifdef DEBUG /* This ifdef is still req'd because xpad is N/A in a non-debug compile */ if (eaccelerator_debug & debug_level) { int i; if (F_fp != stderr) { EACCELERATOR_FLOCK(file_no, LOCK_EX); } i = EAG (xpad); while (i-- > 0) { fputc ('\t', F_fp); } if (F_fp != stderr) { EACCELERATOR_FLOCK(file_no, LOCK_UN); } } #endif } void ea_debug_start_time (struct timeval *tvstart) { gettimeofday (tvstart, NULL); } long ea_debug_elapsed_time (struct timeval *tvstart) { struct timeval tvend; int sec, usec; gettimeofday (&tvend, NULL); sec = tvend.tv_sec - tvstart->tv_sec; usec = tvend.tv_usec - tvstart->tv_usec; return sec * 1000000 + usec; } /* * This dumps a HashTable to debug output. Taken from zend_hash.c and slightly adapted. */ void ea_debug_hash_display(HashTable * ht) { Bucket *p; uint i; fprintf(F_fp, "ht->nTableSize: %d\n", ht->nTableSize); fprintf(F_fp, "ht->nNumOfElements: %d\n", ht->nNumOfElements); for (i = 0; i < ht->nTableSize; i++) { p = ht->arBuckets[i]; while (p != NULL) { fprintf(F_fp, "%s <==> 0x%lX\n", p->arKey, p->h); p = p->pNext; } } p = ht->pListTail; while (p != NULL) { fprintf(F_fp, "%s <==> 0x%lX\n", p->arKey, p->h); p = p->pListLast; } fflush(F_fp); } #endif /* #ifdef HAVE_EACCELERATOR */