]> git.evergreen-ils.org Git - OpenSRF.git/blob - src/libtransport/generic_utils.c
added 'named' configs.
[OpenSRF.git] / src / libtransport / generic_utils.c
1 #include "opensrf/generic_utils.h"
2 #include <stdio.h>
3 #include "pthread.h"
4 #include <sys/timeb.h>
5
6 void get_timestamp( char buf_36chars[]) {
7
8         struct timeb tb;
9         ftime(&tb);
10         char* localtime = strdup( ctime( &(tb.time) ) );
11         char mil[4];
12         memset(mil,0,4);
13         sprintf(mil," (%d)",tb.millitm);
14         strcpy( buf_36chars, localtime );
15         buf_36chars[ strlen(localtime)-1] = '\0'; // remove newline
16         strcat(buf_36chars,mil);
17         free(localtime);
18 }
19
20
21 inline void* safe_malloc( int size ) {
22         void* ptr = (void*) malloc( size );
23         if( ptr == NULL ) 
24                 fatal_handler("safe_malloc(): Out of Memory" );
25         memset( ptr, 0, size );
26         return ptr;
27 }
28
29 // ---------------------------------------------------------------------------------
30 // Here we define how we want to handle various error levels.
31 // ---------------------------------------------------------------------------------
32
33
34 static FILE* log_file = NULL;
35 static int log_level = -1;
36 static int logging = 0;
37 pthread_mutex_t mutex;
38
39 void log_free() { if( log_file != NULL ) fclose(log_file ); }
40
41 void fatal_handler( char* msg, ... ) {
42                 
43         char buf[36];
44         memset( buf, 0, 36 );
45         get_timestamp( buf );
46         pid_t  pid = getpid();
47         va_list args;
48
49         if( logging ) {
50
51                 if( log_level < LOG_ERROR )
52                         return;
53
54                 pthread_mutex_lock( &(mutex) );
55                 fprintf( log_file, "[%s %d] [%s] ", buf, pid, "ERR " );
56         
57                 va_start(args, msg);
58                 vfprintf(log_file, msg, args);
59                 va_end(args);
60         
61                 fprintf(log_file, "\n");
62                 fflush( log_file );
63                 pthread_mutex_unlock( &(mutex) );
64
65         }
66         
67         /* also log to stderr  for ERRORS*/
68         fprintf( stderr, "[%s %d] [%s] ", buf, pid, "ERR " );
69         va_start(args, msg);
70         vfprintf(stderr, msg, args);
71         va_end(args);
72         fprintf( stderr, "\n" );
73
74         exit(99);
75 }
76
77 void warning_handler( char* msg, ... ) {
78
79         char buf[36];
80         memset( buf, 0, 36 );
81         get_timestamp( buf );
82         pid_t  pid = getpid();
83         va_list args;
84         
85         if(logging) {
86
87                 if( log_level < LOG_WARNING )
88                         return;
89
90                 pthread_mutex_lock( &(mutex) );
91                 fprintf( log_file, "[%s %d] [%s] ", buf, pid, "WARN" );
92         
93                 va_start(args, msg);
94                 vfprintf(log_file, msg, args);
95                 va_end(args);
96         
97                 fprintf(log_file, "\n");
98                 fflush( log_file );
99                 pthread_mutex_unlock( &(mutex) );
100
101         } else {
102
103                 fprintf( stderr, "[%s %d] [%s] ", buf, pid, "WARN" );
104                 va_start(args, msg);
105                 vfprintf(stderr, msg, args);
106                 va_end(args);
107                 fprintf( stderr, "\n" );
108         }
109
110 }
111
112 void info_handler( char* msg, ... ) {
113
114         char buf[36];
115         memset( buf, 0, 36 );
116         get_timestamp( buf );
117         pid_t  pid = getpid();
118         va_list args;
119
120         if(logging) {
121
122                 if( log_level < LOG_INFO )
123                         return;
124                 pthread_mutex_lock( &(mutex) );
125                 fprintf( log_file, "[%s %d] [%s] ", buf, pid, "INFO" );
126
127                 va_start(args, msg);
128                 vfprintf(log_file, msg, args);
129                 va_end(args);
130         
131                 fprintf(log_file, "\n");
132                 fflush( log_file );
133                 pthread_mutex_unlock( &(mutex) );
134
135         } else {
136
137                 fprintf( stderr, "[%s %d] [%s] ", buf, pid, "INFO" );
138                 va_start(args, msg);
139                 vfprintf(stderr, msg, args);
140                 va_end(args);
141                 fprintf( stderr, "\n" );
142                 fflush(stderr);
143
144         }
145 }
146
147
148 void debug_handler( char* msg, ... ) {
149
150         char buf[36];
151         memset( buf, 0, 36 );
152         get_timestamp( buf );
153         pid_t  pid = getpid();
154         va_list args;
155         
156         if(logging) {
157
158                 if( log_level < LOG_DEBUG )
159                         return;
160
161                 pthread_mutex_lock( &(mutex) );
162                 fprintf( log_file, "[%s %d] [%s] ", buf, pid, "DEBG" );
163         
164                 va_start(args, msg);
165                 vfprintf(log_file, msg, args);
166                 va_end(args);
167         
168                 fprintf(log_file, "\n");
169                 fflush( log_file );
170                 pthread_mutex_unlock( &(mutex) );
171
172         } else {
173
174                 fprintf( stderr, "[%s %d] [%s] ", buf, pid, "DEBG" );
175                 va_start(args, msg);
176                 vfprintf(stderr, msg, args);
177                 va_end(args);
178                 fprintf( stderr, "\n" );
179         }
180
181 }
182
183
184 int log_init( int llevel, char* lfile ) {
185
186
187         if( llevel < 1 ) {
188                 logging = 0;
189                 return 0;
190         }
191
192         log_level = llevel;
193         log_file = fopen( lfile, "a" );
194         if( log_file == NULL ) {
195                 fprintf( stderr, "Unable to open log file %s for appending\n", lfile );
196                 return 0;
197         }
198         logging = 1;
199         return 1;
200
201 }
202
203
204 // ---------------------------------------------------------------------------------
205 // Flesh out a ubiqitous growing string buffer
206 // ---------------------------------------------------------------------------------
207
208 growing_buffer* buffer_init(int num_initial_bytes) {
209
210         if( num_initial_bytes > BUFFER_MAX_SIZE ) {
211                 return NULL;
212         }
213
214
215         size_t len = sizeof(growing_buffer);
216
217         growing_buffer* gb = (growing_buffer*) safe_malloc(len);
218
219         gb->n_used = 0;/* nothing stored so far */
220         gb->size = num_initial_bytes;
221         gb->buf = (char *) safe_malloc(gb->size + 1);
222
223         return gb;
224 }
225
226 int buffer_add(growing_buffer* gb, char* data) {
227
228
229         if( ! gb || ! data  ) { return 0; }
230         int data_len = strlen( data );
231
232         if( data_len == 0 ) { return 0; }
233         int total_len = data_len + gb->n_used;
234
235         while( total_len >= gb->size ) {
236                 gb->size *= 2;
237         }
238
239         if( gb->size > BUFFER_MAX_SIZE ) {
240                 warning_handler( "Buffer reached MAX_SIZE of %d", BUFFER_MAX_SIZE );
241                 buffer_free( gb );
242                 return 0;
243         }
244
245         char* new_data = (char*) safe_malloc( gb->size );
246
247         strcpy( new_data, gb->buf );
248         free( gb->buf );
249         gb->buf = new_data;
250
251         strcat( gb->buf, data );
252         gb->n_used = total_len;
253         return total_len;
254 }
255
256
257 int buffer_reset( growing_buffer *gb){
258         if( gb == NULL ) { return 0; }
259         if( gb->buf == NULL ) { return 0; }
260         memset( gb->buf, 0, gb->size );
261         gb->n_used = 0;
262         return 1;
263 }
264
265 int buffer_free( growing_buffer* gb ) {
266         if( gb == NULL ) 
267                 return 0;
268         free( gb->buf );
269         free( gb );
270         return 1;
271 }
272
273 char* buffer_data( growing_buffer *gb) {
274         return strdup( gb->buf );
275 }
276
277
278
279
280
281 // ---------------------------------------------------------------------------------
282 // Config module
283 // ---------------------------------------------------------------------------------
284
285
286 // ---------------------------------------------------------------------------------
287 // Allocate and build the conf_reader.  This only has to happen once in a given
288 // system.  Repeated calls are ignored.
289 // ---------------------------------------------------------------------------------
290 /*
291 void config_reader_init( char* config_file ) {
292         if( conf_reader == NULL ) {
293
294                 if( config_file == NULL || strlen(config_file) == 0 ) {
295                         fatal_handler( "config_reader_init(): No config file specified" );
296                         return;
297                 }
298
299                 size_t len = sizeof( config_reader );
300                 conf_reader = (config_reader*) safe_malloc( len );
301
302                 conf_reader->config_doc = xmlParseFile( config_file ); 
303                 conf_reader->xpathCx = xmlXPathNewContext( conf_reader->config_doc );
304                 if( conf_reader->xpathCx == NULL ) {
305                         fatal_handler( "config_reader_init(): Unable to create xpath context");
306                         return;
307                 }
308         }
309 }
310 */
311
312 void config_reader_init( char* name, char* config_file ) {
313
314         if( name == NULL || config_file == NULL || strlen(config_file) == 0 ) {
315                 fatal_handler( "config_reader_init(): No config file specified" );
316                 return;
317         }
318
319         config_reader* reader = 
320                 (config_reader*) safe_malloc(sizeof(config_reader));
321
322         reader->config_doc = xmlParseFile( config_file ); 
323         reader->xpathCx = xmlXPathNewContext( reader->config_doc );
324         reader->name = strdup(name);
325         reader->next = NULL;
326
327         if( reader->xpathCx == NULL ) {
328                 fprintf( stderr, "config_reader_init(): Unable to create xpath context\n");
329                 return;
330         }
331
332         if( conf_reader == NULL ) {
333                 conf_reader = reader;
334         } else {
335                 config_reader* tmp = conf_reader;
336                 conf_reader = reader;
337                 reader->next = tmp;
338         }
339 }
340
341
342 char* config_value( const char* config_name, const char* xp_query, ... ) {
343
344         if( conf_reader == NULL || xp_query == NULL ) {
345                 fatal_handler( "config_value(): NULL conf_reader or NULL param(s)" );
346                 return NULL;
347         }
348
349         config_reader* reader = conf_reader;
350         while( reader != NULL ) {
351                 if( !strcmp(reader->name, config_name)) 
352                         break;
353                 reader = reader->next;
354         }
355
356         if( reader == NULL ) {
357                 fprintf(stderr, "No Config file with name %s\n", config_name );
358                 return NULL;
359         }
360
361         int slen = strlen(xp_query) + 512;/* this is unsafe ... */
362         char xpath_query[ slen ]; 
363         memset( xpath_query, 0, slen );
364         va_list va_args;
365         va_start(va_args, xp_query);
366         vsprintf(xpath_query, xp_query, va_args);
367         va_end(va_args);
368
369
370         char* val;
371         int len = strlen(xpath_query) + 100;
372         char alert_buffer[len];
373         memset( alert_buffer, 0, len );
374
375         // build the xpath object
376         xmlXPathObjectPtr xpathObj = xmlXPathEvalExpression( BAD_CAST xpath_query, reader->xpathCx );
377
378         if( xpathObj == NULL ) {
379                 sprintf( alert_buffer, "Could not build xpath object: %s", xpath_query );
380                 fatal_handler( alert_buffer );
381                 return NULL;
382         }
383
384
385         if( xpathObj->type == XPATH_NODESET ) {
386
387                 // ----------------------------------------------------------------------------
388                 // Grab nodeset from xpath query, then first node, then first text node and 
389                 // finaly the text node's value
390                 // ----------------------------------------------------------------------------
391                 xmlNodeSet* node_list = xpathObj->nodesetval;
392                 if( node_list == NULL ) {
393                         sprintf( alert_buffer, "Could not build xpath object: %s", xpath_query );
394                         warning_handler(alert_buffer);
395                         return NULL;
396                 }
397
398                 if( node_list->nodeNr == 0 ) {
399                         sprintf( alert_buffer, "Config XPATH query  returned 0 results: %s", xpath_query );
400                         warning_handler(alert_buffer);
401                         return NULL;
402                 }
403
404
405                 xmlNodePtr element_node = *(node_list)->nodeTab;
406                 if( element_node == NULL ) {
407                         sprintf( alert_buffer, "Config XPATH query  returned 0 results: %s", xpath_query );
408                         warning_handler(alert_buffer);
409                         return NULL;
410                 }
411
412                 xmlNodePtr text_node = element_node->children;
413                 if( text_node == NULL ) {
414                         sprintf( alert_buffer, "Config variable has no value: %s", xpath_query );
415                         warning_handler(alert_buffer);
416                         return NULL;
417                 }
418
419                 val = text_node->content;
420                 if( val == NULL ) {
421                         sprintf( alert_buffer, "Config variable has no value: %s", xpath_query );
422                         warning_handler(alert_buffer);
423                         return NULL;
424                 }
425
426
427         } else { 
428                 sprintf( alert_buffer, "Xpath evaluation failed: %s", xpath_query );
429                 warning_handler(alert_buffer);
430                 return NULL;
431         }
432
433         char* value = strdup(val);
434         if( value == NULL ) { warning_handler( "config_value(): Empty config value or Out of Memory!" ); }
435
436         // Free XPATH structures
437         if( xpathObj != NULL ) xmlXPathFreeObject( xpathObj );
438
439         return value;
440 }
441
442
443 void config_reader_free() {
444         while( conf_reader != NULL ) {
445                 xmlXPathFreeContext( conf_reader->xpathCx );
446                 xmlFreeDoc( conf_reader->config_doc );
447                 free(conf_reader->name );
448                 config_reader* tmp = conf_reader->next;
449                 free( conf_reader );
450                 conf_reader = tmp;
451         }
452 }