1 #include "opensrf/generic_utils.h"
15 void get_timestamp( char buf_36chars[]) {
19 //time_t epoch = time(NULL);
20 char* localtime = strdup( ctime( &(tb.time) ) );
23 sprintf(mil," (%d)",tb.millitm);
24 strcpy( buf_36chars, localtime );
25 buf_36chars[ strlen(localtime)-1] = '\0'; // remove newline
26 strcat(buf_36chars,mil);
31 inline void* safe_malloc( int size ) {
32 void* ptr = (void*) malloc( size );
34 fatal_handler("safe_malloc(): Out of Memory" );
35 memset( ptr, 0, size );
39 // ---------------------------------------------------------------------------------
40 // Here we define how we want to handle various error levels.
41 // ---------------------------------------------------------------------------------
44 static FILE* log_file = NULL;
45 static int log_level = -1;
46 pthread_mutex_t mutex;
48 void log_free() { if( log_file != NULL ) fclose(log_file ); }
50 void fatal_handler( char* msg, ... ) {
60 if( log_level < LOG_ERROR )
63 pthread_mutex_lock( &(mutex) );
64 fprintf( log_file, "[%s %d] [%s] ", buf, pid, "ERR " );
67 vfprintf(log_file, msg, args);
70 fprintf(log_file, "\n");
72 pthread_mutex_unlock( &(mutex) );
76 /* also log to stderr for ERRORS*/
77 fprintf( stderr, "[%s %d] [%s] ", buf, pid, "ERR " );
79 vfprintf(stderr, msg, args);
81 fprintf( stderr, "\n" );
86 void warning_handler( char* msg, ... ) {
96 if( log_level < LOG_WARNING )
99 pthread_mutex_lock( &(mutex) );
100 fprintf( log_file, "[%s %d] [%s] ", buf, pid, "WARN" );
103 vfprintf(log_file, msg, args);
106 fprintf(log_file, "\n");
108 pthread_mutex_unlock( &(mutex) );
112 fprintf( stderr, "[%s %d] [%s] ", buf, pid, "WARN" );
114 vfprintf(stderr, msg, args);
116 fprintf( stderr, "\n" );
121 void info_handler( char* msg, ... ) {
124 memset( buf, 0, 36 );
125 get_timestamp( buf );
126 pid_t pid = getpid();
131 if( log_level < LOG_INFO )
133 pthread_mutex_lock( &(mutex) );
134 fprintf( log_file, "[%s %d] [%s] ", buf, pid, "INFO" );
137 vfprintf(log_file, msg, args);
140 fprintf(log_file, "\n");
142 pthread_mutex_unlock( &(mutex) );
146 fprintf( stderr, "[%s %d] [%s] ", buf, pid, "INFO" );
148 vfprintf(stderr, msg, args);
150 fprintf( stderr, "\n" );
157 void debug_handler( char* msg, ... ) {
160 memset( buf, 0, 36 );
161 get_timestamp( buf );
162 pid_t pid = getpid();
167 if( log_level < LOG_DEBUG )
170 pthread_mutex_lock( &(mutex) );
171 fprintf( log_file, "[%s %d] [%s] ", buf, pid, "DEBG" );
174 vfprintf(log_file, msg, args);
177 fprintf(log_file, "\n");
179 pthread_mutex_unlock( &(mutex) );
183 fprintf( stderr, "[%s %d] [%s] ", buf, pid, "DEBG" );
185 vfprintf(stderr, msg, args);
187 fprintf( stderr, "\n" );
196 if( log_level != -1 )
200 pthread_mutex_init( &(mutex), NULL );
202 /* load the log level setting if we haven't already */
204 if( conf_reader == NULL ) {
206 //fprintf( stderr, "No config file specified" );
209 char* log_level_str = config_value( "//log/level");
210 if( log_level_str == NULL ) {
211 // fprintf( stderr, "No log level specified" );
214 log_level = atoi(log_level_str);
217 /* see if we have a log file yet */
218 char* f = config_value("//log/file");
221 // fprintf( stderr, "No log file specified" );
225 log_file = fopen( f, "a" );
226 if( log_file == NULL ) {
227 fprintf( stderr, "Unable to open log file %s for appending\n", f );
237 // ---------------------------------------------------------------------------------
238 // Flesh out a ubiqitous growing string buffer
239 // ---------------------------------------------------------------------------------
241 growing_buffer* buffer_init(int num_initial_bytes) {
243 if( num_initial_bytes > BUFFER_MAX_SIZE ) {
248 size_t len = sizeof(growing_buffer);
250 growing_buffer* gb = (growing_buffer*) safe_malloc(len);
252 gb->n_used = 0;/* nothing stored so far */
253 gb->size = num_initial_bytes;
254 gb->buf = (char *) safe_malloc(gb->size + 1);
259 int buffer_add(growing_buffer* gb, char* data) {
262 if( ! gb || ! data ) { return 0; }
263 int data_len = strlen( data );
265 if( data_len == 0 ) { return 0; }
266 int total_len = data_len + gb->n_used;
268 while( total_len >= gb->size ) {
272 if( gb->size > BUFFER_MAX_SIZE ) {
273 warning_handler( "Buffer reached MAX_SIZE of %d", BUFFER_MAX_SIZE );
278 char* new_data = (char*) safe_malloc( gb->size );
280 strcpy( new_data, gb->buf );
284 strcat( gb->buf, data );
285 gb->n_used = total_len;
290 int buffer_reset( growing_buffer *gb){
291 if( gb == NULL ) { return 0; }
292 if( gb->buf == NULL ) { return 0; }
293 memset( gb->buf, 0, gb->size );
298 int buffer_free( growing_buffer* gb ) {
306 char* buffer_data( growing_buffer *gb) {
307 return strdup( gb->buf );
314 // ---------------------------------------------------------------------------------
316 // ---------------------------------------------------------------------------------
319 // ---------------------------------------------------------------------------------
320 // Allocate and build the conf_reader. This only has to happen once in a given
321 // system. Repeated calls are ignored.
322 // ---------------------------------------------------------------------------------
323 void config_reader_init( char* config_file ) {
324 if( conf_reader == NULL ) {
326 if( config_file == NULL || strlen(config_file) == 0 ) {
327 fatal_handler( "config_reader_init(): No config file specified" );
331 size_t len = sizeof( config_reader );
332 conf_reader = (config_reader*) safe_malloc( len );
334 conf_reader->config_doc = xmlParseFile( config_file );
335 conf_reader->xpathCx = xmlXPathNewContext( conf_reader->config_doc );
336 if( conf_reader->xpathCx == NULL ) {
337 fatal_handler( "config_reader_init(): Unable to create xpath context");
343 char* config_value( const char* xp_query, ... ) {
345 if( conf_reader == NULL || xp_query == NULL ) {
346 fatal_handler( "config_value(): NULL conf_reader or NULL param(s)" );
350 int slen = strlen(xp_query) + 512;/* this is unsafe ... */
351 char xpath_query[ slen ];
352 memset( xpath_query, 0, slen );
354 va_start(va_args, xp_query);
355 vsprintf(xpath_query, xp_query, va_args);
360 int len = strlen(xpath_query) + 100;
361 char alert_buffer[len];
362 memset( alert_buffer, 0, len );
364 // build the xpath object
365 xmlXPathObjectPtr xpathObj = xmlXPathEvalExpression( BAD_CAST xpath_query, conf_reader->xpathCx );
367 if( xpathObj == NULL ) {
368 sprintf( alert_buffer, "Could not build xpath object: %s", xpath_query );
369 fatal_handler( alert_buffer );
374 if( xpathObj->type == XPATH_NODESET ) {
376 // ----------------------------------------------------------------------------
377 // Grab nodeset from xpath query, then first node, then first text node and
378 // finaly the text node's value
379 // ----------------------------------------------------------------------------
380 xmlNodeSet* node_list = xpathObj->nodesetval;
381 if( node_list == NULL ) {
382 sprintf( alert_buffer, "Could not build xpath object: %s", xpath_query );
383 warning_handler(alert_buffer);
387 if( node_list->nodeNr == 0 ) {
388 sprintf( alert_buffer, "Config XPATH query returned 0 results: %s", xpath_query );
389 warning_handler(alert_buffer);
394 xmlNodePtr element_node = *(node_list)->nodeTab;
395 if( element_node == NULL ) {
396 sprintf( alert_buffer, "Config XPATH query returned 0 results: %s", xpath_query );
397 warning_handler(alert_buffer);
401 xmlNodePtr text_node = element_node->children;
402 if( text_node == NULL ) {
403 sprintf( alert_buffer, "Config variable has no value: %s", xpath_query );
404 warning_handler(alert_buffer);
408 val = text_node->content;
410 sprintf( alert_buffer, "Config variable has no value: %s", xpath_query );
411 warning_handler(alert_buffer);
417 sprintf( alert_buffer, "Xpath evaluation failed: %s", xpath_query );
418 warning_handler(alert_buffer);
422 char* value = strdup(val);
423 if( value == NULL ) { warning_handler( "config_value(): Empty config value or Out of Memory!" ); }
425 // Free XPATH structures
426 if( xpathObj != NULL ) xmlXPathFreeObject( xpathObj );
432 void config_reader_free() {
433 if( conf_reader == NULL ) { return; }
434 xmlXPathFreeContext( conf_reader->xpathCx );
435 xmlFreeDoc( conf_reader->config_doc );