~ubuntu-branches/ubuntu/utopic/gridengine/utopic

« back to all changes in this revision

Viewing changes to source/libs/uti/sge_log.c

  • Committer: Bazaar Package Importer
  • Author(s): Mark Hymers
  • Date: 2008-06-25 22:36:13 UTC
  • Revision ID: james.westby@ubuntu.com-20080625223613-tvd9xlhuoct9kyhm
Tags: upstream-6.2~beta2
ImportĀ upstreamĀ versionĀ 6.2~beta2

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*___INFO__MARK_BEGIN__*/
 
2
/*************************************************************************
 
3
 * 
 
4
 *  The Contents of this file are made available subject to the terms of
 
5
 *  the Sun Industry Standards Source License Version 1.2
 
6
 * 
 
7
 *  Sun Microsystems Inc., March, 2001
 
8
 * 
 
9
 * 
 
10
 *  Sun Industry Standards Source License Version 1.2
 
11
 *  =================================================
 
12
 *  The contents of this file are subject to the Sun Industry Standards
 
13
 *  Source License Version 1.2 (the "License"); You may not use this file
 
14
 *  except in compliance with the License. You may obtain a copy of the
 
15
 *  License at http://gridengine.sunsource.net/Gridengine_SISSL_license.html
 
16
 * 
 
17
 *  Software provided under this License is provided on an "AS IS" basis,
 
18
 *  WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
 
19
 *  WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
 
20
 *  MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
 
21
 *  See the License for the specific provisions governing your rights and
 
22
 *  obligations concerning the Software.
 
23
 * 
 
24
 *   The Initial Developer of the Original Code is: Sun Microsystems, Inc.
 
25
 * 
 
26
 *   Copyright: 2001 by Sun Microsystems, Inc.
 
27
 * 
 
28
 *   All Rights Reserved.
 
29
 * 
 
30
 ************************************************************************/
 
31
/*___INFO__MARK_END__*/
 
32
 
 
33
#include "sge_log.h"
 
34
 
 
35
#include <fcntl.h>
 
36
#include <string.h>
 
37
#include <stdio.h>
 
38
#include <pthread.h>
 
39
#include <sys/types.h>
 
40
#include <sys/stat.h>
 
41
 
 
42
#include "sge.h"
 
43
#include "sge_time.h"
 
44
#include "sge_dstring.h"
 
45
#include "sgermon.h"
 
46
#include "sge_prog.h"
 
47
#include "sge_uidgid.h"
 
48
#include "sge_mtutil.h"
 
49
#include "gdi/sge_gdi_ctx.h"
 
50
 
 
51
#include "msg_utilib.h"
 
52
 
 
53
 
 
54
typedef struct {
 
55
   pthread_mutex_t  mutex;
 
56
   char*            log_file;
 
57
   u_long32         log_level;
 
58
   int              log_as_admin_user;
 
59
   int              verbose;
 
60
   int              gui_log;
 
61
} log_state_t;
 
62
 
 
63
typedef struct {
 
64
   char  log_buffer[4 * MAX_STRING_SIZE]; /* a.k.a. SGE_EVENT */
 
65
} log_buffer_t;
 
66
 
 
67
typedef struct {
 
68
   sge_gdi_ctx_class_t *context;
 
69
} log_context_t;
 
70
 
 
71
 
 
72
static log_state_t Log_State = {PTHREAD_MUTEX_INITIALIZER, TMP_ERR_FILE_SNBU, LOG_WARNING, 0, 1, 1};
 
73
 
 
74
static pthread_once_t log_buffer_once = PTHREAD_ONCE_INIT;
 
75
static pthread_key_t  log_buffer_key;
 
76
 
 
77
static pthread_once_t log_context_once = PTHREAD_ONCE_INIT;
 
78
static pthread_key_t  log_context_key;
 
79
 
 
80
static void log_buffer_once_init(void);
 
81
static void log_context_once_init(void);
 
82
 
 
83
static void log_buffer_destroy(void* theState);
 
84
static log_buffer_t* log_buffer_getspecific(void);
 
85
 
 
86
static void log_context_destroy(void* theState);
 
87
static log_context_t* log_context_getspecific(void);
 
88
static sge_gdi_ctx_class_t* log_state_get_log_context(void);
 
89
 
 
90
 
 
91
static void sge_do_log(u_long32 prog_number,
 
92
                       const char *progname,
 
93
                       const char *unqualified_hostname,
 
94
                       int aLevel, 
 
95
                       const char* aMessage); 
 
96
 
 
97
static sge_gdi_ctx_class_t *log_get_log_context(void);
 
98
static void log_set_log_context(sge_gdi_ctx_class_t *theCtx);
 
99
 
 
100
/****** uti/log/log_get_log_buffer() ******************************************
 
101
*  NAME
 
102
*     log_get_log_buffer() -- Return a buffer that can be used to build logging 
 
103
*                                   strings
 
104
*
 
105
*  SYNOPSIS
 
106
*     char *log_get_log_buffer(void) 
 
107
*
 
108
*  FUNCTION
 
109
*     Return a buffer that can be used to build logging strings
 
110
*
 
111
*  RESULT
 
112
*     char * 
 
113
*
 
114
******************************************************************************/
 
115
char *log_get_log_buffer(void)
 
116
{
 
117
   log_buffer_t *buf = NULL;
 
118
   char *log_buffer = NULL;
 
119
 
 
120
   buf = log_buffer_getspecific();
 
121
 
 
122
   if (buf != NULL) {
 
123
      log_buffer = buf->log_buffer;
 
124
   }
 
125
 
 
126
   return log_buffer;
 
127
}
 
128
 
 
129
/****** uti/log/log_get_log_context() ******************************************
 
130
*  NAME
 
131
*     log_get_log_context() -- Return a context for the specific thread 
 
132
*
 
133
*  SYNOPSIS
 
134
*     sge_gdi_ctx_class_t* log_get_log_context(void) 
 
135
*
 
136
*  FUNCTION
 
137
*     Return a context for the specific thread
 
138
*
 
139
*  RESULT
 
140
*     sge_gdi_ctx_class_t* 
 
141
*
 
142
******************************************************************************/
 
143
static sge_gdi_ctx_class_t* log_get_log_context(void)
 
144
{
 
145
   log_context_t *log_ctx = NULL;
 
146
   sge_gdi_ctx_class_t *context = NULL;
 
147
 
 
148
   log_ctx = log_context_getspecific();
 
149
 
 
150
   if (log_ctx != NULL) {
 
151
      context = log_ctx->context;
 
152
   }   
 
153
 
 
154
   return context;
 
155
}
 
156
 
 
157
/****** uti/log/log_set_log_context() ******************************************
 
158
*  NAME
 
159
*     log_set_log_context() -- set a context for the specific thread 
 
160
*
 
161
*  SYNOPSIS
 
162
*     void log_set_log_context(void *newctx) 
 
163
*
 
164
*  FUNCTION
 
165
*     Return a context for the specific thread
 
166
*
 
167
*  INPUTS
 
168
*     void newctx - the new ctx
 
169
*
 
170
*  RESULT
 
171
*
 
172
*  NOTES
 
173
*     MT-NOTE: log_state_set_log_file() is not MT safe.
 
174
*     MT-NOTE:
 
175
*     MT-NOTE: It is safe, however, to call this function from within multiple
 
176
*     MT-NOTE: threads as long as no other thread calls log_state_set_log_file() 
 
177
*
 
178
******************************************************************************/
 
179
static void log_set_log_context(sge_gdi_ctx_class_t *newctx)
 
180
{
 
181
   log_context_t *log_ctx = NULL;
 
182
 
 
183
   log_ctx = log_context_getspecific();
 
184
 
 
185
   if (log_ctx != NULL) {
 
186
      log_ctx->context = newctx;
 
187
   } 
 
188
}
 
189
 
 
190
/****** uti/log/log_state_get_log_level() ******************************************
 
191
*  NAME
 
192
*     log_state_get_log_level() -- Return log level.
 
193
*
 
194
*  SYNOPSIS
 
195
*     u_long32 log_state_get_log_level(void) 
 
196
*
 
197
*  FUNCTION
 
198
*     Return log level
 
199
*
 
200
*  RESULT
 
201
*     u_long32
 
202
*
 
203
******************************************************************************/
 
204
u_long32 log_state_get_log_level(void)
 
205
{
 
206
   u_long32 level = 0;
 
207
 
 
208
   sge_mutex_lock("Log_State_Lock", "log_state_get_log_level", __LINE__, &Log_State.mutex);
 
209
 
 
210
   level = Log_State.log_level;
 
211
 
 
212
   sge_mutex_unlock("Log_State_Lock", "log_state_get_log_level", __LINE__, &Log_State.mutex);
 
213
 
 
214
   return level;
 
215
}
 
216
 
 
217
/****** uti/sge_log/log_state_get_log_file() ***********************************
 
218
*  NAME
 
219
*     log_state_get_log_file() -- get log file name
 
220
*
 
221
*  SYNOPSIS
 
222
*     const char* log_state_get_log_file(void) 
 
223
*
 
224
*  FUNCTION
 
225
*     Return name of current log file. The string returned may or may not 
 
226
*     contain a path.
 
227
*
 
228
*  INPUTS
 
229
*     void - none 
 
230
*
 
231
*  RESULT
 
232
*     const char* - log file name (with relative or absolute path)
 
233
*
 
234
*  NOTES
 
235
*     MT-NOTE: log_state_get_log_file() is not MT safe.
 
236
*     MT-NOTE:
 
237
*     MT-NOTE: It is safe, however, to call this function from within multiple
 
238
*     MT-NOTE: threads as long as no other thread does change 'Log_File'.
 
239
*
 
240
*  BUGS
 
241
*     BUGBUG-AD: This function should use something like a barrier for
 
242
*     BUGBUG-AD: synchronization.
 
243
*
 
244
*******************************************************************************/
 
245
const char *log_state_get_log_file(void)
 
246
{
 
247
   char* file = NULL;
 
248
 
 
249
   sge_mutex_lock("Log_State_Lock", "log_state_get_log_file", __LINE__, &Log_State.mutex);
 
250
 
 
251
   file = Log_State.log_file;
 
252
 
 
253
   sge_mutex_unlock("Log_State_Lock", "log_state_get_log_file", __LINE__, &Log_State.mutex);
 
254
 
 
255
   return file;
 
256
}
 
257
 
 
258
/****** uti/log/log_state_get_log_verbose() ******************************************
 
259
*  NAME
 
260
*     log_state_get_log_verbose() -- Is verbose logging enabled?
 
261
*
 
262
*  SYNOPSIS
 
263
*     int log_state_get_log_verbose(void) 
 
264
*
 
265
*  FUNCTION
 
266
*     Is verbose logging enabled? 
 
267
*     With verbose logging enabled not only ERROR/CRITICAL messages are 
 
268
*     printed to stderr but also WARNING/INFO.
 
269
*
 
270
*  RESULT
 
271
*     int - 0 or 1 
 
272
*
 
273
*  SEE ALSO
 
274
*     uti/log/log_state_set_log_verbose()
 
275
******************************************************************************/
 
276
int log_state_get_log_verbose(void)
 
277
{
 
278
   int verbose = 0;
 
279
 
 
280
   sge_mutex_lock("Log_State_Lock", "log_state_get_log_verbose", __LINE__, &Log_State.mutex);
 
281
   
 
282
   verbose = Log_State.verbose;
 
283
   
 
284
   sge_mutex_unlock("Log_State_Lock", "log_state_get_log_verbose", __LINE__, &Log_State.mutex);
 
285
 
 
286
   return verbose;
 
287
}
 
288
 
 
289
/****** uti/log/log_state_get_log_gui() ******************************************
 
290
*  NAME
 
291
*     log_state_get_log_gui() -- Is GUI logging enabled?
 
292
*
 
293
*  SYNOPSIS
 
294
*     int log_state_get_log_gui(void) 
 
295
*
 
296
*  FUNCTION
 
297
*     Is GUI logging enabled? 
 
298
*     With GUI logging enabled messages are printed to stderr/stdout.  
 
299
*
 
300
*  RESULT
 
301
*     int - 0 or 1 
 
302
*
 
303
*  SEE ALSO
 
304
*     uti/log/log_state_set_log_gui()
 
305
******************************************************************************/
 
306
int log_state_get_log_gui(void)
 
307
{
 
308
   int gui_log = 0;
 
309
 
 
310
   sge_mutex_lock("Log_State_Lock", "log_state_get_log_gui", __LINE__, &Log_State.mutex);
 
311
   
 
312
   gui_log = Log_State.gui_log;
 
313
 
 
314
   sge_mutex_unlock("Log_State_Lock", "log_state_get_log_gui", __LINE__, &Log_State.mutex);
 
315
 
 
316
   return gui_log;
 
317
}
 
318
 
 
319
/****** uti/log/log_state_get_log_as_admin_user() ******************************************
 
320
*  NAME
 
321
*     log_state_get_log_as_admin_user() -- Needs sge_log() to change into admin user?
 
322
*
 
323
*  SYNOPSIS
 
324
*     trace_func_type log_state_get_log_as_admin_user(void) 
 
325
*
 
326
*  FUNCTION
 
327
*     Returns whether logging shall be done as admin user.
 
328
*
 
329
*  RESULT
 
330
*     int
 
331
*
 
332
*  SEE ALSO
 
333
*     uti/log/log_state_set_log_as_admin_user()
 
334
******************************************************************************/
 
335
int log_state_get_log_as_admin_user(void)
 
336
{
 
337
   int log_as_admin_user = 0;
 
338
 
 
339
   sge_mutex_lock("Log_State_Lock", "log_state_get_log_as_admin_user", __LINE__, &Log_State.mutex);
 
340
   
 
341
   log_as_admin_user = Log_State.log_as_admin_user;
 
342
   
 
343
   sge_mutex_unlock("Log_State_Lock", "log_state_get_log_as_admin_user", __LINE__, &Log_State.mutex);
 
344
 
 
345
   return log_as_admin_user;
 
346
}
 
347
 
 
348
/****** uti/log/log_state_set_log_level() *****************************************
 
349
*  NAME
 
350
*     log_state_set_log_level() -- Set log level to be used.
 
351
*
 
352
*  SYNOPSIS
 
353
*     void log_state_set_log_level(int i) 
 
354
*
 
355
*  FUNCTION
 
356
*     Set log level to be used.
 
357
*
 
358
*  INPUTS
 
359
*     u_long32 
 
360
*
 
361
*  SEE ALSO
 
362
*     uti/log/log_state_get_log_level() 
 
363
******************************************************************************/
 
364
void log_state_set_log_level(u_long32 theLevel)
 
365
 
366
 
 
367
   sge_mutex_lock("Log_State_Lock", "log_state_set_log_level", __LINE__, &Log_State.mutex);
 
368
   
 
369
   Log_State.log_level = theLevel;
 
370
 
 
371
   sge_mutex_unlock("Log_State_Lock", "log_state_set_log_level", __LINE__, &Log_State.mutex);
 
372
 
 
373
   return;
 
374
}
 
375
 
 
376
void log_state_set_log_file(char *theFile)
 
377
{
 
378
   sge_mutex_lock("Log_State_Lock", "log_state_set_log_file", __LINE__, &Log_State.mutex);
 
379
   
 
380
   Log_State.log_file = theFile;
 
381
   
 
382
   sge_mutex_unlock("Log_State_Lock", "log_state_set_log_file", __LINE__, &Log_State.mutex);
 
383
 
 
384
   return;
 
385
}
 
386
 
 
387
/****** uti/log/log_state_set_log_verbose() *****************************************
 
388
*  NAME
 
389
*     log_state_set_log_verbose() -- Enable/disable verbose logging 
 
390
*
 
391
*  SYNOPSIS
 
392
*     void log_state_set_log_verbose(int i) 
 
393
*
 
394
*  FUNCTION
 
395
*     Enable/disable verbose logging 
 
396
*
 
397
*  INPUTS
 
398
*     int i - 0 or 1  
 
399
*
 
400
*  SEE ALSO
 
401
*     uti/log/log_state_get_log_verbose() 
 
402
******************************************************************************/
 
403
void log_state_set_log_verbose(int i)
 
404
{
 
405
   sge_mutex_lock("Log_State_Lock", "log_state_set_log_verbose", __LINE__, &Log_State.mutex);
 
406
   
 
407
   Log_State.verbose = i;
 
408
   
 
409
   sge_mutex_unlock("Log_State_Lock", "log_state_set_log_verbose", __LINE__, &Log_State.mutex);
 
410
 
 
411
   return;
 
412
}
 
413
 
 
414
/****** uti/log/log_state_set_log_gui() ********************************************
 
415
*  NAME
 
416
*     log_state_set_log_gui() -- Enable/disable logging for GUIs 
 
417
*
 
418
*  SYNOPSIS
 
419
*     void log_state_set_log_gui(int i) 
 
420
*
 
421
*  FUNCTION
 
422
*     Enable/disable logging for GUIs 
 
423
*     With GUI logging enabled messages are printed to stderr/stdout.  
 
424
*
 
425
*  INPUTS
 
426
*     int i - 0 or 1 
 
427
******************************************************************************/
 
428
void log_state_set_log_gui(int i)
 
429
{
 
430
 
 
431
   sge_mutex_lock("Log_State_Lock", "log_state_set_log_gui", __LINE__, &Log_State.mutex);
 
432
   
 
433
   Log_State.gui_log = i;
 
434
 
 
435
   sge_mutex_unlock("Log_State_Lock", "log_state_set_log_gui", __LINE__, &Log_State.mutex);
 
436
   
 
437
   return;
 
438
}   
 
439
 
 
440
/****** uti/log/log_state_set_log_as_admin_user() *****************************
 
441
*  NAME
 
442
*     log_state_set_log_as_admin_user() -- Enable/Disable logging as admin user 
 
443
*
 
444
*  SYNOPSIS
 
445
*     void log_state_set_log_as_admin_user(int i)
 
446
*
 
447
*  FUNCTION
 
448
*     This function enables/disables logging as admin user. This 
 
449
*     means that the function/macros switches from start user to 
 
450
*     admin user before any messages will be written. After that 
 
451
*     they will switch back to 'start' user. 
 
452
*
 
453
*  INPUTS
 
454
*     int i - 0 or 1 
 
455
*  
 
456
*  SEE ALSO
 
457
*     uti/uidgid/sge_switch2admin_user
 
458
*     uti/uidgid/sge_switch2start_user
 
459
******************************************************************************/
 
460
void log_state_set_log_as_admin_user(int i)
 
461
{
 
462
   sge_mutex_lock("Log_State_Lock", "log_state_set_log_as_admin_user", __LINE__, &Log_State.mutex);
 
463
   
 
464
   Log_State.log_as_admin_user = i;
 
465
 
 
466
   sge_mutex_unlock("Log_State_Lock", "log_state_set_log_as_admin_user", __LINE__, &Log_State.mutex);
 
467
}
 
468
 
 
469
 
 
470
static sge_gdi_ctx_class_t* log_state_get_log_context(void)
 
471
{
 
472
   sge_gdi_ctx_class_t *log_context = NULL;
 
473
 
 
474
/*    sge_mutex_lock("Log_State_Lock", "log_state_get_log_context", __LINE__, &Log_State.mutex); */
 
475
 
 
476
   log_context = log_get_log_context();
 
477
 
 
478
/*    sge_mutex_unlock("Log_State_Lock", "log_state_get_log_context", __LINE__, &Log_State.mutex); */
 
479
 
 
480
   return log_context;
 
481
}
 
482
 
 
483
void log_state_set_log_context(void *theCtx)
 
484
{
 
485
   sge_mutex_lock("Log_State_Lock", "log_state_set_log_context", __LINE__, &Log_State.mutex);
 
486
   
 
487
   log_set_log_context((sge_gdi_ctx_class_t*)theCtx);
 
488
 
 
489
   sge_mutex_unlock("Log_State_Lock", "log_state_set_log_context", __LINE__, &Log_State.mutex);
 
490
}
 
491
 
 
492
 
 
493
 
 
494
/****** uti/log/sge_log() *****************************************************
 
495
*  NAME
 
496
*     sge_log() -- Low level logging function 
 
497
*
 
498
*  SYNOPSIS
 
499
*     int sge_log(int log_level, char *mesg, char *file__, 
 
500
*                 char *func__, int line__) 
 
501
*
 
502
*  FUNCTION
 
503
*     Low level logging function. Used by various macros.
 
504
*     Do not use this function directly. 
 
505
*
 
506
*  INPUTS
 
507
*     int log_level - Logging Level
 
508
*     char *mesg    - Message
 
509
*     char *file__  - Filename
 
510
*     char *func__  - Function Name
 
511
*     int line__    - Line within 'file__'
 
512
*
 
513
*  RESULT
 
514
*     int - 0
 
515
*
 
516
*  SEE ALSO
 
517
*     uti/log/CRITICAL
 
518
*     uti/log/ERROR
 
519
*     uti/log/WARNING
 
520
*     uti/log/NOTICE
 
521
*     uti/log/INFO
 
522
*     uti/log/DEBUG
 
523
*
 
524
*  NOTES
 
525
*     MT-NOTE: sge_log() is not MT safe due to sge_switch2admin_user()
 
526
*     MT-NOTE: sge_log() can be used in clients where no admin user switching 
 
527
*     MT-NOTE: takes place
 
528
*     MT-NOTE: sge_log() is not MT safe due rmon_condition()
 
529
*     MT-NOTE: sge_log() can be used if DENTER_MAIN() is called only by one 
 
530
*     MT-NOTE: thread
 
531
******************************************************************************/
 
532
int sge_log(int log_level, const char *mesg, const char *file__, const char *func__, int line__) 
 
533
{
 
534
   char buf[128*4];
 
535
   int levelchar;
 
536
   char levelstring[32*4];
 
537
   
 
538
   sge_gdi_ctx_class_t *ctx = NULL;
 
539
   /* TODO: this must be kept for qmaster and should be done in a different
 
540
            way (qmaster context) !!! */
 
541
   u_long32 me = 0;
 
542
   const char *threadname = NULL;
 
543
   const char *unqualified_hostname = NULL;
 
544
   int is_daemonized = 0; 
 
545
 
 
546
   DENTER(TOP_LAYER, "sge_log");
 
547
   
 
548
   ctx = log_state_get_log_context();
 
549
   
 
550
   if (ctx != NULL) {
 
551
      me = ctx->get_who(ctx);
 
552
      threadname = ctx->get_thread_name(ctx);
 
553
      unqualified_hostname = ctx->get_unqualified_hostname(ctx);
 
554
      is_daemonized = ctx->is_daemonized(ctx);
 
555
   } else {
 
556
      DPRINTF(("sge_log: ctx is NULL\n"));
 
557
   }   
 
558
 
 
559
   /* Make sure to have at least a one byte logging string */
 
560
   if (!mesg || mesg[0] == '\0') {
 
561
      sprintf(buf, MSG_LOG_CALLEDLOGGINGSTRING_S, 
 
562
              mesg ? MSG_LOG_ZEROLENGTH : MSG_POINTER_NULL);
 
563
      mesg = buf;
 
564
   }
 
565
 
 
566
   DPRINTF(("%s %d %s\n", file__, line__, mesg));
 
567
 
 
568
   /* quick exit if nothing to log */
 
569
   if (log_level > MAX(log_state_get_log_level(), LOG_WARNING)) {
 
570
      DRETURN(0);
 
571
   }
 
572
 
 
573
   if (!log_state_get_log_gui()) {
 
574
      DRETURN(0);
 
575
   }
 
576
 
 
577
   switch(log_level) {
 
578
      case LOG_PROF:
 
579
         strcpy(levelstring, MSG_LOG_PROFILING);
 
580
         levelchar = 'P';
 
581
         break;
 
582
      case LOG_CRIT:
 
583
         strcpy(levelstring, MSG_LOG_CRITICALERROR);
 
584
         levelchar = 'C';
 
585
         break;
 
586
      case LOG_ERR:
 
587
         strcpy(levelstring, MSG_LOG_ERROR);
 
588
         levelchar = 'E';
 
589
         break;
 
590
      case LOG_WARNING:
 
591
         strcpy(levelstring, "");
 
592
         levelchar = 'W';
 
593
         break;
 
594
      case LOG_NOTICE:
 
595
         strcpy(levelstring, "");
 
596
         levelchar = 'N';
 
597
         break;
 
598
      case LOG_INFO:
 
599
         strcpy(levelstring, "");
 
600
         levelchar = 'I';
 
601
         break;
 
602
      case LOG_DEBUG:
 
603
         strcpy(levelstring, "");
 
604
         levelchar = 'D';
 
605
         break;
 
606
      default:
 
607
         strcpy(levelstring, "");
 
608
         levelchar = 'L';
 
609
         break;
 
610
   }
 
611
 
 
612
   /* avoid double output in debug mode */
 
613
   if (!is_daemonized && !rmon_condition(TOP_LAYER, INFOPRINT) && 
 
614
       (log_state_get_log_verbose() || log_level <= LOG_ERR)) {
 
615
      fprintf(stderr, "%s%s\n", levelstring, mesg);
 
616
   }
 
617
 
 
618
   sge_do_log(me, threadname, unqualified_hostname, levelchar, mesg);
 
619
 
 
620
   DRETURN(0);
 
621
} /* sge_log() */
 
622
 
 
623
/****** uti/sge_log/sge_do_log() ***********************************************
 
624
*  NAME
 
625
*     sge_do_log() -- Write message to log file 
 
626
*
 
627
*  SYNOPSIS
 
628
*     static void sge_do_log(int aLevel, const char *aMessage, const char 
 
629
*
 
630
*  FUNCTION
 
631
*     ??? 
 
632
*
 
633
*  INPUTS
 
634
*     int aLevel           - log level
 
635
*     const char *aMessage - log message
 
636
*
 
637
*  RESULT
 
638
*     void - none
 
639
*
 
640
*  NOTES
 
641
*     MT-NOTE: sge_do_log() is MT safe.
 
642
*
 
643
*******************************************************************************/
 
644
static void sge_do_log(u_long32 me, const char* progname, const char* unqualified_hostname,
 
645
                       int aLevel, const char *aMessage) 
 
646
{
 
647
   int fd;
 
648
 
 
649
   if (me == QMASTER || me == EXECD || me == SCHEDD || me == SHADOWD) {
 
650
      if ((fd = SGE_OPEN3(log_state_get_log_file(), O_WRONLY | O_APPEND | O_CREAT, 0666)) >= 0) {
 
651
         char msg2log[4*MAX_STRING_SIZE];
 
652
         dstring msg;
 
653
         
 
654
         sge_dstring_init(&msg, msg2log, sizeof(msg2log));
 
655
 
 
656
         append_time((time_t)sge_get_gmt(), &msg, false); 
 
657
 
 
658
         sge_dstring_sprintf_append(&msg, "|%6.6s|%s|%c|%s\n",
 
659
                 progname,
 
660
                 unqualified_hostname,
 
661
                 aLevel,
 
662
                 aMessage);
 
663
 
 
664
         write(fd, msg2log, strlen(msg2log));
 
665
         close(fd);
 
666
      }
 
667
   }   
 
668
 
 
669
   return;
 
670
} /* sge_do_log() */
 
671
 
 
672
/****** uti/log/log_buffer_once_init() ********************************************
 
673
*  NAME
 
674
*     log_buffer_once_init() -- One-time logging initialization.
 
675
*
 
676
*  SYNOPSIS
 
677
*     static log_buffer_once_init(void) 
 
678
*
 
679
*  FUNCTION
 
680
*     Create access key for thread local storage. Register cleanup function.
 
681
*     This function must be called exactly once.
 
682
*
 
683
*  INPUTS
 
684
*     void - none
 
685
*
 
686
*  RESULT
 
687
*     void - none 
 
688
*
 
689
*  NOTES
 
690
*     MT-NOTE: log_buffer_once_init() is MT safe. 
 
691
*
 
692
*******************************************************************************/
 
693
static void log_buffer_once_init(void)
 
694
{
 
695
   pthread_key_create(&log_buffer_key, &log_buffer_destroy);
 
696
} /* log_once_init */
 
697
 
 
698
/****** uti/log/log_buffer_destroy() ****************************************
 
699
*  NAME
 
700
*     log_buffer_destroy() -- Free thread local storage
 
701
*
 
702
*  SYNOPSIS
 
703
*     static void log_buffer_destroy(void* theState) 
 
704
*
 
705
*  FUNCTION
 
706
*     Free thread local storage.
 
707
*
 
708
*  INPUTS
 
709
*     void* theState - Pointer to memroy which should be freed.
 
710
*
 
711
*  RESULT
 
712
*     static void - none
 
713
*
 
714
*  NOTES
 
715
*     MT-NOTE: log_buffer_destroy() is MT safe.
 
716
*
 
717
*******************************************************************************/
 
718
static void log_buffer_destroy(void* theBuffer)
 
719
{
 
720
   sge_free((char*)theBuffer);
 
721
}
 
722
 
 
723
/****** uti/log/log_buffer_getspecific() ****************************************
 
724
*  NAME
 
725
*     log_buffer_getspecific() -- Get thread local log state
 
726
*
 
727
*  SYNOPSIS
 
728
*     static log_buffer_t* log_buffer_getspecific() 
 
729
*
 
730
*  FUNCTION
 
731
*     Return thread local log state.
 
732
*
 
733
*     If a given thread does call this function for the first time, no thread
 
734
*     local log state is available for this particular thread. In this case the
 
735
*     thread local log state is allocated and set.
 
736
*
 
737
*  RESULT
 
738
*     static log_buffer_t* - Pointer to thread local log state.
 
739
*
 
740
*  NOTES
 
741
*     MT-NOTE: log_buffer_getspecific() is MT safe 
 
742
*
 
743
*******************************************************************************/
 
744
static log_buffer_t* log_buffer_getspecific(void)
 
745
{
 
746
   log_buffer_t *buf = NULL;
 
747
   int res = -1;
 
748
 
 
749
   pthread_once(&log_buffer_once, log_buffer_once_init);
 
750
 
 
751
   if ((buf = pthread_getspecific(log_buffer_key)) != NULL) {
 
752
      return buf;
 
753
   }
 
754
 
 
755
   buf = (log_buffer_t*)sge_malloc(sizeof(log_buffer_t));
 
756
   memset((void*)(buf), 0, sizeof(log_buffer_t));
 
757
 
 
758
   res = pthread_setspecific(log_buffer_key, (const void*)buf);
 
759
 
 
760
   if (0 != res) {
 
761
      fprintf(stderr, "pthread_set_specific(%s) failed: %s\n", "log_buffer_getspecific", strerror(res));
 
762
      abort();
 
763
   }
 
764
   
 
765
   return buf;
 
766
} /* log_buffer_getspecific() */
 
767
 
 
768
 
 
769
/****** uti/log/log_context_once_init() ********************************************
 
770
*  NAME
 
771
*     log_context_once_init() -- One-time logging initialization.
 
772
*
 
773
*  SYNOPSIS
 
774
*     static log_context_once_init(void) 
 
775
*
 
776
*  FUNCTION
 
777
*     Create access key for thread local storage. Register cleanup function.
 
778
*     This function must be called exactly once.
 
779
*
 
780
*  INPUTS
 
781
*     void - none
 
782
*
 
783
*  RESULT
 
784
*     void - none 
 
785
*
 
786
*  NOTES
 
787
*     MT-NOTE: log_context_once_init() is MT safe. 
 
788
*
 
789
*******************************************************************************/
 
790
static void log_context_once_init(void)
 
791
{
 
792
   pthread_key_create(&log_context_key, &log_context_destroy);
 
793
} /* log_once_init */
 
794
 
 
795
/****** uti/log/log_context_destroy() ****************************************
 
796
*  NAME
 
797
*     log_context_destroy() -- Free thread local storage
 
798
*
 
799
*  SYNOPSIS
 
800
*     static void log_context_destroy(void* theState) 
 
801
*
 
802
*  FUNCTION
 
803
*     Free thread local storage.
 
804
*
 
805
*  INPUTS
 
806
*     void* theState - Pointer to memroy which should be freed.
 
807
*
 
808
*  RESULT
 
809
*     static void - none
 
810
*
 
811
*  NOTES
 
812
*     MT-NOTE: log_context_destroy() is MT safe.
 
813
*
 
814
*******************************************************************************/
 
815
static void log_context_destroy(void* theContext)
 
816
{
 
817
   sge_free((char*)theContext);
 
818
}
 
819
 
 
820
/****** uti/log/log_context_getspecific() ****************************************
 
821
*  NAME
 
822
*     log_context_getspecific() -- Get thread local log context
 
823
*
 
824
*  SYNOPSIS
 
825
*     static log_context_t* log_context_getspecific() 
 
826
*
 
827
*  FUNCTION
 
828
*     Return thread local log context.
 
829
*
 
830
*     If a given thread does call this function for the first time, no thread
 
831
*     local log state is available for this particular thread. In this case the
 
832
*     thread local log state is allocated and set.
 
833
*
 
834
*  RESULT
 
835
*     static log_context_t* - Pointer to thread local log context.
 
836
*
 
837
*  NOTES
 
838
*     MT-NOTE: log_context_getspecific() is MT safe 
 
839
*
 
840
*******************************************************************************/
 
841
static log_context_t* log_context_getspecific(void)
 
842
{
 
843
   log_context_t *myctx = NULL;
 
844
   int res = -1;
 
845
 
 
846
   pthread_once(&log_context_once, log_context_once_init);
 
847
 
 
848
   if ((myctx = pthread_getspecific(log_context_key)) != NULL) {
 
849
      return myctx;
 
850
   }
 
851
 
 
852
   myctx = (log_context_t*)sge_malloc(sizeof(log_context_t));
 
853
   if (myctx != NULL) {
 
854
      myctx->context = NULL;
 
855
   }   
 
856
   res = pthread_setspecific(log_context_key, (const void*)myctx);
 
857
 
 
858
   if (0 != res) {
 
859
      fprintf(stderr, "pthread_set_specific(%s) failed: %s\n", "log_context_getspecific", strerror(res));
 
860
      abort();
 
861
   }
 
862
   
 
863
   return myctx;
 
864
} /* log_context_getspecific() */
 
865