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