1 #include "opensrf/generic_utils.h"
14 void get_timestamp( char buf_25chars[]) {
15 time_t epoch = time(NULL);
16 char* localtime = strdup( ctime( &epoch ) );
17 strcpy( buf_25chars, localtime );
18 buf_25chars[ strlen(localtime)-1] = '\0'; // remove newline
23 inline void* safe_malloc( int size ) {
24 void* ptr = (void*) malloc( size );
26 fatal_handler("safe_malloc(): Out of Memory" );
27 memset( ptr, 0, size );
31 // ---------------------------------------------------------------------------------
32 // Here we define how we want to handle various error levels.
33 // ---------------------------------------------------------------------------------
36 static FILE* log_file = NULL;
37 static int log_level = -1;
38 pthread_mutex_t mutex;
40 void log_free() { if( log_file != NULL ) fclose(log_file ); }
42 void fatal_handler( char* msg, ... ) {
52 if( log_level < LOG_ERROR )
55 pthread_mutex_lock( &(mutex) );
56 fprintf( log_file, "[%s %d] [%s] ", buf, pid, "ERR " );
59 vfprintf(log_file, msg, args);
62 fprintf(log_file, "\n");
64 pthread_mutex_unlock( &(mutex) );
68 /* also log to stderr for ERRORS*/
69 fprintf( stderr, "[%s %d] [%s] ", buf, pid, "ERR " );
71 vfprintf(stderr, msg, args);
73 fprintf( stderr, "\n" );
78 void warning_handler( char* msg, ... ) {
88 if( log_level < LOG_WARNING )
91 pthread_mutex_lock( &(mutex) );
92 fprintf( log_file, "[%s %d] [%s] ", buf, pid, "WARN" );
95 vfprintf(log_file, msg, args);
98 fprintf(log_file, "\n");
100 pthread_mutex_unlock( &(mutex) );
104 fprintf( stderr, "[%s %d] [%s] ", buf, pid, "WARN" );
106 vfprintf(stderr, msg, args);
108 fprintf( stderr, "\n" );
113 void info_handler( char* msg, ... ) {
116 memset( buf, 0, 25 );
117 get_timestamp( buf );
118 pid_t pid = getpid();
123 if( log_level < LOG_INFO )
125 pthread_mutex_lock( &(mutex) );
126 fprintf( log_file, "[%s %d] [%s] ", buf, pid, "INFO" );
129 vfprintf(log_file, msg, args);
132 fprintf(log_file, "\n");
134 pthread_mutex_unlock( &(mutex) );
138 fprintf( stderr, "[%s %d] [%s] ", buf, pid, "INFO" );
140 vfprintf(stderr, msg, args);
142 fprintf( stderr, "\n" );
149 void debug_handler( char* msg, ... ) {
152 memset( buf, 0, 25 );
153 get_timestamp( buf );
154 pid_t pid = getpid();
159 if( log_level < LOG_DEBUG )
162 pthread_mutex_lock( &(mutex) );
163 fprintf( log_file, "[%s %d] [%s] ", buf, pid, "DEBG" );
166 vfprintf(log_file, msg, args);
169 fprintf(log_file, "\n");
171 pthread_mutex_unlock( &(mutex) );
175 fprintf( stderr, "[%s %d] [%s] ", buf, pid, "DEBG" );
177 vfprintf(stderr, msg, args);
179 fprintf( stderr, "\n" );
188 if( log_level != -1 )
192 pthread_mutex_init( &(mutex), NULL );
194 /* load the log level setting if we haven't already */
196 if( conf_reader == NULL ) {
198 //fprintf( stderr, "No config file specified" );
201 char* log_level_str = config_value( "//log/level");
202 if( log_level_str == NULL ) {
203 // fprintf( stderr, "No log level specified" );
206 log_level = atoi(log_level_str);
209 /* see if we have a log file yet */
210 char* f = config_value("//log/file");
213 // fprintf( stderr, "No log file specified" );
217 log_file = fopen( f, "a" );
218 if( log_file == NULL ) {
219 fprintf( stderr, "Unable to open log file %s for appending\n", f );
229 // ---------------------------------------------------------------------------------
230 // Flesh out a ubiqitous growing string buffer
231 // ---------------------------------------------------------------------------------
233 growing_buffer* buffer_init(int num_initial_bytes) {
235 if( num_initial_bytes > BUFFER_MAX_SIZE ) {
240 size_t len = sizeof(growing_buffer);
242 growing_buffer* gb = (growing_buffer*) safe_malloc(len);
244 gb->n_used = 0;/* nothing stored so far */
245 gb->size = num_initial_bytes;
246 gb->buf = (char *) safe_malloc(gb->size + 1);
251 int buffer_add(growing_buffer* gb, char* data) {
254 if( ! gb || ! data ) { return 0; }
255 int data_len = strlen( data );
257 if( data_len == 0 ) { return 0; }
258 int total_len = data_len + gb->n_used;
260 while( total_len >= gb->size ) {
264 if( gb->size > BUFFER_MAX_SIZE ) {
265 warning_handler( "Buffer reached MAX_SIZE of %d", BUFFER_MAX_SIZE );
270 char* new_data = (char*) safe_malloc( gb->size );
272 strcpy( new_data, gb->buf );
276 strcat( gb->buf, data );
277 gb->n_used = total_len;
282 int buffer_reset( growing_buffer *gb){
283 if( gb == NULL ) { return 0; }
284 if( gb->buf == NULL ) { return 0; }
285 memset( gb->buf, 0, gb->size );
290 int buffer_free( growing_buffer* gb ) {
298 char* buffer_data( growing_buffer *gb) {
299 return strdup( gb->buf );
306 // ---------------------------------------------------------------------------------
308 // ---------------------------------------------------------------------------------
311 // ---------------------------------------------------------------------------------
312 // Allocate and build the conf_reader. This only has to happen once in a given
313 // system. Repeated calls are ignored.
314 // ---------------------------------------------------------------------------------
315 void config_reader_init( char* config_file ) {
316 if( conf_reader == NULL ) {
318 if( config_file == NULL || strlen(config_file) == 0 ) {
319 fatal_handler( "config_reader_init(): No config file specified" );
323 size_t len = sizeof( config_reader );
324 conf_reader = (config_reader*) safe_malloc( len );
326 conf_reader->config_doc = xmlParseFile( config_file );
327 conf_reader->xpathCx = xmlXPathNewContext( conf_reader->config_doc );
328 if( conf_reader->xpathCx == NULL ) {
329 fatal_handler( "config_reader_init(): Unable to create xpath context");
335 char* config_value( const char* xp_query, ... ) {
337 if( conf_reader == NULL || xp_query == NULL ) {
338 fatal_handler( "config_value(): NULL conf_reader or NULL param(s)" );
342 int slen = strlen(xp_query) + 512;/* this is unsafe ... */
343 char xpath_query[ slen ];
344 memset( xpath_query, 0, slen );
346 va_start(va_args, xp_query);
347 vsprintf(xpath_query, xp_query, va_args);
352 int len = strlen(xpath_query) + 100;
353 char alert_buffer[len];
354 memset( alert_buffer, 0, len );
356 // build the xpath object
357 xmlXPathObjectPtr xpathObj = xmlXPathEvalExpression( BAD_CAST xpath_query, conf_reader->xpathCx );
359 if( xpathObj == NULL ) {
360 sprintf( alert_buffer, "Could not build xpath object: %s", xpath_query );
361 fatal_handler( alert_buffer );
366 if( xpathObj->type == XPATH_NODESET ) {
368 // ----------------------------------------------------------------------------
369 // Grab nodeset from xpath query, then first node, then first text node and
370 // finaly the text node's value
371 // ----------------------------------------------------------------------------
372 xmlNodeSet* node_list = xpathObj->nodesetval;
373 if( node_list == NULL ) {
374 sprintf( alert_buffer, "Could not build xpath object: %s", xpath_query );
375 warning_handler(alert_buffer);
379 if( node_list->nodeNr == 0 ) {
380 sprintf( alert_buffer, "Config XPATH query returned 0 results: %s", xpath_query );
381 warning_handler(alert_buffer);
386 xmlNodePtr element_node = *(node_list)->nodeTab;
387 if( element_node == NULL ) {
388 sprintf( alert_buffer, "Config XPATH query returned 0 results: %s", xpath_query );
389 warning_handler(alert_buffer);
393 xmlNodePtr text_node = element_node->children;
394 if( text_node == NULL ) {
395 sprintf( alert_buffer, "Config variable has no value: %s", xpath_query );
396 warning_handler(alert_buffer);
400 val = text_node->content;
402 sprintf( alert_buffer, "Config variable has no value: %s", xpath_query );
403 warning_handler(alert_buffer);
409 sprintf( alert_buffer, "Xpath evaluation failed: %s", xpath_query );
410 warning_handler(alert_buffer);
414 char* value = strdup(val);
415 if( value == NULL ) { warning_handler( "config_value(): Empty config value or Out of Memory!" ); }
417 // Free XPATH structures
418 if( xpathObj != NULL ) xmlXPathFreeObject( xpathObj );
424 void config_reader_free() {
425 if( conf_reader == NULL ) { return; }
426 xmlXPathFreeContext( conf_reader->xpathCx );
427 xmlFreeDoc( conf_reader->config_doc );