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

« back to all changes in this revision

Viewing changes to source/libs/rmon/rmon_macros.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 "rmon.h"
 
34
 
 
35
#include <stdio.h>
 
36
#include <unistd.h>
 
37
#include <stdlib.h>
 
38
#include <string.h>
 
39
#include <pthread.h>
 
40
#include <errno.h>
 
41
 
 
42
#include "sge_mtutil.h"
 
43
#include "msg_rmon.h"
 
44
 
 
45
#define DEBUG RMON_LOCAL
 
46
 
 
47
#if 0
 
48
/*
 
49
 * It increases scheduler dispatch time by 60-70%.
 
50
 * Must be wrong.
 
51
 */
 
52
define RMON_USE_CTX
 
53
#endif 
 
54
 
 
55
/* ALPHA (osf4 and tru64) have f(un)lockfile, but prototype is missing */
 
56
#if defined (ALPHA)
 
57
extern void flockfile(FILE *);
 
58
extern void funlockfile(FILE *);
 
59
#endif
 
60
 
 
61
enum {
 
62
   RMON_NONE     = 0,   /* monitoring off */
 
63
   RMON_LOCAL    = 1,   /* monitoring on */
 
64
   RMON_BUF_SIZE = 5120  /* size of buffer used for monitoring messages */
 
65
};
 
66
 
 
67
monitoring_level RMON_DEBUG_ON = { {0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L} };
 
68
monitoring_level RMON_DEBUG_ON_STORAGE = { {0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L} };
 
69
 
 
70
static const char* empty = "    ";
 
71
 
 
72
static u_long mtype = RMON_NONE;
 
73
#ifdef DEBUG_CLIENT_SUPPORT
 
74
static u_long mtype_storage = RMON_NONE;
 
75
#endif
 
76
static FILE* rmon_fp;
 
77
 
 
78
static void mwrite(char *message, const char *thread_name);
 
79
static int set_debug_level_from_env(void);
 
80
static int set_debug_target_from_env(void);
 
81
static void rmon_mprintf_va(int debug_class, const char* fmt, va_list args);
 
82
 
 
83
#ifdef DEBUG_CLIENT_SUPPORT
 
84
static pthread_mutex_t rmon_print_callback_mutex = PTHREAD_MUTEX_INITIALIZER;
 
85
static pthread_mutex_t rmon_condition_mutex = PTHREAD_MUTEX_INITIALIZER;
 
86
static rmon_print_callback_func_t rmon_print_callback = NULL;
 
87
#define RMON_CALLBACK_FUNC_LOCK()      pthread_mutex_lock(&rmon_print_callback_mutex)
 
88
#define RMON_CALLBACK_FUNC_UNLOCK()    pthread_mutex_unlock(&rmon_print_callback_mutex)
 
89
#define RMON_CONDITION_LOCK()          pthread_mutex_lock(&rmon_condition_mutex)
 
90
#define RMON_CONDITION_UNLOCK()        pthread_mutex_unlock(&rmon_condition_mutex)
 
91
#endif
 
92
 
 
93
 
 
94
static pthread_key_t rmon_ctx_key;
 
95
static pthread_once_t rmon_ctx_key_once = PTHREAD_ONCE_INIT;
 
96
static void rmon_ctx_key_init(void);
 
97
static void rmon_ctx_key_destroy(void * ctx);
 
98
 
 
99
static pthread_key_t rmon_helper_key;
 
100
static pthread_once_t rmon_helper_key_once = PTHREAD_ONCE_INIT;
 
101
static void rmon_helper_key_init(void);
 
102
static void rmon_helper_key_destroy(void * ctx);
 
103
 
 
104
 
 
105
rmon_ctx_t* rmon_get_thread_ctx(void)
 
106
{
 
107
  pthread_once(&rmon_ctx_key_once, rmon_ctx_key_init);
 
108
  return (rmon_ctx_t*) pthread_getspecific(rmon_ctx_key);
 
109
}
 
110
 
 
111
void rmon_set_thread_ctx(rmon_ctx_t* ctx) {
 
112
   pthread_once(&rmon_ctx_key_once, rmon_ctx_key_init);
 
113
   pthread_setspecific(rmon_ctx_key, ctx);
 
114
}
 
115
 
 
116
/* Allocate the key */
 
117
static void rmon_ctx_key_init(void)
 
118
{
 
119
  pthread_key_create(&rmon_ctx_key, rmon_ctx_key_destroy);
 
120
}
 
121
 
 
122
/* Free the thread-specific buffer */
 
123
static void rmon_ctx_key_destroy(void * ctx)
 
124
{
 
125
  /* Nothing to destroy */
 
126
}
 
127
 
 
128
rmon_helper_t *rmon_get_helper(void)
 
129
{
 
130
   rmon_helper_t *helper = NULL;
 
131
   
 
132
   pthread_once(&rmon_helper_key_once, rmon_helper_key_init);
 
133
 
 
134
   helper = pthread_getspecific(rmon_helper_key);
 
135
   if (helper == NULL) {
 
136
      helper = (rmon_helper_t *)malloc(sizeof(rmon_helper_t));
 
137
 
 
138
      memset(helper, 0, sizeof(rmon_helper_t));
 
139
      pthread_setspecific(rmon_helper_key, helper);
 
140
   }
 
141
   return helper;
 
142
}
 
143
 
 
144
static void rmon_helper_key_init(void)
 
145
{
 
146
   pthread_key_create(&rmon_helper_key, rmon_helper_key_destroy);
 
147
}
 
148
 
 
149
static void rmon_helper_key_destroy(void * ctx)
 
150
{
 
151
   free(ctx);
 
152
}
 
153
 
 
154
/****** rmon/Introduction ******************************************************
 
155
*  NAME
 
156
*     RMON - Grid Engine Monitoring Interface
 
157
*
 
158
*  FUNCTION
 
159
*     The RMON library is a set of functions, which do allow monitoring of 
 
160
*     of application execution. The functions provided, however, should not
 
161
*     be used directly. Rather the RMON functions are utilized by a set of
 
162
*     monitoring macros, like 'DENTER' or 'DEXIT'.
 
163
*
 
164
*     If monitoring is active, the RMON functions do get called very frequently.
 
165
*     Hence, the overhead caused by monitoring needs to be minimal. For this
 
166
*     reason, access to external global and static global variables is NOT
 
167
*     synchronized through a mutex! Not using a lock of type 'pthread_mutex_t'
 
168
*     also means that the RMON functions are async-signal safe.
 
169
 
170
*     To use RMON library in a multi threaded environment, some restrictions
 
171
*     must be followed strictly! It is of utmost importance, that the function
 
172
*     'rmon_mopen()' is ONLY invoked from exactly one thread. The thread which
 
173
*     is calling 'rmon_mopen()' must be the ONLY thread at this point in time.
 
174
*     'DENTER_MAIN' is the only macro from which 'rmon_mopen()' is called. The
 
175
*     macro 'DENTER_MAIN' is used at the beginning of a main function. At this
 
176
*     point in time, the so called main-thread is the only thread.
 
177
*
 
178
*     It is safe to call the remaining RMON functions, like 'rmon_menter()' or
 
179
*     'rmon_mexit()', from within multiple threads. 'rmon_mopen()' is the only
 
180
*     RMON function which does change the critical global variables ('mtype',
 
181
*     'rmon_fp' and 'RMON_DEBUG_ON'). 'rmon_menter()' and 'rmon_mexit()' are used by
 
182
*     the macro 'DENTER' and 'DEXIT', respectively.
 
183
*     
 
184
*******************************************************************************/
 
185
 
 
186
/****** rmon_macros/rmon_condition() *******************************************
 
187
*  NAME
 
188
*     rmon_condition() -- Check monitoring condition. 
 
189
*
 
190
*  SYNOPSIS
 
191
*     int rmon_condition(int layer, int class) 
 
192
*
 
193
*  FUNCTION
 
194
*     Check whether monitoring should be enabled for the given combination of
 
195
*     'layer' and 'class'. 
 
196
*
 
197
*  INPUTS
 
198
*     int layer - monitor layer 
 
199
*     int class - monitor class 
 
200
*
 
201
*  RESULT
 
202
*     1 - do monitor
 
203
*     0 - do not monitor
 
204
*
 
205
*  NOTES
 
206
*     MT-NOTE: 'rmon_condition()' is MT safe with exceptions. See introduction!
 
207
*
 
208
*******************************************************************************/
 
209
int rmon_condition(int layer, int class)
 
210
{
 
211
   int ret_val;
 
212
#define MLGETL(s, i) ((s)->ml[i]) /* for the sake of speed */
 
213
   /*
 
214
    * NOTE:
 
215
    * 
 
216
    * This is only a static u_long value used as flag for switching
 
217
    * debug printing on/off. Therefore we don't need a mutex lock
 
218
    * at this point.
 
219
    */ 
 
220
#ifdef DEBUG_CLIENT_SUPPORT
 
221
   if ( mtype == RMON_NONE ) {
 
222
      return 0;
 
223
   }
 
224
   
 
225
   /* if debug printing is on we use a lock for further layer checking */
 
226
   RMON_CONDITION_LOCK();
 
227
#endif
 
228
   ret_val = ((mtype != RMON_NONE) && (class & MLGETL(&RMON_DEBUG_ON, layer))) ? 1 : 0;
 
229
#ifdef DEBUG_CLIENT_SUPPORT
 
230
   RMON_CONDITION_UNLOCK();
 
231
#endif
 
232
   return ret_val;
 
233
#undef MLGETL
 
234
} /* rmon_condition() */
 
235
 
 
236
 
 
237
/****** rmon_macros/rmon_debug_client_callback() ****************************
 
238
*  NAME
 
239
*     rmon_debug_client_callback() -- callback for debug clients
 
240
*
 
241
*  SYNOPSIS
 
242
*     static void rmon_debug_client_callback(int dc_connected, int debug_level) 
 
243
*
 
244
*  FUNCTION
 
245
*     Is called when a debug client is connected/disconnected or on
 
246
*     debug level changes. Use cl_com_application_debug() to send debug
 
247
*     messages to the connected qping -dump client.
 
248
*
 
249
*  INPUTS
 
250
*     int dc_connected - 1 debug client is connected
 
251
*                        0 no debug client is connected
 
252
*     int debug_level  - debug level from 0 (off) to 5(DPRINTF)
 
253
*  NOTES
 
254
*     MT-NOTE: rmon_debug_client_callback() is MT safe 
 
255
*              (but is called from commlib thread, which means that no
 
256
*               qmaster thread specifc setup is done), just use global
 
257
*               thread locking methods which are initalized when called, or
 
258
*               initalized at compile time)
 
259
*
 
260
*******************************************************************************/
 
261
void rmon_debug_client_callback(int dc_connected, int debug_level) {
 
262
#ifdef DEBUG_CLIENT_SUPPORT
 
263
   RMON_CONDITION_LOCK();
 
264
 
 
265
   /* we are saving the old value of the RMON_DEBUG_ON structure into RMON_DEBUG_ON_STORAGE */
 
266
   if (dc_connected) {
 
267
      /* TODO: support rmon debug levels with $SGE_DEBUG_LEVEL string ? 
 
268
       *       if so, the debug_level parameter should be a string value
 
269
       */
 
270
      (&RMON_DEBUG_ON)->ml[TOP_LAYER]   = 2; 
 
271
      if (debug_level > 1) {
 
272
         (&RMON_DEBUG_ON)->ml[TOP_LAYER]   = 3; 
 
273
      }
 
274
      mtype = RMON_LOCAL;
 
275
   } else {
 
276
      (&RMON_DEBUG_ON)->ml[TOP_LAYER]   = (&RMON_DEBUG_ON_STORAGE)->ml[TOP_LAYER]; 
 
277
      mtype = mtype_storage;
 
278
   }
 
279
   RMON_CONDITION_UNLOCK();
 
280
#else
 
281
   return;
 
282
#endif
 
283
}
 
284
 
 
285
void rmon_set_print_callback(rmon_print_callback_func_t function_p) {
 
286
#ifdef DEBUG_CLIENT_SUPPORT
 
287
   if (function_p != NULL) {
 
288
      RMON_CALLBACK_FUNC_LOCK();
 
289
      rmon_print_callback = *function_p;
 
290
      RMON_CALLBACK_FUNC_UNLOCK();
 
291
   }
 
292
#else
 
293
   return;
 
294
#endif
 
295
}
 
296
 
 
297
 
 
298
 
 
299
/****** rmon_macros/rmon_is_enabled() ******************************************
 
300
*  NAME
 
301
*     rmon_is_enabled() -- Check if monitoring is enabled. 
 
302
*
 
303
*  SYNOPSIS
 
304
*     int rmon_is_enabled(void) 
 
305
*
 
306
*  FUNCTION
 
307
*     Check if monitoring is enabled. Note that even if monitoring is enabled
 
308
*     no actual monitoring output may be generated. Generation of monitoring
 
309
*     output is controlled by 'rmon_condition()'.   
 
310
*
 
311
*  INPUTS
 
312
*     void - none 
 
313
*
 
314
*  RESULT
 
315
*     1 - monitoring enabled 
 
316
*     0 - monitoring disabled
 
317
*
 
318
*  NOTES
 
319
*     MT-NOTE: 'rmon_is_enabled()' is MT safe with exceptions. See introduction! 
 
320
*
 
321
*******************************************************************************/
 
322
int rmon_is_enabled(void)
 
323
{
 
324
   return ((mtype == RMON_LOCAL) ? 1 : 0);
 
325
} /* rmon_is_enabled() */
 
326
 
 
327
/****** rmon_macros/rmon_mopen() ***********************************************
 
328
*  NAME
 
329
*     rmon_mopen() -- Open, i.e. initialize monitoring. 
 
330
*
 
331
*  SYNOPSIS
 
332
*     void rmon_mopen(int *argc, char *argv[], char *programname) 
 
333
*
 
334
*  FUNCTION
 
335
*     Initialize monitoring. Clear all monitoring levels. Set monitoring levels
 
336
*     according to 'SGE_DEBUG_LEVEL' environment variable. Set monitoring
 
337
*     target (i.e. output stream) according to 'SGE_DEBUG_TARGET' environment
 
338
*     variable. Enable monitoring.  
 
339
*
 
340
*     NOTE: Even though 'argc' and 'argv' are not used, they do make sure that
 
341
*     'rmon_mopen()' is only used within a main function to a certain degree.
 
342
*
 
343
*  INPUTS
 
344
*     int *argc         - not used 
 
345
*     char *argv[]      - not used 
 
346
*     char *programname - not used 
 
347
*
 
348
*  RESULT
 
349
*     void - none
 
350
*
 
351
*  NOTES
 
352
*     MT-NOTE: 'rmon_mopen()' is NOT MT safe. See introduction! 
 
353
*
 
354
*******************************************************************************/
 
355
void rmon_mopen(int *argc, char *argv[], char *programname)
 
356
{
 
357
   int ret = -1;
 
358
 
 
359
   rmon_mlclr(&RMON_DEBUG_ON);
 
360
   rmon_fp = stderr;
 
361
 
 
362
   ret = set_debug_level_from_env();
 
363
   ret = set_debug_target_from_env();
 
364
 
 
365
   if (ret != 0) {
 
366
      exit(-1);
 
367
   }
 
368
 
 
369
   mtype = RMON_LOCAL;
 
370
#ifdef DEBUG_CLIENT_SUPPORT
 
371
   mtype_storage = mtype;
 
372
#endif
 
373
 
 
374
   return;
 
375
} /* rmon_mopen */
 
376
 
 
377
/****** rmon_macros/rmon_menter() **********************************************
 
378
*  NAME
 
379
*     rmon_menter() -- Monitor function entry 
 
380
*
 
381
*  SYNOPSIS
 
382
*     void rmon_menter(const char *func) 
 
383
*
 
384
*  FUNCTION
 
385
*     Monitor function entry. Generate function entry message. 
 
386
*
 
387
*  INPUTS
 
388
*     const char *func - function name 
 
389
*
 
390
*  RESULT
 
391
*     void - none 
 
392
*
 
393
*  NOTES
 
394
*     MT-NOTE: 'rmon_menter()' is MT safe with exceptions. See introduction! 
 
395
*
 
396
*******************************************************************************/
 
397
 
 
398
void rmon_menter(const char *func, const char *thread_name)
 
399
{
 
400
   char msgbuf[RMON_BUF_SIZE];
 
401
#ifdef RMON_USE_CTX
 
402
   rmon_ctx_t *ctx = rmon_get_thread_ctx();
 
403
   if (ctx) {
 
404
      ctx->menter(ctx, func);
 
405
      return;
 
406
   }
 
407
#endif      
 
408
   sprintf(msgbuf, "--> %s() {\n", func);
 
409
   mwrite(msgbuf, thread_name);
 
410
} /* rmon_enter() */
 
411
 
 
412
 
 
413
 
 
414
/****** rmon_macros/rmon_mexit() ***********************************************
 
415
*  NAME
 
416
*     rmon_mexit() -- Monitor function exit 
 
417
*
 
418
*  SYNOPSIS
 
419
*     void rmon_mexit(const char *func, const char *file, int line) 
 
420
*
 
421
*  FUNCTION
 
422
*     Monitor function exit. Generate function exit message. 
 
423
*
 
424
*  INPUTS
 
425
*     const char *func - function name 
 
426
*     const char *file - source file in which function is defined 
 
427
*     int line         - number of invokation source line
 
428
*
 
429
*  RESULT
 
430
*     void - none
 
431
*
 
432
*  NOTES
 
433
*     MT-NOTE: 'rmon_mexit()' is MT safe with exceptions. See introduction! 
 
434
*
 
435
*******************************************************************************/
 
436
void rmon_mexit(const char *func, const char *file, int line, const char *thread_name)
 
437
{
 
438
   char msgbuf[RMON_BUF_SIZE];
 
439
#ifdef RMON_USE_CTX   
 
440
   rmon_ctx_t *ctx = rmon_get_thread_ctx();
 
441
   if (ctx) {
 
442
      ctx->mexit(ctx, func, file, line);
 
443
      return;
 
444
   }
 
445
#endif
 
446
   sprintf(msgbuf, "<-- %s() %s %d }\n", func, file, line);
 
447
   mwrite(msgbuf, thread_name);
 
448
 
 
449
} /* rmon_mexit() */
 
450
 
 
451
/****** rmon_macros/rmon_mtrace() **********************************************
 
452
*  NAME
 
453
*     rmon_mtrace() -- Monitor function progress 
 
454
*
 
455
*  SYNOPSIS
 
456
*     void rmon_mtrace(const char *func, const char *file, int line) 
 
457
*
 
458
*  FUNCTION
 
459
*     Monitor function progress. Generate function trace message. 
 
460
*
 
461
*  INPUTS
 
462
*     const char *func - function name 
 
463
*     const char *file - source file in which function is defined 
 
464
*     int line         - number of invokation source line
 
465
*
 
466
*  RESULT
 
467
*     void - none 
 
468
*
 
469
*  NOTES
 
470
*     MT-NOTE: 'rmon_mtrace()' is MT safe with exceptions. See introduction! 
 
471
*
 
472
*******************************************************************************/
 
473
void rmon_mtrace(const char *func, const char *file, int line, const char *thread_name)
 
474
{
 
475
   char msgbuf[RMON_BUF_SIZE];
 
476
#ifdef RMON_USE_CTX   
 
477
   rmon_ctx_t *ctx = rmon_get_thread_ctx();
 
478
   if (ctx) {
 
479
      ctx->mtrace(ctx, func, file, line);
 
480
      return;
 
481
   }
 
482
#endif      
 
483
   strcpy(msgbuf, empty);
 
484
   sprintf(&msgbuf[4], "%s:%s:%d\n", func, file, line);
 
485
   mwrite(msgbuf, thread_name);
 
486
} /* rmon_mtrace() */
 
487
 
 
488
/****** rmon_macros/rmon_mprintf() *********************************************
 
489
*  NAME
 
490
*     rmon_mprintf() -- Print formatted monitoring message. 
 
491
*
 
492
*  SYNOPSIS
 
493
*     void rmon_mprintf(const char *fmt, ...) 
 
494
*
 
495
*  FUNCTION
 
496
*     Print formatted monitoring message. 
 
497
*
 
498
*  INPUTS
 
499
*     const char *fmt - format string 
 
500
*     ...             - variable argument list 
 
501
*
 
502
*  RESULT
 
503
*     void - none
 
504
*
 
505
*  NOTES
 
506
*     MT-NOTE: 'rmon_mprintf()' is MT safe with exceptions. See introduction! 
 
507
*
 
508
*******************************************************************************/
 
509
void rmon_mprintf(int debug_class, const char *fmt,...)
 
510
{
 
511
   va_list args;
 
512
   
 
513
   va_start(args, fmt);
 
514
   rmon_mprintf_va(debug_class, fmt, args);
 
515
   va_end(args);
 
516
   
 
517
   return;
 
518
} /* rmon_mprintf() */
 
519
 
 
520
 
 
521
void rmon_mprintf_lock(const char* fmt, ...) {
 
522
   va_list args;
 
523
   va_start(args, fmt);
 
524
   rmon_mprintf_va(LOCK, fmt, args);
 
525
   va_end(args);
 
526
}
 
527
 
 
528
void rmon_mprintf_info(const char* fmt, ...) {
 
529
   va_list args;
 
530
   va_start(args, fmt);
 
531
   rmon_mprintf_va(INFOPRINT, fmt, args);
 
532
   va_end(args);
 
533
}
 
534
 
 
535
void rmon_mprintf_timing(const char* fmt, ...) {
 
536
   va_list args;
 
537
   va_start(args, fmt);
 
538
   rmon_mprintf_va(TIMING, fmt, args);
 
539
   va_end(args);
 
540
}
 
541
 
 
542
void rmon_mprintf_special(const char* fmt, ...) {
 
543
   va_list args;
 
544
   va_start(args, fmt);
 
545
   rmon_mprintf_va(SPECIAL, fmt, args);
 
546
   va_end(args);
 
547
}
 
548
 
 
549
static void rmon_mprintf_va(int debug_class, const char* fmt, va_list args) {
 
550
   char msgbuf[RMON_BUF_SIZE];
 
551
   rmon_helper_t *helper = NULL;
 
552
#ifdef RMON_USE_CTX   
 
553
   rmon_ctx_t *ctx = rmon_get_thread_ctx();
 
554
   if (ctx) {
 
555
      ctx->mprintf(ctx, debug_class, fmt, args);
 
556
      return;
 
557
   }
 
558
#endif
 
559
   helper = rmon_get_helper();
 
560
   strcpy(msgbuf, empty);
 
561
   vsnprintf(&msgbuf[4], (RMON_BUF_SIZE) - 10 , fmt, args);
 
562
   if ((helper != NULL) && (helper->thread_name != NULL) && (strlen(helper->thread_name) > 0)) {
 
563
      mwrite(msgbuf, helper->thread_name);
 
564
   } else {
 
565
      mwrite(msgbuf, NULL);
 
566
   }
 
567
}
 
568
 
 
569
/****** rmon_macros/mwrite() ***************************************************
 
570
*  NAME
 
571
*     mwrite() -- Write monitoring message
 
572
*
 
573
*  SYNOPSIS
 
574
*     static void mwrite(char *message) 
 
575
*
 
576
*  FUNCTION
 
577
*     Write monitoring message. The message is written to the output stream
 
578
*     associated with 'rmon_fp'. The output stream is flushed immediately. 
 
579
*
 
580
*     A prefix is added to 'message'. It does consist of a trace sequence number,
 
581
*     the PID and the thread ID of the calling thread.
 
582
*
 
583
*  INPUTS
 
584
*     char *message - monitoring message
 
585
*
 
586
*  RESULT
 
587
*     void - none 
 
588
*
 
589
*  NOTES
 
590
*     MT-NOTE: 'mwrite()' is MT safe with exceptions. See introduction!
 
591
*     MT-NOTE:
 
592
*     MT-NOTE: It is guaranteed that the output of different threads is not
 
593
*     MT-NOTE: mingled.
 
594
*
 
595
*******************************************************************************/
 
596
static void mwrite(char *message, const char *thread_name)
 
597
{
 
598
   static u_long traceid = 0;
 
599
   unsigned long tmp_pid    = (unsigned long) getpid();
 
600
   unsigned long tmp_thread = (unsigned long) pthread_self();
 
601
 
 
602
#if !defined(DARWIN6)
 
603
   flockfile(rmon_fp);
 
604
#endif
 
605
 
 
606
#ifdef DEBUG_CLIENT_SUPPORT
 
607
   /* if there is a callback function, don't call standard function */
 
608
   RMON_CALLBACK_FUNC_LOCK();
 
609
   if (rmon_print_callback != NULL) {
 
610
      rmon_print_callback(message, traceid, tmp_pid, tmp_thread);
 
611
   }
 
612
   RMON_CALLBACK_FUNC_UNLOCK();
 
613
#endif
 
614
 
 
615
   if (thread_name != NULL) {
 
616
      fprintf(rmon_fp, "%6ld %6d %12.12s ", traceid, (int)tmp_pid, thread_name);
 
617
   } else {
 
618
      fprintf(rmon_fp, "%6ld %6d %ld ", traceid, (int)tmp_pid, (long int)tmp_thread);
 
619
   }
 
620
   fprintf(rmon_fp, "%s", message);
 
621
   fflush(rmon_fp);
 
622
 
 
623
   traceid++;
 
624
#if !defined(DARWIN6)
 
625
   funlockfile(rmon_fp);
 
626
#endif
 
627
 
 
628
   return;
 
629
} /* mwrite() */
 
630
 
 
631
/****** rmon_macros/set_debug_level_from_env() *********************************
 
632
*  NAME
 
633
*     set_debug_level_from_env() -- Set debug level from environment variable.
 
634
*
 
635
*  SYNOPSIS
 
636
*     static int set_debug_level_from_env(void) 
 
637
*
 
638
*  FUNCTION
 
639
*     Set debug level. Read environment variable "SGE_DEBUG_LEVEL" and use it
 
640
*     to initialize debug levels.
 
641
*
 
642
*  INPUTS
 
643
*     void - none 
 
644
*
 
645
*  RESULT
 
646
*     0 - successful
 
647
*     ENOENT - environment variable not set
 
648
*     EINVAL - unexpected format
 
649
*
 
650
*  NOTES
 
651
*     MT-NOTE: 'set_debug_level_from_env()' is MT safe with exceptions.
 
652
*     MT-NOTE:  See introduction!
 
653
*
 
654
*******************************************************************************/
 
655
static int set_debug_level_from_env(void)
 
656
{
 
657
   const char *env, *s = NULL;
 
658
   int i, l[N_LAYER];
 
659
 
 
660
   if ((env = getenv("SGE_DEBUG_LEVEL")) == NULL) {
 
661
      return ENOENT;
 
662
   }
 
663
 
 
664
   s = strdup(env);
 
665
   if ((i = sscanf(s, "%d%d%d%d%d%d%d%d", l, l+1, l+2, l+3, l+4, l+5, l+6, l+7)) != N_LAYER) {
 
666
      printf("%s\n", MSG_RMON_ILLEGALDBUGLEVELFORMAT);
 
667
      free((char *)s);
 
668
      return EINVAL;
 
669
   }
 
670
 
 
671
   for (i = 0; i < N_LAYER; i++) {
 
672
      rmon_mlputl(&RMON_DEBUG_ON, i, l[i]);
 
673
      rmon_mlputl(&RMON_DEBUG_ON_STORAGE, i, l[i]);
 
674
   }
 
675
 
 
676
   free((char *)s);
 
677
   return 0;
 
678
} /* set_debug_level_from_env() */
 
679
 
 
680
/****** rmon_macros/set_debug_target_from_env() *********************************
 
681
*  NAME
 
682
*     set_debug_target_from_env() -- Set debug target from environment variable.
 
683
*
 
684
*  SYNOPSIS
 
685
*     static int set_debug_target_from_env(void) 
 
686
*
 
687
*  FUNCTION
 
688
*     Set debug target. Read environment variable "SGE_DEBUG_TARGET" and use it
 
689
*     to initialize debug output target. 
 
690
*
 
691
*     'SGE_DEBUG_TARGET' may either be 'stdout', 'stderr' or a fully qualified
 
692
*     file name (that is file name and path). If a file name is given an 
 
693
*     already existing file with the same name will be overwritten.
 
694
*
 
695
*  INPUTS
 
696
*     void - none 
 
697
*
 
698
*  RESULT
 
699
*     0 - successful
 
700
*     EACCES - file name is invalid or unable to open file
 
701
*
 
702
*  NOTES
 
703
*     MT-NOTE: 'set_debug_target_from_env()' is MT safe with exceptions.
 
704
*     MT-NOTE: See introduction!
 
705
*
 
706
*******************************************************************************/
 
707
static int set_debug_target_from_env(void)
 
708
{
 
709
   const char *env, *s = NULL;
 
710
 
 
711
   if ((env = getenv("SGE_DEBUG_TARGET")) == NULL) {
 
712
      return 0;
 
713
   }
 
714
 
 
715
   s = strdup(env);
 
716
   if (strcmp(s, "stdout") == 0) {
 
717
         rmon_fp = stdout;
 
718
   } else if (strcmp(s, "stderr") == 0) {
 
719
         rmon_fp = stderr;
 
720
   } else if ((rmon_fp = fopen(s, "w")) == NULL) {
 
721
      rmon_fp = stderr;
 
722
      fprintf(rmon_fp, MSG_RMON_UNABLETOOPENXFORWRITING_S, s);
 
723
      fprintf(rmon_fp, MSG_RMON_ERRNOXY_DS, errno, strerror(errno));
 
724
      free((char *)s);
 
725
      return EINVAL;
 
726
   } 
 
727
 
 
728
   free((char *)s);
 
729
   return 0;
 
730
} /* set_debug_target_from_env() */
 
731