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

« back to all changes in this revision

Viewing changes to source/daemons/common/pdc.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
 *
 
34
 * pdc.c - Portable Data Collector Library and Test Module
 
35
 * 
 
36
 */
 
37
 
 
38
#if !defined(COMPILE_DC)
 
39
 
 
40
int verydummypdc;
 
41
 
 
42
#   ifdef MODULE_TEST
 
43
#include <stdio.h>
 
44
#include "basis_types.h"
 
45
#include "sge_language.h"
 
46
#include "sge_os.h"
 
47
#include "sge_log.h"
 
48
 
 
49
int main(int argc,char *argv[])
 
50
{
 
51
#ifdef __SGE_COMPILE_WITH_GETTEXT__  
 
52
   /* init language output for gettext() , it will use the right language */
 
53
   sge_init_language_func((gettext_func_type)        gettext,
 
54
                         (setlocale_func_type)      setlocale,
 
55
                         (bindtextdomain_func_type) bindtextdomain,
 
56
                         (textdomain_func_type)     textdomain);
 
57
   sge_init_language(NULL,NULL);  
 
58
#endif /* __SGE_COMPILE_WITH_GETTEXT__  */
 
59
   printf("sorry - no pdc for this architecture yet\n");
 
60
   return 0;
 
61
}
 
62
#endif
 
63
#else
 
64
 
 
65
#define _KMEMUSER 1
 
66
 
 
67
#include <stdio.h>
 
68
#include <string.h>
 
69
#include <unistd.h>
 
70
#include <stdlib.h>
 
71
#include <fcntl.h>
 
72
#include <signal.h>
 
73
#include <sys/types.h>
 
74
#include <sys/time.h>
 
75
 
 
76
#if defined(IRIX)
 
77
#include <sys/sysmp.h>
 
78
#include <sys/syssgi.h>
 
79
#include <sys/arsess.h>
 
80
#include <sys/procfs.h>
 
81
#include <sys/sysinfo.h>
 
82
#include <sys/tcpipstats.h>
 
83
#include <sys/systeminfo.h>
 
84
#include <sys/swap.h>
 
85
#endif
 
86
 
 
87
#if defined(ALPHA)
 
88
#   include <nlist.h>
 
89
#   include <sys/sysinfo.h>
 
90
#   include <machine/hal_sysinfo.h>
 
91
#   include <mach.h>
 
92
#   include </sys/include/vm/vm_perf.h>
 
93
#   include <paths.h>
 
94
#endif
 
95
 
 
96
#if defined(NECSX4) || defined(NECSX5)
 
97
#  include <nlist.h>
 
98
#  include <sys/var.h>
 
99
#  include <sys/types.h>
 
100
#  include <sys/time.h>
 
101
#  include <sys/resource.h>
 
102
#endif
 
103
 
 
104
#if defined(CRAY)
 
105
#include <sys/param.h>
 
106
#include <sys/table.h>
 
107
#include <sys/sysinfo.h>
 
108
#include <sys/pws.h>
 
109
#include <sys/session.h>
 
110
#include <sys/cred.h>
 
111
#include <sys/aoutdata.h>
 
112
#include <sys/proc.h>
 
113
#include <sys/map.h>
 
114
#include <sys/swap.h>
 
115
#include <sys/acct.h>
 
116
#include <sys/stat.h>
 
117
#include <sys/machcons.h>
 
118
#include "sge_unistd.h"
 
119
#endif
 
120
 
 
121
#if defined(AIX)
 
122
#  if defined(_ALL_SOURCE)
 
123
#     undef _ALL_SOURCE
 
124
#  endif
 
125
#include <procinfo.h>
 
126
#include <sys/types.h>
 
127
#endif
 
128
 
 
129
#if defined(FREEBSD)
 
130
#include <sys/param.h>
 
131
#include <sys/sysctl.h>
 
132
#include <sys/user.h>
 
133
 
 
134
#include <fcntl.h>
 
135
#include <kvm.h>
 
136
#include <limits.h>
 
137
#endif
 
138
 
 
139
#if defined(DARWIN)
 
140
#include <sys/sysctl.h>
 
141
#include <mach/mach.h>
 
142
#include <mach/task.h>
 
143
#include <mach/mach_init.h>
 
144
#endif
 
145
 
 
146
 
 
147
#if defined(HP1164)
 
148
#include <sys/param.h>
 
149
#include <sys/pstat.h>
 
150
#endif
 
151
 
 
152
#if defined(LINUX) || defined(ALPHA) || defined(IRIX) || defined(SOLARIS) || defined(DARWIN) || defined (FREEBSD) || defined(NETBSD) || defined(HP1164) || defined(AIX)
 
153
 
 
154
#include "sge_os.h"
 
155
#endif
 
156
 
 
157
#if defined(IRIX)
 
158
#  define F64 "%lld"
 
159
#  define S64 "%lli"
 
160
#elif defined(ALPHA)
 
161
#  define F64 "%ld"
 
162
#  define S64 "%li"
 
163
#elif defined(LINUX) || defined(SOLARIS)
 
164
#  define F64 "%ld"
 
165
#  define S64 "%li"
 
166
#else
 
167
#  define F64 "%d"
 
168
#  define S64 "%i"
 
169
#endif
 
170
 
 
171
#  if DEBUG
 
172
      static FILE *df = NULL;
 
173
#  endif
 
174
 
 
175
#ifdef SOLARIS
 
176
int getpagesize(void);
 
177
#endif
 
178
 
 
179
#include <errno.h>
 
180
#include "msg_sge.h"
 
181
#include "sgedefs.h"
 
182
#include "exec_ifm.h"
 
183
#include "pdc.h"
 
184
#include "procfs.h"
 
185
#include "basis_types.h"
 
186
#include "cull.h"
 
187
#include "ptf.h"
 
188
#include "sge_feature.h"
 
189
#include "sge_language.h"
 
190
#include "sgermon.h"
 
191
 
 
192
typedef struct {
 
193
   int job_collection_interval;  /* max job data collection interval */
 
194
   int prc_collection_interval;  /* max process data collection interval */
 
195
   int sys_collection_interval;  /* max system data collection interval */
 
196
} ps_config_t;
 
197
 
 
198
/* default collection intervals */
 
199
static ps_config_t ps_config = { 0, 0, 5 };
 
200
 
 
201
lnk_link_t job_list;
 
202
long pagesize;           /* size of a page of memory (probably 8k) */
 
203
int physical_memory;     /* size of real mem in KB                 */
 
204
char unixname[128];      /* the name of the booted kernel          */
 
205
 
 
206
#if defined(LINUX)
 
207
int sup_grp_in_proc;
 
208
#endif
 
209
 
 
210
#define INCPTR(type, ptr, nbyte) ptr = (type *)((char *)ptr + nbyte)
 
211
#define INCJOBPTR(ptr, nbyte) INCPTR(struct psJob_s, ptr, nbyte)
 
212
#define INCPROCPTR(ptr, nbyte) INCPTR(struct psProc_s, ptr, nbyte)
 
213
 
 
214
#if defined(LINUX)
 
215
   int sup_groups_in_proc (void) {
 
216
      return(sup_grp_in_proc);
 
217
   }
 
218
#endif
 
219
 
 
220
#if defined(LINUX) || defined(SOLARIS) || defined(ALPHA) || defined(FREEBSD) || defined(DARWIN)
 
221
 
 
222
void pdc_kill_addgrpid(gid_t add_grp_id, int sig,
 
223
   tShepherd_trace shepherd_trace)
 
224
{
 
225
#if defined(LINUX) || defined(SOLARIS) || defined(ALPHA)
 
226
   procfs_kill_addgrpid(add_grp_id, sig, shepherd_trace);      
 
227
#elif defined(FREEBSD)
 
228
   kvm_t *kd;
 
229
   int i, nprocs;
 
230
   struct kinfo_proc *procs;
 
231
   char kerrbuf[_POSIX2_LINE_MAX];
 
232
 
 
233
   kd = kvm_openfiles(NULL, NULL, NULL, O_RDONLY, kerrbuf);
 
234
   if (kd == NULL) {
 
235
#if DEBUG
 
236
      fprintf(stderr, "kvm_openfiles: error %s\n", kerrbuf);
 
237
#endif
 
238
      return;
 
239
   }
 
240
 
 
241
   procs = kvm_getprocs(kd, KERN_PROC_ALL, 0, &nprocs);
 
242
   if (procs == NULL) {
 
243
#if DEBUG
 
244
      fprintf(stderr, "kvm_getprocs: error %s\n", kvm_geterr(kd));
 
245
#endif
 
246
      kvm_close(kd);
 
247
      return;
 
248
   }
 
249
   for (; nprocs >= 0; nprocs--, procs++) {
 
250
      for (i = 0; i < procs->ki_ngroups; i++) {
 
251
         if (procs->ki_groups[i] == add_grp_id) {
 
252
            char err_str[256];
 
253
 
 
254
            if (procs->ki_uid != 0 && procs->ki_ruid != 0 &&
 
255
           procs->ki_svuid != 0 &&
 
256
           procs->ki_rgid != 0 && procs->ki_svgid != 0) {
 
257
               kill(procs->ki_pid, sig);
 
258
               sprintf(err_str, MSG_SGE_KILLINGPIDXY_UI ,
 
259
                       sge_u32c(procs->ki_pid), add_grp_id);
 
260
            } else {
 
261
               sprintf(err_str, MSG_SGE_DONOTKILLROOTPROCESSXY_UI ,
 
262
                       sge_u32c(procs->ki_pid), add_grp_id);
 
263
            }
 
264
            if (shepherd_trace)
 
265
               shepherd_trace(err_str);
 
266
         }
 
267
      }
 
268
   }
 
269
   kvm_close(kd);
 
270
#elif defined(DARWIN)
 
271
   int i, nprocs;
 
272
   struct kinfo_proc *procs;
 
273
   struct kinfo_proc *procs_begin;
 
274
   int mib[4] = { CTL_KERN, KERN_PROC, KERN_PROC_ALL, 0 };
 
275
   size_t bufSize = 0;
 
276
 
 
277
   if (sysctl(mib, 4, NULL, &bufSize, NULL, 0) < 0) {
 
278
      return;
 
279
   }
 
280
   if ((procs = (struct kinfo_proc *)malloc(bufSize)) == NULL) {
 
281
      return;
 
282
   }
 
283
   if (sysctl(mib, 4, procs, &bufSize, NULL, 0) < 0) {
 
284
      FREE(procs);
 
285
      return;
 
286
   }
 
287
   procs_begin = procs;
 
288
   nprocs = bufSize/sizeof(struct kinfo_proc);
 
289
 
 
290
   for (; nprocs >= 0; nprocs--, procs++) {
 
291
      for (i = 0; i < procs->kp_eproc.e_ucred.cr_ngroups; i++) {
 
292
         if (procs->kp_eproc.e_ucred.cr_groups[i] == add_grp_id) {
 
293
            char err_str[256];
 
294
 
 
295
            if (procs->kp_eproc.e_ucred.cr_uid != 0 && procs->kp_eproc.e_pcred.p_ruid != 0 &&
 
296
                procs->kp_eproc.e_pcred.p_svuid != 0 &&
 
297
                procs->kp_eproc.e_pcred.p_rgid != 0 && procs->kp_eproc.e_pcred.p_svgid != 0) {
 
298
               kill(procs->kp_proc.p_pid, sig);
 
299
               sprintf(err_str, MSG_SGE_KILLINGPIDXY_UI ,
 
300
                  sge_u32c(procs->kp_proc.p_pid), add_grp_id);
 
301
            } else {
 
302
               sprintf(err_str, MSG_SGE_DONOTKILLROOTPROCESSXY_UI ,
 
303
                  sge_u32c(procs->kp_proc.p_pid), add_grp_id);
 
304
            }
 
305
            if (shepherd_trace)
 
306
               shepherd_trace(err_str);
 
307
         }
 
308
      }
 
309
   }
 
310
   FREE(procs_begin)
 
311
#endif
 
312
}
 
313
#endif
 
314
 
 
315
lnk_link_t * find_job(JobID_t jid) {
 
316
   lnk_link_t *curr;
 
317
 
 
318
   for (curr=job_list.next; curr != &job_list; curr=curr->next) {
 
319
      if (jid == LNK_DATA(curr, job_elem_t, link)->job.jd_jid)
 
320
         return curr;
 
321
   }
 
322
   return NULL;
 
323
}
 
324
 
 
325
#if defined(NECSX4) || defined(NECSX5)
 
326
long
 
327
getpagesize(void)
 
328
{
 
329
   return sysconf(_SC_PAGESIZE);
 
330
}
 
331
 
 
332
#  define MICROSEC2SECS(msecs) ((double)(msecs)/(double)1000000)
 
333
#endif   
 
334
 
 
335
#if defined(IRIX)
 
336
 
 
337
/*
 
338
 * This is a structure containing all the fields that we need
 
339
 * out of the arsess_t structure.  It is filled in by the
 
340
 * pdc_get_arsess() and pdc_get_arsess64() routines.
 
341
 */
 
342
 
 
343
typedef struct {
 
344
    ash_t  ash;
 
345
    pid_t  pid;
 
346
    uint64 prid;
 
347
    uint64 start;
 
348
    uint64 refcnt;
 
349
    uint64 utime;
 
350
    uint64 stime;
 
351
    uint64 bwtime;
 
352
    uint64 rwtime;
 
353
    uint64 qwtime;
 
354
    uint64 mem;
 
355
    uint64 chr;
 
356
    uint64 chw;
 
357
} pdc_arsess_t;
 
358
 
 
359
int
 
360
pdc_get_arsess(pdc_arsess_t *parse, arsess_t *arse)
 
361
{
 
362
   parse->ash = arse->as_handle;
 
363
   parse->pid = arse->as_pid;
 
364
   parse->prid = arse->as_prid;
 
365
   parse->start = arse->as_start;
 
366
   parse->refcnt = arse->as_refcnt;
 
367
   parse->utime = arse->as_timers.ac_utime;
 
368
   parse->stime = arse->as_timers.ac_stime;
 
369
   parse->bwtime = arse->as_timers.ac_bwtime;
 
370
   parse->rwtime = arse->as_timers.ac_rwtime;
 
371
   parse->qwtime = arse->as_timers.ac_qwtime;
 
372
   parse->mem = arse->as_counts.ac_mem;
 
373
   parse->chr = arse->as_counts.ac_chr;
 
374
   parse->chw = arse->as_counts.ac_chw;
 
375
   return 0;
 
376
}
 
377
 
 
378
/*
 
379
 * define a 64-bit version of arsess_t for use on 64-bit IRIX
 
380
 */
 
381
 
 
382
typedef struct arsess64 {
 
383
        ash_t           as_handle;      /* array session handle */
 
384
        prid_t          as_prid;        /* project ID */
 
385
 
 
386
        lock_t          as_lock;        /* update lock */
 
387
#ifdef notdef
 
388
        struct arsess   *as_next;       /* next arsess in act/free list */
 
389
        struct arsess   *as_prev;       /* previous arsess in act list */
 
390
#else
 
391
        __uint64_t      as_next;
 
392
        __uint64_t      as_prev;
 
393
#endif
 
394
        int             as_refcnt;      /* reference count */
 
395
        time_t          as_start;       /* start time (secs since 1970) */
 
396
        time_t          as_ticks;       /* lbolt at start */
 
397
        pid_t           as_pid;         /* pid that started this session */
 
398
        ushort_t        as_flag;        /* various flags */
 
399
        char            as_nice;        /* initial nice value of as_pid */
 
400
 
 
401
        /* Accounting data */
 
402
        acct_spi_t      as_spi;         /* Service Provider Information */
 
403
        acct_timers_t   as_timers;      /* accounting timers */
 
404
        acct_counts_t   as_counts;      /* accounting counters */
 
405
 
 
406
        __uint64_t      as_fill;        /* fill for 64-bit structure */
 
407
} arsess64_t;
 
408
 
 
409
 
 
410
typedef struct arsess65 {
 
411
        ash_t           as_handle;      /* array session handle */
 
412
        prid_t          as_prid;        /* project ID */
 
413
        int             as_refcnt;      /* reference count */
 
414
        time_t          as_start;       /* start time (secs since 1970) */
 
415
        time_t          as_ticks;       /* lbolt at start */
 
416
        pid_t           as_pid;         /* pid that started this session */
 
417
        int             as_spilen;      /* length of Service Provider Info */
 
418
        ushort_t        as_flag;        /* various flags */
 
419
        char            as_nice;        /* initial nice value of as_pid */
 
420
        char            as_rsrv1[985];  /*   reserved */
 
421
 
 
422
        /* Accounting data */
 
423
        char            as_spi[1024];   /* Service Provider Info */
 
424
        acct_timers_t   as_timers;      /* accounting timers */
 
425
        acct_counts_t   as_counts;      /* accounting counters */
 
426
        char            as_rsrv2[1888]; /*   reserved */
 
427
} arsess65_t;
 
428
 
 
429
 
 
430
int pdc_get_arsess65(pdc_arsess_t *parse, arsess_t *arsein)
 
431
{
 
432
   arsess65_t *arse = (arsess65_t *)arsein;
 
433
 
 
434
   parse->ash = arse->as_handle;
 
435
   parse->pid = arse->as_pid;
 
436
   parse->prid = arse->as_prid;
 
437
   parse->start = arse->as_start;
 
438
   parse->refcnt = arse->as_refcnt;
 
439
   parse->utime = arse->as_timers.ac_utime;
 
440
   parse->stime = arse->as_timers.ac_stime;
 
441
   parse->bwtime = arse->as_timers.ac_bwtime;
 
442
   parse->rwtime = arse->as_timers.ac_rwtime;
 
443
   parse->qwtime = arse->as_timers.ac_qwtime;
 
444
   parse->mem = arse->as_counts.ac_mem;
 
445
   parse->chr = arse->as_counts.ac_chr;
 
446
   parse->chw = arse->as_counts.ac_chw;
 
447
   return 0;
 
448
}
 
449
 
 
450
 
 
451
int pdc_get_arsess64(pdc_arsess_t *parse, arsess_t *arsein)
 
452
{
 
453
   arsess64_t *arse = (arsess64_t *)arsein;
 
454
 
 
455
   parse->ash = arse->as_handle;
 
456
   parse->pid = arse->as_pid;
 
457
   parse->prid = arse->as_prid;
 
458
   parse->start = arse->as_start;
 
459
   parse->refcnt = arse->as_refcnt;
 
460
   parse->utime = arse->as_timers.ac_utime;
 
461
   parse->stime = arse->as_timers.ac_stime;
 
462
   parse->bwtime = arse->as_timers.ac_bwtime;
 
463
   parse->rwtime = arse->as_timers.ac_rwtime;
 
464
   parse->qwtime = arse->as_timers.ac_qwtime;
 
465
   parse->mem = arse->as_counts.ac_mem;
 
466
   parse->chr = arse->as_counts.ac_chr;
 
467
   parse->chw = arse->as_counts.ac_chw;
 
468
   return 0;
 
469
}
 
470
#elif defined(ALPHA)
 
471
 
 
472
static struct nlist mem_nl[] = {
 
473
   { "vm_perfsum" }, /* PERFSUM */
 
474
   { 0 },
 
475
};
 
476
int kmem_fd = -1;
 
477
 
 
478
#define PERFSUM      0
 
479
 
 
480
int readk(off_t where, char *addr, int size) {
 
481
   if (lseek(kmem_fd, where, SEEK_SET) == -1)
 
482
      return -1;
 
483
   if (read(kmem_fd, addr, size) == -1)
 
484
      return -1;
 
485
   return 0;
 
486
}
 
487
 
 
488
#elif defined(CRAY)
 
489
 
 
490
#ifndef MAX
 
491
#define MAX(a,b) ((a)>(b)?(a):(b))
 
492
#endif
 
493
 
 
494
int
 
495
getpagesize(void)
 
496
{
 
497
   return 4096;
 
498
}
 
499
 
 
500
int
 
501
read_kernel_table(char *name, void **table, long *size, int *entries)
 
502
{
 
503
   struct tbs tinfo;
 
504
   long tsize;
 
505
 
 
506
   if (tabinfo(name, &tinfo) < 0) {
 
507
      return -1;
 
508
   }
 
509
 
 
510
   tsize = tinfo.head + (tinfo.ent * tinfo.len);
 
511
   if (tsize > *size) {
 
512
      if (*table) free(*table);
 
513
      *table = malloc(tsize);
 
514
      if (*table == NULL) {
 
515
         return -1;
 
516
      }
 
517
      memset(*table, 0, tsize);
 
518
      *size = tsize;
 
519
   }
 
520
 
 
521
   if (tabread(name, (char *)*table, tsize, 0) == -1) {
 
522
      return -1;
 
523
   }
 
524
 
 
525
   if (entries) *entries = tinfo.ent;
 
526
 
 
527
   return 0;
 
528
}
 
529
 
 
530
time_t
 
531
cvt_comp_t(comp_t comp)
 
532
{
 
533
   time_t frac;
 
534
   int exp;
 
535
   if (comp == 0x1fffff) return -1;
 
536
   frac = comp & 0xffff;
 
537
   exp = (comp >> 16) & 0x1f;
 
538
   while (exp-- > 0)
 
539
      frac <<= 3;
 
540
   return frac;
 
541
}
 
542
 
 
543
#define PACCT "/usr/adm/acct/day/pacct"
 
544
 
 
545
#define CLOCKS2SECS(clocks) ((double)(clocks)/(double)clk_tck)
 
546
 
 
547
/*
 
548
 * read_pacct reads end of process and end of job records from the process
 
549
 * accounting (pacct) file. The process records contain the memory integral
 
550
 * and characters transferred by the process during its lifetime. This
 
551
 * information is not available in the kernel. Instead, it is stored in
 
552
 * the user area of the process while it is running. The end of job
 
553
 * record indicates that a job has completed. This routine is designed
 
554
 * to keep the pacct file open. To handle switching pacct files and to
 
555
 * handle a corrupted pacct file. If it encounters a corrupted pacct file
 
556
 * it will skip reading until a new pacct file is available. There is a
 
557
 * race condition that read_pacct must protect itself from. When the
 
558
 * shepherd forks the job, the O.S. job ID is set and the job ID is
 
559
 * communicated back to the execd through a file. Once the job ID is
 
560
 * read from the file, then it is communicated to the PDC which will
 
561
 * then recognize any pacct records for processes belonging to the job.
 
562
 * However, while the execd is waiting to read the file, processes running
 
563
 * in the job will likely run and complete and process completion records
 
564
 * will be written to the pacct file. If the PDC reads these pacct records
 
565
 * before the job ID has been registered with the PDC, then these pacct
 
566
 * records will be missed and the memory and I/O usage for the processes
 
567
 * will not be accounted for in the job usage totals. To prevent this, the
 
568
 * PDC will precreate job elements for any processes which it reads in the
 
569
 * pacct data for which a job element does not already exist. If these
 
570
 * precreated jobs are not monitored with a psWatchJob() call within 30
 
571
 * seconds, they will be deleted.
 
572
 */
 
573
 
 
574
#define READ_PACCT_WAIT 0
 
575
 
 
576
int
 
577
read_pacct(lnk_link_t *job_list, time_t time_stamp)
 
578
{
 
579
   union acct acct;
 
580
   struct achead hdr;
 
581
   unsigned char flag;
 
582
   int hdrsize = sizeof(struct achead)+1;
 
583
   int bytes;
 
584
   int count = 0;
 
585
   int jobcount = 0;
 
586
   SGE_STRUCT_STAT pstat;
 
587
   int more_records = 1;
 
588
   int in_window = 1;
 
589
   time_t end_time;
 
590
   lnk_link_t *curr;
 
591
 
 
592
   static int clk_tck;
 
593
   static int corrupted;
 
594
   static fpos_t offset;
 
595
   static int newfile;
 
596
   static FILE *fp = NULL;
 
597
   static SGE_INO_T pacct_inode;
 
598
 
 
599
#  if DEBUG
 
600
      if (df == NULL)
 
601
         df = fopen("/tmp/pacct.out", "w");
 
602
#  endif
 
603
 
 
604
   if (clk_tck == 0)
 
605
      clk_tck = sysconf(_SC_CLK_TCK);
 
606
 
 
607
   /*
 
608
    * get inode of pacct file. If it has changed, we know
 
609
    * the old pacct file has been deleted and a new one
 
610
    * has been created. However there may still be records
 
611
    * in the old file that we have not completed reading
 
612
    * so for now we set the newfile flag and will try to
 
613
    * read to the end of the old file before switching to
 
614
    * the new pacct file.
 
615
    */
 
616
 
 
617
   if (SGE_STAT(PACCT, &pstat)==0 && pacct_inode != pstat.st_ino)
 
618
      newfile = 1;
 
619
 
 
620
   /* don't read corrupted pacct file */
 
621
 
 
622
   if (corrupted && !newfile) {
 
623
      return 0;
 
624
   }
 
625
 
 
626
   if (fp) {
 
627
      fsetpos(fp, &offset);
 
628
   }
 
629
 
 
630
   while (more_records) {
 
631
 
 
632
      while(fp && !feof(fp) && in_window && !corrupted) {
 
633
 
 
634
         if (fread(&hdr, sizeof(hdr), 1, fp) != 1) {
 
635
            if (feof(fp))
 
636
               break;
 
637
            corrupted = 1;
 
638
            return -1;
 
639
         }
 
640
 
 
641
         if (fread(&flag, 1, 1, fp) != 1) {
 
642
            corrupted = 1;
 
643
            return -1;
 
644
         }
 
645
 
 
646
         if (hdr.ah_size > sizeof(acct)) {
 
647
            corrupted = 1;
 
648
            return -1;
 
649
         }
 
650
 
 
651
         bytes = hdr.ah_size - hdrsize;
 
652
 
 
653
         if (fread((char *)&acct + hdrsize, bytes, 1, fp) != 1) {
 
654
            corrupted = 1;
 
655
            return -1;
 
656
         }
 
657
 
 
658
         if ((flag & ACCTR) == ACCTBASE) {
 
659
            job_elem_t *job_elem;
 
660
            psJob_t *job;
 
661
 
 
662
            count++;
 
663
 
 
664
#           if 0
 
665
               printf("%d. pid=%d uid=%d gid=%d btime=%d utime=%d stime=%d "
 
666
                      "etime=%d\n", count,
 
667
                      acct.acctbs.ac_pid, acct.acctbs.ac_uid,
 
668
                      acct.acctbs.ac_gid, acct.acctbs.ac_btime,
 
669
                      (int)CLOCKS2SECS(cvt_comp_t(acct.acctbs.ac_utime)),
 
670
                      (int)CLOCKS2SECS(cvt_comp_t(acct.acctbs.ac_stime)),
 
671
                      (int)CLOCKS2SECS(cvt_comp_t(acct.acctbs.ac_etime)));
 
672
#           endif
 
673
 
 
674
            end_time = acct.acctbs.ac_btime +
 
675
                  (int)CLOCKS2SECS(cvt_comp_t(acct.acctbs.ac_etime));
 
676
 
 
677
            /* skip pacct records more than a day old */
 
678
            if (end_time < (time_stamp - 60*60*24))
 
679
               continue;
 
680
 
 
681
            in_window = (end_time < (time_stamp - READ_PACCT_WAIT));
 
682
 
 
683
            if (!in_window)
 
684
               continue;
 
685
 
 
686
            if (curr=find_job(acct.acctbs.ac_jobid)) {
 
687
               job_elem = LNK_DATA(curr, job_elem_t, link);
 
688
               job = &job_elem->job;
 
689
 
 
690
#              if DEBUG
 
691
 
 
692
                  fprintf(df, "%d job=%d jid=%d pid=%d uid=%d gid=%d btime=%d "
 
693
                          "utime=%d stime=%d etime=%d mem=%d chars=%d\n", 
 
694
                          time_stamp, job->jd_jid, acct.acctbs.ac_jobid,
 
695
                          acct.acctbs.ac_pid, acct.acctbs.ac_uid,
 
696
                          acct.acctbs.ac_gid, acct.acctbs.ac_btime,
 
697
                          (int)CLOCKS2SECS(cvt_comp_t(acct.acctbs.ac_utime)),
 
698
                          (int)CLOCKS2SECS(cvt_comp_t(acct.acctbs.ac_stime)),
 
699
                          (int)CLOCKS2SECS(cvt_comp_t(acct.acctbs.ac_etime)),
 
700
                          cvt_comp_t(acct.acctbs.ac_mem)*(NBPC/1024)/OS_HZ,
 
701
                          cvt_comp_t(acct.acctbs.ac_io));
 
702
 
 
703
                  fflush(df);
 
704
 
 
705
#              endif
 
706
 
 
707
            } else {
 
708
 
 
709
               /* If the job is not in the list, add it just in case
 
710
                  it is later monitored. If this job is not monitored
 
711
                  within 30 seconds of when it was added, it will be
 
712
                  deleted. This allows us to account for usage for
 
713
                  processes which end before the psWatchJob is called
 
714
                  and for processes which end while the execd is down. */
 
715
 
 
716
#              if DEBUG
 
717
 
 
718
                  fprintf(df, "%d precreating "F64"\n", time_stamp,
 
719
                          acct.acctbs.ac_jobid);
 
720
                  fflush(df);
 
721
 
 
722
#              endif
 
723
 
 
724
               job_elem = (job_elem_t *)malloc(sizeof(job_elem_t));
 
725
               job = &job_elem->job;
 
726
               memset(job_elem, 0, sizeof(job_elem_t));
 
727
               job_elem->precreated = time_stamp;
 
728
               job_elem->starttime = acct.acctbs.ac_btime;
 
729
               job_elem->job.jd_jid = acct.acctbs.ac_jobid;
 
730
               job_elem->job.jd_length = sizeof(psJob_t);
 
731
               LNK_INIT(&job_elem->procs);
 
732
               LNK_INIT(&job_elem->arses);
 
733
               /* add to job list */
 
734
               LNK_ADD(job_list->prev, &job_elem->link);
 
735
 
 
736
            }
 
737
 
 
738
            /* set earliest start time */
 
739
            if (acct.acctbs.ac_btime < job_elem->starttime)
 
740
               job_elem->starttime = acct.acctbs.ac_btime;
 
741
 
 
742
            /* memory used (integral) in K seconds */
 
743
            job->jd_mem +=
 
744
                  cvt_comp_t(acct.acctbs.ac_mem)*(NBPC/1024)/OS_HZ;
 
745
 
 
746
            /* characters moved */
 
747
            job->jd_chars += cvt_comp_t(acct.acctbs.ac_io);
 
748
 
 
749
         } else if ((flag & ACCTR) == ACCTEOJ) {
 
750
 
 
751
            jobcount++;
 
752
 
 
753
#           if 0
 
754
               printf("%d. jid=%d maxvmem=%d etime=%d\n", jobcount,
 
755
                      acct.accteoj.ace_jobid, acct.accteoj.ace_himem,
 
756
                      acct.accteoj.ace_etime);
 
757
#           endif
 
758
 
 
759
            end_time = acct.accteoj.ace_etime;
 
760
 
 
761
            /* skip pacct records more than a day old */
 
762
            if (end_time < (time_stamp - 60*60*24))
 
763
               continue;
 
764
 
 
765
            in_window = (end_time < (time_stamp - READ_PACCT_WAIT));
 
766
 
 
767
            if (!in_window)
 
768
               continue;
 
769
 
 
770
            if (curr=find_job(acct.accteoj.ace_jobid)) {
 
771
               job_elem_t *job_elem = LNK_DATA(curr, job_elem_t, link);
 
772
               psJob_t *job = &job_elem->job;
 
773
               uint64 himem;
 
774
 
 
775
               /* mark job as complete */
 
776
               job->jd_refcnt = 0;
 
777
 
 
778
               /* elapsed time */
 
779
               job->jd_etime = acct.accteoj.ace_etime - job_elem->starttime;
 
780
               if (job->jd_etime < 0) job->jd_etime = 0;
 
781
 
 
782
               /* high-water memory size */
 
783
               himem = cvt_comp_t(acct.accteoj.ace_himem)*NBPC;
 
784
               job->jd_himem = MAX(job->jd_himem, himem);
 
785
 
 
786
               /* file system blocks consumed */
 
787
               job->jd_fsblks = acct.accteoj.ace_fsblkused;
 
788
            }
 
789
 
 
790
         }
 
791
 
 
792
              fgetpos(fp, &offset);
 
793
      }
 
794
 
 
795
      /*
 
796
       * If we are at the end of the old (deleted) pacct file
 
797
       * or the pacct file is not open or the old file was corrupt,
 
798
       * close the old pacct file and open the new one.
 
799
       */
 
800
 
 
801
      if (newfile && (fp==NULL || feof(fp) || corrupted)) {
 
802
 
 
803
         if (fp) {
 
804
            FCLOSE(fp);
 
805
         }
 
806
         if (SGE_STAT(PACCT, &pstat)==0 && (fp = fopen(PACCT, "r"))) {
 
807
            pacct_inode = pstat.st_ino;
 
808
            newfile = 0;
 
809
            corrupted = 0;
 
810
                 fgetpos(fp, &offset);
 
811
         } else {
 
812
            return -1;
 
813
         }
 
814
 
 
815
      }
 
816
 
 
817
      more_records = fp && !feof(fp) && in_window;
 
818
   }
 
819
 
 
820
   return 0;
 
821
FCLOSE_ERROR:
 
822
   return -1;
 
823
}
 
824
 
 
825
#endif
 
826
 
 
827
static int
 
828
get_gmt(void)
 
829
{
 
830
   struct timeval now;
 
831
 
 
832
#ifdef SOLARIS
 
833
   gettimeofday(&now, NULL);
 
834
#else
 
835
   struct timezone tzp;
 
836
   gettimeofday(&now, &tzp);
 
837
#endif
 
838
 
 
839
   return now.tv_sec;
 
840
}
 
841
 
 
842
#ifdef PDC_STANDALONE
 
843
static psSys_t sysdata;
 
844
 
 
845
#if defined(IRIX) || defined(CRAY)
 
846
static struct {
 
847
   int initialized;
 
848
   double utime;
 
849
   double stime;
 
850
   double itime;
 
851
   double srtime;
 
852
   double wtime;
 
853
   double ttime;
 
854
} base;
 
855
#endif
 
856
#endif
 
857
 
 
858
void
 
859
psSetCollectionIntervals(int jobi, int prci, int sysi)
 
860
{
 
861
   if (jobi != -1)
 
862
      ps_config.job_collection_interval = jobi;
 
863
 
 
864
   if (prci != -1)
 
865
      ps_config.prc_collection_interval = prci;
 
866
 
 
867
   if (sysi != -1)
 
868
      ps_config.sys_collection_interval = sysi;
 
869
}
 
870
 
 
871
 
 
872
#ifdef PDC_STANDALONE
 
873
int psRetrieveSystemData(void)
 
874
{
 
875
#if defined(IRIX)
 
876
   struct sysinfo si;
 
877
   struct rminfo rmi;
 
878
   struct minfo mi;
 
879
#ifdef ever_needed
 
880
   struct dinfo di;
 
881
   struct syserr se;
 
882
   struct kna k;
 
883
#endif
 
884
   off_t swapmax, swapvirt, swaprsrv, swaptot, swapfree;
 
885
   double utime, stime, itime, srtime, wtime, ttime;
 
886
   double period;
 
887
   static uint64 prev_runque, prev_runocc, prev_swpque, prev_swpocc;
 
888
   long clock_tick = sysconf(_SC_CLK_TCK);
 
889
#elif defined(ALPHA)
 
890
   struct vm_statistics vmstats;
 
891
#elif defined(CRAY)
 
892
   static struct sysinfo *si;
 
893
   static long si_size;
 
894
   static struct pw *pw;
 
895
   static long pw_size;
 
896
   static struct swapper *sw;
 
897
   static long sw_size;
 
898
   double utime, stime, itime, srtime, wtime, ttime;
 
899
   double period;
 
900
   static int prev_runque, prev_runocc, prev_swpque, prev_swpocc;
 
901
   int i;
 
902
   static int clk_tck;
 
903
#endif
 
904
   time_t time_stamp = get_gmt();
 
905
   time_t prev_time_stamp;
 
906
   static time_t next;
 
907
 
 
908
   if (time_stamp <= next) {
 
909
      return 0;
 
910
   }
 
911
   next = time_stamp + ps_config.sys_collection_interval;
 
912
 
 
913
   prev_time_stamp = sysdata.sys_tstamp;
 
914
 
 
915
   /* Time of last snap */
 
916
   sysdata.sys_tstamp = time_stamp;
 
917
 
 
918
#if defined(IRIX)
 
919
 
 
920
 
 
921
   if (sysmp(MP_SAGET, MPSA_SINFO, &si, sizeof(si))<0) {
 
922
      return -1;
 
923
   }
 
924
 
 
925
   if (sysmp(MP_SAGET, MPSA_RMINFO, &rmi, sizeof(rmi))<0) {
 
926
      return -1;
 
927
   }
 
928
 
 
929
   if (sysmp(MP_SAGET, MPSA_MINFO, &mi, sizeof(mi))<0) {
 
930
      return -1;
 
931
   }
 
932
 
 
933
#ifdef ever_needed
 
934
 
 
935
   if (sysmp(MP_SAGET, MPSA_SERR, &se, sizeof(se))<0) {
 
936
      return -1;
 
937
   }
 
938
 
 
939
   if (sysmp(MP_SAGET, MPSA_DINFO, &di, sizeof(di))<0) {
 
940
      return -1;
 
941
   }
 
942
 
 
943
   if (sysmp(MP_SAGET, MPSA_TCPIPSTATS, &k, sizeof(k))<0) {
 
944
      return -1;
 
945
   }
 
946
 
 
947
#endif
 
948
 
 
949
   if (swapctl(SC_GETFREESWAP, &swapfree)<0) {
 
950
      return -1;
 
951
   }
 
952
   
 
953
   if (swapctl(SC_GETSWAPMAX, &swapmax)<0) {
 
954
      return -1;
 
955
   }
 
956
   
 
957
   if (swapctl(SC_GETSWAPVIRT, &swapvirt)<0) {
 
958
      return -1;
 
959
   }
 
960
   
 
961
   if (swapctl(SC_GETRESVSWAP, &swaprsrv)<0) {
 
962
      return -1;
 
963
   }
 
964
   
 
965
   if (swapctl(SC_GETSWAPTOT, &swaptot)<0) {
 
966
      return -1;
 
967
   }
 
968
 
 
969
   /* convert CPU time values to double CPU seconds */
 
970
   utime = (double)si.cpu[CPU_USER] / (double)clock_tick;
 
971
   stime = (double)si.cpu[CPU_KERNEL] / (double)clock_tick;
 
972
   itime = (double)si.cpu[CPU_IDLE] / (double)clock_tick;
 
973
   srtime = 0;
 
974
   wtime = (double)si.cpu[CPU_WAIT] / (double)clock_tick;
 
975
   ttime = ((double)si.cpu[CPU_IDLE] + (double)si.cpu[CPU_USER] +
 
976
            (double)si.cpu[CPU_KERNEL] + (double)si.cpu[CPU_WAIT] +
 
977
            (double)si.cpu[CPU_SXBRK] + (double)si.cpu[CPU_INTR]) /
 
978
            (double)clock_tick;
 
979
 
 
980
   /* if this is the first time, intialize base CPU time values */
 
981
 
 
982
   if (!base.initialized) {
 
983
      base.initialized = 1;
 
984
      base.utime = utime;
 
985
      base.stime = stime;
 
986
      base.itime = itime;
 
987
      base.srtime = srtime;
 
988
      base.wtime = wtime;
 
989
      base.ttime = ttime;
 
990
      prev_runque = si.runque;
 
991
      prev_runocc = si.runocc;
 
992
      prev_swpque = si.swpque;
 
993
      prev_swpocc = si.swpocc;
 
994
   }
 
995
 
 
996
   /* total cpu time avail (this int) */
 
997
   sysdata.sys_ttime = ttime - (base.ttime + sysdata.sys_ttimet);
 
998
 
 
999
   /* total cpu time avail (since start) */
 
1000
   sysdata.sys_ttimet = ttime - base.ttime;
 
1001
 
 
1002
   /* user time this interval */
 
1003
   sysdata.sys_utime = utime - (base.utime + sysdata.sys_utimet);
 
1004
 
 
1005
   /* user time (since start) */
 
1006
   sysdata.sys_utimet = utime - base.utime;
 
1007
 
 
1008
   /* system time this interval */
 
1009
   sysdata.sys_stime = stime - (base.stime + sysdata.sys_stimet);
 
1010
 
 
1011
   /* system time (since start) */
 
1012
   sysdata.sys_stimet = stime - base.stime;
 
1013
 
 
1014
   /* idle time this interval */
 
1015
   sysdata.sys_itime = itime - (base.itime + sysdata.sys_itimet);
 
1016
 
 
1017
   /* idle time (since start) */
 
1018
   sysdata.sys_itimet = itime - base.itime;
 
1019
 
 
1020
   /* srun wait this interval */
 
1021
   sysdata.sys_srtime = srtime - (base.srtime + sysdata.sys_srtimet);
 
1022
 
 
1023
   /* srun wait (since start) */
 
1024
   sysdata.sys_srtimet = srtime - base.srtime;
 
1025
 
 
1026
   /* I/O wait time this interval */
 
1027
   sysdata.sys_wtime = wtime - (base.wtime + sysdata.sys_wtimet);
 
1028
 
 
1029
   /* I/O wait time (since start) */
 
1030
   sysdata.sys_wtimet = wtime - base.wtime;
 
1031
 
 
1032
   /* Total Swap space available */
 
1033
   sysdata.sys_swp_total = (uint64)swaptot * 512;
 
1034
 
 
1035
   /* Swap space free */
 
1036
   sysdata.sys_swp_free = (uint64)swapfree * 512;
 
1037
 
 
1038
   /* Swap space in use (bytes) */
 
1039
   sysdata.sys_swp_used = ((uint64)swaptot - (uint64)swapfree) * 512;
 
1040
 
 
1041
   /* swaprsrv is the amount of space currently reserved by processes 
 
1042
      which is not the same as that which is in use by processes 
 
1043
      see swapctl(SC_GETRESVSWAP) */
 
1044
 
 
1045
   /* Swap space reserved (bytes) */
 
1046
   sysdata.sys_swp_rsvd = (uint64)swaprsrv * 512;
 
1047
 
 
1048
   /* Virtual Swap space avail (bytes) */
 
1049
   sysdata.sys_swp_virt = (uint64)swapvirt * 512;
 
1050
 
 
1051
   /* Swap rate in bytes/second */
 
1052
   sysdata.sys_swp_rate = 0;
 
1053
 
 
1054
   /* Memory available (unused, free) */
 
1055
   sysdata.sys_mem_avail = ((uint64)rmi.freemem + (uint64)rmi.chunkpages) *
 
1056
         pagesize;
 
1057
 
 
1058
   /* Memory in use (bytes) (SVD 10/19/98 - s/rmi.availrmem/rmi.physmem/) */ 
 
1059
   sysdata.sys_mem_used = (uint64)rmi.physmem*pagesize - sysdata.sys_mem_avail;
 
1060
 
 
1061
   /* Memory + swap used (bytes) */
 
1062
   sysdata.sys_mswp_used = sysdata.sys_swp_used + sysdata.sys_mem_used;
 
1063
 
 
1064
   /* Memory + swap avail (bytes) */
 
1065
   sysdata.sys_mswp_avail = sysdata.sys_swp_free + sysdata.sys_mem_avail;
 
1066
 
 
1067
   if ((time_stamp - prev_time_stamp) > 0)
 
1068
      period = (time_stamp - prev_time_stamp);
 
1069
   else
 
1070
      period = 1.0;
 
1071
   
 
1072
   /* Swap "Occ" delta */
 
1073
   sysdata.sys_swpocc = ((double)si.swpocc - prev_swpocc) / period;
 
1074
   prev_swpocc = si.swpocc;
 
1075
 
 
1076
   /* Swap Queue delta */
 
1077
   sysdata.sys_swpque = ((double)si.swpque - prev_swpque) / period;
 
1078
   prev_swpque = si.swpque;
 
1079
 
 
1080
   /* Run "Occ" delta */
 
1081
   sysdata.sys_runocc = ((double)si.runocc - prev_runocc) / period;
 
1082
   prev_runocc = si.runocc;
 
1083
 
 
1084
   /* Run Queue delta */
 
1085
   sysdata.sys_runque = ((double)si.runque - prev_runque) / period;
 
1086
   if (sysdata.sys_ncpus > 1) sysdata.sys_runque /= sysdata.sys_ncpus;
 
1087
   prev_runque = si.runque;
 
1088
 
 
1089
   /* characters read */
 
1090
   sysdata.sys_readch = si.readch;
 
1091
 
 
1092
   /* characters written */
 
1093
   sysdata.sys_writech = si.writech;
 
1094
 
 
1095
#elif defined(ALPHA)
 
1096
   {
 
1097
      struct vm_perf   perf;
 
1098
   
 
1099
      /* memory information */
 
1100
      /* this is possibly bogus - we work out total # pages by */
 
1101
      /* adding up the free, active, inactive, wired down, and */
 
1102
      /* zero filled. Anyone who knows a better way, TELL ME!  */
 
1103
      /* Change: dont use zero filled. */
 
1104
 
 
1105
      if (mem_nl[PERFSUM].n_value) {
 
1106
         if (readk((off_t)mem_nl[PERFSUM].n_value,(char *)&perf,sizeof perf))
 
1107
         /* Virtual Swap space avail (bytes) */
 
1108
         sysdata.sys_swp_free = perf.vpf_swapspace*pagesize;
 
1109
      }
 
1110
 
 
1111
      (void) vm_statistics(current_task(),&vmstats);
 
1112
 
 
1113
      /* free mem */
 
1114
      sysdata.sys_mem_avail = vmstats.free_count*pagesize; 
 
1115
 
 
1116
      /* Memory in use (bytes) */
 
1117
      sysdata.sys_mem_used = (physical_memory*1024) - sysdata.sys_mem_avail;
 
1118
 
 
1119
      /* Swap space reserved (bytes) */
 
1120
      sysdata.sys_swp_rsvd = sysdata.sys_swp_used + sysdata.sys_mem_used;
 
1121
 
 
1122
      /* Memory + swap used (bytes) */
 
1123
      sysdata.sys_mswp_used = sysdata.sys_swp_used + sysdata.sys_mem_used;
 
1124
 
 
1125
      /* Memory + swap avail (bytes) */
 
1126
      sysdata.sys_mswp_avail = sysdata.sys_swp_free + sysdata.sys_mem_avail;
 
1127
 
 
1128
   }
 
1129
 
 
1130
#elif defined(CRAY)
 
1131
 
 
1132
   if (clk_tck == 0)
 
1133
      clk_tck = sysconf(_SC_CLK_TCK);
 
1134
 
 
1135
   if (read_kernel_table(SINFO, (void **)&si, &si_size, NULL)<0)
 
1136
      return -1;
 
1137
 
 
1138
   if (read_kernel_table(PWS, (void **)&pw, &pw_size, NULL)<0)
 
1139
      return -1;
 
1140
 
 
1141
   if (read_kernel_table(SWAPTAB, (void **)&sw, &sw_size, NULL)<0)
 
1142
      return -1;
 
1143
 
 
1144
   /* convert CPU time values to double CPU seconds */
 
1145
 
 
1146
   utime = stime = itime = srtime = wtime = ttime = 0;
 
1147
 
 
1148
   for (i=0; i<pw->pw_ccpu; i++) {
 
1149
      utime += CLOCKS2SECS(pw->pws[i].pw_userc);
 
1150
      stime += CLOCKS2SECS(pw->pws[i].pw_unixc);
 
1151
      itime += CLOCKS2SECS(pw->pws[i].pw_idlec);
 
1152
      wtime += CLOCKS2SECS(pw->pws[i].pw_syswc);
 
1153
      ttime += CLOCKS2SECS(pw->pws[i].pw_syswc + pw->pws[i].pw_unixc +
 
1154
                pw->pws[i].pw_userc + pw->pws[i].pw_idlec +
 
1155
                pw->pws[i].pw_guestc);
 
1156
   }
 
1157
 
 
1158
   /* if this is the first time, intialize base CPU time values */
 
1159
 
 
1160
   if (!base.initialized) {
 
1161
      base.initialized = 1;
 
1162
      base.utime = utime;
 
1163
      base.stime = stime;
 
1164
      base.itime = itime;
 
1165
      base.srtime = srtime;
 
1166
      base.wtime = wtime;
 
1167
      base.ttime = ttime;
 
1168
      prev_runque = si->runque;
 
1169
      prev_runocc = si->runocc;
 
1170
      prev_swpque = si->swpque;
 
1171
      prev_swpocc = si->swpocc;
 
1172
   }
 
1173
 
 
1174
   /* total CPUs available (dynamic on Cray) */
 
1175
   sysdata.sys_ncpus = sysconf(_SC_CRAY_NCPU);
 
1176
 
 
1177
   /* total cpu time avail (this int) */
 
1178
   sysdata.sys_ttime = ttime - (base.ttime + sysdata.sys_ttimet);
 
1179
 
 
1180
   /* total cpu time avail (since start) */
 
1181
   sysdata.sys_ttimet = ttime - base.ttime;
 
1182
 
 
1183
   /* user time this interval */
 
1184
   sysdata.sys_utime = utime - (base.utime + sysdata.sys_utimet);
 
1185
 
 
1186
   /* user time (since start) */
 
1187
   sysdata.sys_utimet = utime - base.utime;
 
1188
 
 
1189
   /* system time this interval */
 
1190
   sysdata.sys_stime = stime - (base.stime + sysdata.sys_stimet);
 
1191
 
 
1192
   /* system time (since start) */
 
1193
   sysdata.sys_stimet = stime - base.stime;
 
1194
 
 
1195
   /* idle time this interval */
 
1196
   sysdata.sys_itime = itime - (base.itime + sysdata.sys_itimet);
 
1197
 
 
1198
   /* idle time (since start) */
 
1199
   sysdata.sys_itimet = itime - base.itime;
 
1200
 
 
1201
   /* srun wait this interval */
 
1202
   sysdata.sys_srtime = srtime - (base.srtime + sysdata.sys_srtimet);
 
1203
 
 
1204
   /* srun wait (since start) */
 
1205
   sysdata.sys_srtimet = srtime - base.srtime;
 
1206
 
 
1207
   /* I/O wait time this interval */
 
1208
   sysdata.sys_wtime = wtime - (base.wtime + sysdata.sys_wtimet);
 
1209
 
 
1210
   /* I/O wait time (since start) */
 
1211
   sysdata.sys_wtimet = wtime - base.wtime;
 
1212
 
 
1213
   /* Memory available (unused, free) */
 
1214
   sysdata.sys_mem_avail = sysconf(_SC_CRAY_USRMEM) * 8 - si->umemused * NBPC;
 
1215
 
 
1216
   /* Memory in use (bytes) */
 
1217
   sysdata.sys_mem_used = si->umemused * NBPC + sysconf(_SC_CRAY_SYSMEM) * 8;
 
1218
 
 
1219
   /* Total Swap space available */
 
1220
   sysdata.sys_swp_total = sw->swp_map.bmp_total * sw->swp_wght * 4096;
 
1221
 
 
1222
   /* Swap space free */
 
1223
   sysdata.sys_swp_free = sw->swp_map.bmp_avail * sw->swp_wght * 4096;
 
1224
 
 
1225
   /* Swap space in use (bytes) */
 
1226
   sysdata.sys_swp_used = sysdata.sys_swp_total - sysdata.sys_swp_free;
 
1227
 
 
1228
   /* Swap space reserved (bytes) */
 
1229
   sysdata.sys_swp_rsvd = sysdata.sys_swp_used + sysdata.sys_mem_used;
 
1230
 
 
1231
   /* Virtual (CRAY: sys_mem_used + sys_swp_used) Swap space avail (bytes) */
 
1232
   sysdata.sys_swp_virt = sysdata.sys_swp_used + sysdata.sys_mem_used;
 
1233
 
 
1234
   /* Memory + swap used (bytes) */
 
1235
   sysdata.sys_mswp_used = sysdata.sys_swp_used + sysdata.sys_mem_used;
 
1236
 
 
1237
   /* Memory + swap avail (bytes) */
 
1238
   sysdata.sys_mswp_avail = sysdata.sys_swp_free + sysdata.sys_mem_avail;
 
1239
 
 
1240
   /* Swap rate in bytes/second */
 
1241
   sysdata.sys_swp_rate = sw->swp_interv==0 ? (double)0 :
 
1242
         (double)(sw->swp_blksper * 4096) / (double)sw->swp_interv;
 
1243
 
 
1244
   if ((time_stamp - prev_time_stamp) > 0)
 
1245
      period = (time_stamp - prev_time_stamp);
 
1246
   else
 
1247
      period = 1.0;
 
1248
   
 
1249
   /* Swap "Occ" delta */
 
1250
   sysdata.sys_swpocc = ((double)si->swpocc - prev_swpocc) / period;
 
1251
   prev_swpocc = si->swpocc;
 
1252
 
 
1253
   /* Swap Queue delta */
 
1254
   sysdata.sys_swpque = ((double)si->swpque - prev_swpque) / period;
 
1255
   prev_swpque = si->swpque;
 
1256
 
 
1257
   /* Run "Occ" delta */
 
1258
   sysdata.sys_runocc = ((double)si->runocc - prev_runocc) / period;
 
1259
   prev_runocc = si->runocc;
 
1260
 
 
1261
   /* Run Queue delta */
 
1262
   sysdata.sys_runque = ((double)si->runque - prev_runque) / period;
 
1263
   if (sysdata.sys_ncpus > 1) sysdata.sys_runque /= sysdata.sys_ncpus;
 
1264
   prev_runque = si->runque;
 
1265
 
 
1266
   /* characters read */
 
1267
   sysdata.sys_readch = si->readch;
 
1268
 
 
1269
   /* characters written */
 
1270
   sysdata.sys_writech = si->writech;
 
1271
 
 
1272
#endif
 
1273
   return 0;
 
1274
}
 
1275
 
 
1276
#endif
 
1277
 
 
1278
static int
 
1279
get_numjobs(void)
 
1280
{
 
1281
   lnk_link_t *curr;
 
1282
   int count = 0;
 
1283
   for (curr=job_list.next; curr != &job_list; curr=curr->next)
 
1284
      if (LNK_DATA(curr, job_elem_t, link)->precreated == 0)
 
1285
         count++;
 
1286
   return count;
 
1287
}
 
1288
 
 
1289
#ifdef IRIX
 
1290
 
 
1291
/* only used on IRIX 6 */
 
1292
typedef struct {
 
1293
   lnk_link_t link;
 
1294
   pdc_arsess_t arse;
 
1295
} arsess_elem_t;
 
1296
 
 
1297
#define ASHMAXINC 100
 
1298
 
 
1299
/* only used on IRIX 6 */
 
1300
static int
 
1301
get_arsess_list(lnk_link_t *arsess_list)
 
1302
{
 
1303
   int num_ashes, i;
 
1304
   static ash_t *ashes;
 
1305
   static int ash_max;
 
1306
   union {
 
1307
      arsess_t arse;
 
1308
      arsess64_t arse64;
 
1309
      arsess65_t arse65;
 
1310
   } ar;
 
1311
   static int (*get_arsess_p)(pdc_arsess_t *, arsess_t *);
 
1312
 
 
1313
   if (get_arsess_p == NULL) {
 
1314
      char irix_release[10];
 
1315
      sysinfo(SI_RELEASE, irix_release, sizeof(irix_release));
 
1316
      if (strcmp(irix_release, "6.5")>=0)
 
1317
         get_arsess_p = &pdc_get_arsess65;
 
1318
      else if (sysconf(_SC_KERN_POINTERS) == 64)
 
1319
         get_arsess_p = &pdc_get_arsess64;
 
1320
      else
 
1321
         get_arsess_p = &pdc_get_arsess;
 
1322
   }
 
1323
 
 
1324
   if (ashes == NULL) {
 
1325
      ash_max = ASHMAXINC;
 
1326
      ashes = (ash_t *)malloc(sizeof(ash_t)*ash_max);
 
1327
      memset(ashes, 0, sizeof(ash_t)*ash_max);
 
1328
   }
 
1329
 
 
1330
   LNK_INIT(arsess_list);
 
1331
 
 
1332
   while ((num_ashes = syssgi(SGI_ENUMASHS, ashes, ash_max)) < 0 &&
 
1333
          errno == ENOMEM) {
 
1334
      ash_max += ASHMAXINC;
 
1335
      ashes = (ash_t *)sge_realloc(ashes, sizeof(ash_t)*ash_max, 1);
 
1336
   }
 
1337
 
 
1338
   if (num_ashes > 0) {
 
1339
      for (i=0; i<num_ashes; i++) {
 
1340
         if (syssgi(SGI_GETARSESS, &ashes[i], &ar) >= 0) {
 
1341
            arsess_elem_t *arse_elem;
 
1342
            arse_elem = malloc(sizeof(arsess_elem_t));
 
1343
            memset(arse_elem, 0, sizeof(arsess_elem_t));
 
1344
            (*get_arsess_p)(&arse_elem->arse, &ar.arse);
 
1345
            LNK_ADD(arsess_list->prev, &arse_elem->link);
 
1346
         }
 
1347
      }
 
1348
   }
 
1349
 
 
1350
   return num_ashes;
 
1351
}
 
1352
 
 
1353
 
 
1354
/* only used on IRIX 6 */
 
1355
static void
 
1356
free_arsess_list(lnk_link_t *arsess_list)
 
1357
{
 
1358
   lnk_link_t *curra;
 
1359
   while((curra=arsess_list->next) != arsess_list) {
 
1360
      LNK_DELETE(curra);
 
1361
      free(LNK_DATA(curra, arsess_elem_t, link));
 
1362
   }
 
1363
}
 
1364
 
 
1365
/* only used on IRIX 6 */
 
1366
static arsess_elem_t *
 
1367
find_arsess(lnk_link_t *arsess_list, ash_t ash)
 
1368
{
 
1369
   lnk_link_t *curra;
 
1370
   for(curra=arsess_list->next; curra!=arsess_list; curra=curra->next) {
 
1371
      arsess_elem_t *arsess_elem = LNK_DATA(curra, arsess_elem_t, link);
 
1372
      if (arsess_elem->arse.ash == ash)
 
1373
         return arsess_elem;
 
1374
   }
 
1375
   return NULL;
 
1376
}
 
1377
 
 
1378
/* only used on IRIX 6 */
 
1379
static int
 
1380
in_pidlist(pid_t *pidlist, int max, pid_t pid)
 
1381
{
 
1382
   int j;
 
1383
   for (j=0; pidlist[j] && j<max; j++)
 
1384
      if (pidlist[j] == pid)
 
1385
         return j+1;
 
1386
   return 0;
 
1387
}
 
1388
 
 
1389
#endif /* IRIX */
 
1390
 
 
1391
static void
 
1392
free_process_list(job_elem_t *job_elem)
 
1393
{
 
1394
   lnk_link_t *currp;
 
1395
 
 
1396
   /* free process list */
 
1397
   while((currp=job_elem->procs.next) != &job_elem->procs) {
 
1398
      LNK_DELETE(currp);
 
1399
      free(LNK_DATA(currp, proc_elem_t, link));
 
1400
   }
 
1401
}
 
1402
 
 
1403
static void
 
1404
free_job(job_elem_t *job_elem)
 
1405
{
 
1406
#ifdef IRIX
 
1407
   lnk_link_t *currp;
 
1408
#endif
 
1409
 
 
1410
   free_process_list(job_elem);
 
1411
 
 
1412
#ifdef IRIX
 
1413
   /* free arse list */
 
1414
   while((currp=job_elem->arses.next) != &job_elem->arses) {
 
1415
      LNK_DELETE(currp);
 
1416
      free(LNK_DATA(currp, arsess_elem_t, link));
 
1417
   }
 
1418
#endif
 
1419
 
 
1420
   /* free job element */
 
1421
   free(job_elem);
 
1422
}
 
1423
 
 
1424
static int psRetrieveOSJobData(void) {
 
1425
   lnk_link_t *curr, *next;
 
1426
   time_t time_stamp = get_gmt();
 
1427
   static time_t next_time, pnext_time;
 
1428
 
 
1429
#if defined(IRIX)
 
1430
   lnk_link_t arsess_list;
 
1431
   arsess_elem_t *arse_elem;
 
1432
#elif defined(CRAY)
 
1433
   static struct proc *pt;
 
1434
   static long pt_size;
 
1435
   static struct sess *st;
 
1436
   static long st_size;
 
1437
   int nproc, nsess, i;
 
1438
   static int clk_tck;
 
1439
#endif
 
1440
 
 
1441
   DENTER(TOP_LAYER, "psRetrieveOSJobData");
 
1442
 
 
1443
   if (time_stamp <= next_time) {
 
1444
      DRETURN(0);
 
1445
   }
 
1446
   next_time = time_stamp + ps_config.job_collection_interval;
 
1447
 
 
1448
#if defined(IRIX)
 
1449
 
 
1450
   /* go get all the array sessions */
 
1451
 
 
1452
   get_arsess_list(&arsess_list);
 
1453
 
 
1454
#elif defined(ALPHA) || defined(LINUX) || defined(SOLARIS)
 
1455
   {
 
1456
 
 
1457
      /* There is no way to retrieve a pid list containing all processes 
 
1458
         of a session id. So we have to iterate through the whole process 
 
1459
         table to decide whether a process is needed for a job or not. */
 
1460
      pt_open();
 
1461
 
 
1462
      while (!pt_dispatch_proc_to_job(&job_list, time_stamp))
 
1463
         ; 
 
1464
      pt_close();
 
1465
   }
 
1466
#elif defined(AIX)
 
1467
   {
 
1468
      #define SIZE 16
 
1469
 
 
1470
      struct procsinfo pinfo[SIZE];
 
1471
 
 
1472
      int idx = 0, count;
 
1473
      job_elem_t *job_elem;
 
1474
      double old_time = 0.0;
 
1475
      uint64 old_vmem = 0;
 
1476
      pid_t index;
 
1477
 
 
1478
      while ((count = getprocs(pinfo, sizeof(struct procsinfo), NULL, 0, &index, SIZE)) > 0) {
 
1479
 
 
1480
        int i;
 
1481
        /* for all processes */
 
1482
        for (i=0; i < count; i++)
 
1483
        {
 
1484
          for (curr=job_list.next; curr != &job_list; curr=curr->next) {
 
1485
            int group;
 
1486
 
 
1487
            job_elem = LNK_DATA(curr, job_elem_t, link);
 
1488
 
 
1489
            if (job_elem->job.jd_jid == pinfo[i].pi_pgrp) {
 
1490
 
 
1491
              lnk_link_t  *curr2;
 
1492
              proc_elem_t *proc_elem;
 
1493
              int newprocess = 1;
 
1494
 
 
1495
              for (curr2=job_elem->procs.next; curr2 != &job_elem->procs; curr2=curr2->next) {
 
1496
 
 
1497
                proc_elem = LNK_DATA(curr2, proc_elem_t, link);
 
1498
 
 
1499
                if (proc_elem->proc.pd_pid == pinfo[i].pi_pid) {
 
1500
                  newprocess = 0;
 
1501
                  break;
 
1502
                }
 
1503
              }
 
1504
 
 
1505
              if (newprocess) {
 
1506
                proc_elem = (proc_elem_t *) malloc(sizeof(proc_elem_t));
 
1507
 
 
1508
                if (proc_elem == NULL) {
 
1509
                    DRETURN(0);
 
1510
                }
 
1511
 
 
1512
                memset(proc_elem, 0, sizeof(proc_elem_t));
 
1513
                proc_elem->proc.pd_length = sizeof(psProc_t);
 
1514
                proc_elem->proc.pd_state  = 1; /* active */
 
1515
 
 
1516
                LNK_ADD(job_elem->procs.prev, &proc_elem->link);
 
1517
                job_elem->job.jd_proccount++;
 
1518
 
 
1519
              }
 
1520
              else {
 
1521
                  /* save previous usage data - needed to build delta usage */
 
1522
                  old_time = proc_elem->proc.pd_utime + proc_elem->proc.pd_stime;
 
1523
                  old_vmem  = proc_elem->vmem;
 
1524
              }
 
1525
 
 
1526
              proc_elem->proc.pd_tstamp = time_stamp;
 
1527
              proc_elem->proc.pd_pid    = pinfo[i].pi_pid;
 
1528
 
 
1529
              proc_elem->proc.pd_utime  = pinfo[i].pi_ru.ru_utime.tv_sec;
 
1530
              proc_elem->proc.pd_stime  = pinfo[i].pi_ru.ru_stime.tv_sec;
 
1531
 
 
1532
              proc_elem->proc.pd_uid    = pinfo[i].pi_uid;
 
1533
              proc_elem->vmem           = pinfo[i].pi_dvm +
 
1534
                                          pinfo[i].pi_tsize + pinfo[i].pi_dsize;
 
1535
              proc_elem->rss            = pinfo[i].pi_drss + pinfo[i].pi_trss;
 
1536
              proc_elem->proc.pd_pstart = pinfo[i].pi_start;
 
1537
 
 
1538
              proc_elem->mem = ((proc_elem->proc.pd_stime + proc_elem->proc.pd_utime) - old_time) *
 
1539
                                (( old_vmem + proc_elem->vmem)/2);
 
1540
 
 
1541
            } /* if */
 
1542
          } /* for job_list */
 
1543
        } /* process */
 
1544
      }
 
1545
   }
 
1546
#elif defined(HP1164)
 
1547
   {
 
1548
      #define SIZE 16
 
1549
      struct pst_status pstat_buffer[SIZE];
 
1550
      int idx = 0, count;
 
1551
      job_elem_t *job_elem;
 
1552
      double old_time = 0;
 
1553
      uint64 old_vmem = 0;
 
1554
 
 
1555
      while ((count = pstat_getproc(pstat_buffer, sizeof(struct pst_status), SIZE, idx)) > 0) {
 
1556
 
 
1557
        int i;
 
1558
        /* for all processes */
 
1559
        for (i=0; i < count; i++)
 
1560
        {
 
1561
          for (curr=job_list.next; curr != &job_list; curr=curr->next) {
 
1562
            int group;
 
1563
 
 
1564
            job_elem = LNK_DATA(curr, job_elem_t, link);
 
1565
 
 
1566
            if (job_elem->job.jd_jid == pstat_buffer[i].pst_pgrp) {
 
1567
 
 
1568
              lnk_link_t  *curr2;
 
1569
              proc_elem_t *proc_elem;
 
1570
              int newprocess = 1;
 
1571
 
 
1572
              for (curr2=job_elem->procs.next; curr2 != &job_elem->procs; curr2=curr2->next) {
 
1573
 
 
1574
                proc_elem = LNK_DATA(curr2, proc_elem_t, link);
 
1575
 
 
1576
                if (proc_elem->proc.pd_pid == pstat_buffer[i].pst_pid) {
 
1577
                  newprocess = 0;
 
1578
                  break;
 
1579
                }
 
1580
              }
 
1581
 
 
1582
              if (newprocess) {
 
1583
                proc_elem = (proc_elem_t *) malloc(sizeof(proc_elem_t));
 
1584
 
 
1585
                if (proc_elem == NULL) {
 
1586
                    DRETURN(0);
 
1587
                }
 
1588
 
 
1589
                memset(proc_elem, 0, sizeof(proc_elem_t));
 
1590
                proc_elem->proc.pd_length = sizeof(psProc_t);
 
1591
                proc_elem->proc.pd_state  = 1; /* active */
 
1592
 
 
1593
                LNK_ADD(job_elem->procs.prev, &proc_elem->link);
 
1594
                job_elem->job.jd_proccount++;
 
1595
 
 
1596
              }
 
1597
              else {
 
1598
                  /* save previous usage data - needed to build delta usage */
 
1599
                  old_time = proc_elem->proc.pd_utime + proc_elem->proc.pd_stime;
 
1600
                  old_vmem  = proc_elem->vmem;
 
1601
              }
 
1602
 
 
1603
              proc_elem->proc.pd_tstamp = time_stamp;
 
1604
              proc_elem->proc.pd_pid    = pstat_buffer[i].pst_pid;
 
1605
 
 
1606
              proc_elem->proc.pd_utime  = pstat_buffer[i].pst_utime;
 
1607
              proc_elem->proc.pd_stime  = pstat_buffer[i].pst_stime;
 
1608
 
 
1609
              proc_elem->proc.pd_uid    = pstat_buffer[i].pst_uid;
 
1610
              proc_elem->proc.pd_gid    = pstat_buffer[i].pst_gid;
 
1611
              proc_elem->vmem           = pstat_buffer[i].pst_vdsize +
 
1612
                                          pstat_buffer[i].pst_vtsize + pstat_buffer[i].pst_vssize;
 
1613
              proc_elem->rss            = pstat_buffer[i].pst_rssize;
 
1614
              proc_elem->proc.pd_pstart = pstat_buffer[i].pst_start;
 
1615
 
 
1616
              proc_elem->vmem = proc_elem->vmem * getpagesize();
 
1617
              proc_elem->rss  = proc_elem->rss  * getpagesize();
 
1618
 
 
1619
              proc_elem->mem = ((proc_elem->proc.pd_stime + proc_elem->proc.pd_utime) - old_time) *
 
1620
                                (( old_vmem + proc_elem->vmem)/2);
 
1621
 
 
1622
            } /* if */
 
1623
          } /* for job_list */
 
1624
        } /* process */
 
1625
 
 
1626
        idx = pstat_buffer[count-1].pst_idx + 1;
 
1627
      }
 
1628
   }
 
1629
#elif defined(FREEBSD)
 
1630
   {
 
1631
      kvm_t *kd;
 
1632
      int i, nprocs;
 
1633
      struct kinfo_proc *procs;
 
1634
      char kerrbuf[_POSIX2_LINE_MAX];
 
1635
      job_elem_t *job_elem;
 
1636
      double old_time = 0.0;
 
1637
      uint64 old_vmem = 0;
 
1638
 
 
1639
      kd = kvm_openfiles(NULL, NULL, NULL, O_RDONLY, kerrbuf);
 
1640
      if (kd == NULL) {
 
1641
         DPRINTF(("kvm_openfiles: error %s\n", kerrbuf));
 
1642
         DRETURN(-1);
 
1643
      }
 
1644
 
 
1645
      procs = kvm_getprocs(kd, KERN_PROC_ALL, 0, &nprocs);
 
1646
      if (procs == NULL) {
 
1647
         DPRINTF(("kvm_getprocs: error %s\n", kvm_geterr(kd)));
 
1648
         kvm_close(kd);
 
1649
         DRETURN(-1);
 
1650
      }
 
1651
      for (; nprocs >= 0; nprocs--, procs++) {
 
1652
         for (curr=job_list.next; curr != &job_list; curr=curr->next) {
 
1653
            job_elem = LNK_DATA(curr, job_elem_t, link);
 
1654
 
 
1655
            for (i = 0; i < procs->ki_ngroups; i++) {
 
1656
               if (job_elem->job.jd_jid == procs->ki_groups[i]) {
 
1657
                  lnk_link_t  *curr2;
 
1658
                  proc_elem_t *proc_elem;
 
1659
                  int newprocess = 1;
 
1660
                  
 
1661
                  if (job_elem->job.jd_proccount != 0) {
 
1662
                     for (curr2=job_elem->procs.next; curr2 != &job_elem->procs; curr2=curr2->next) {
 
1663
                        proc_elem = LNK_DATA(curr2, proc_elem_t, link);
 
1664
 
 
1665
                        if (proc_elem->proc.pd_pid == procs->ki_pid) {
 
1666
                           newprocess = 0;
 
1667
                           break;
 
1668
                        }
 
1669
                     }
 
1670
                  }
 
1671
                  if (newprocess) {
 
1672
                     proc_elem = malloc(sizeof(proc_elem_t));
 
1673
                     if (proc_elem == NULL) {
 
1674
                        kvm_close(kd);
 
1675
                        DRETURN(0);
 
1676
                     }
 
1677
 
 
1678
                     memset(proc_elem, 0, sizeof(proc_elem_t));
 
1679
                     proc_elem->proc.pd_length = sizeof(psProc_t);
 
1680
                     proc_elem->proc.pd_state  = 1; /* active */
 
1681
                     proc_elem->proc.pd_pstart = procs->ki_start.tv_sec;
 
1682
 
 
1683
                     LNK_ADD(job_elem->procs.prev, &proc_elem->link);
 
1684
                     job_elem->job.jd_proccount++;
 
1685
                  } else {
 
1686
                     /* save previous usage data - needed to build delta usage */
 
1687
                     old_time = proc_elem->proc.pd_utime + proc_elem->proc.pd_stime;
 
1688
                     old_vmem  = proc_elem->vmem;
 
1689
                  }
 
1690
                  proc_elem->proc.pd_tstamp = time_stamp;
 
1691
                  proc_elem->proc.pd_pid    = procs->ki_pid;
 
1692
 
 
1693
                  proc_elem->proc.pd_utime  = procs->ki_rusage.ru_utime.tv_sec;
 
1694
                  proc_elem->proc.pd_stime  = procs->ki_rusage.ru_stime.tv_sec;
 
1695
 
 
1696
                  proc_elem->proc.pd_uid    = procs->ki_uid;
 
1697
                  proc_elem->proc.pd_gid    = procs->ki_rgid;
 
1698
                  proc_elem->vmem           = procs->ki_size;
 
1699
                  proc_elem->rss            = procs->ki_rssize;
 
1700
                  proc_elem->mem = ((proc_elem->proc.pd_stime + proc_elem->proc.pd_utime) - old_time) *
 
1701
                                    ((old_vmem + proc_elem->vmem)/2);
 
1702
               }
 
1703
            }
 
1704
         }
 
1705
      }
 
1706
      kvm_close(kd);
 
1707
   }
 
1708
#elif defined(DARWIN)
 
1709
   {
 
1710
      int i, nprocs;
 
1711
      struct kinfo_proc *procs;
 
1712
      struct kinfo_proc *procs_begin;
 
1713
      job_elem_t *job_elem;
 
1714
      double old_time = 0.0;
 
1715
      uint64 old_vmem = 0;
 
1716
      int mib[4] = { CTL_KERN, KERN_PROC, KERN_PROC_ALL, 0 };
 
1717
      size_t bufSize = 0;
 
1718
 
 
1719
      if (sysctl(mib, 4, NULL, &bufSize, NULL, 0) < 0) {
 
1720
         DPRINTF(("sysctl() failed(1)\n"));
 
1721
         DRETURN(-1);
 
1722
      }
 
1723
      if ((procs = (struct kinfo_proc *)malloc(bufSize)) == NULL) {
 
1724
         DPRINTF(("malloc() failed\n"));
 
1725
         DRETURN(-1);
 
1726
      }
 
1727
      if (sysctl(mib, 4, procs, &bufSize, NULL, 0) < 0) {
 
1728
         DPRINTF(("sysctl() failed(2)\n"));
 
1729
         FREE(procs);
 
1730
         DRETURN(-1);
 
1731
      }
 
1732
      procs_begin = procs;
 
1733
      nprocs = bufSize/sizeof(struct kinfo_proc);
 
1734
      
 
1735
      for (; nprocs >= 0; nprocs--, procs++) {
 
1736
         for (curr=job_list.next; curr != &job_list; curr=curr->next) {
 
1737
            job_elem = LNK_DATA(curr, job_elem_t, link);
 
1738
 
 
1739
            for (i = 0; i < procs->kp_eproc.e_ucred.cr_ngroups; i++) {
 
1740
               if (job_elem->job.jd_jid == procs->kp_eproc.e_ucred.cr_groups[i]) {
 
1741
                  lnk_link_t  *curr2;
 
1742
                  proc_elem_t *proc_elem;
 
1743
                  int newprocess = 1;
 
1744
                  
 
1745
                  if (job_elem->job.jd_proccount != 0) {
 
1746
                     for (curr2=job_elem->procs.next; curr2 != &job_elem->procs; curr2=curr2->next) {
 
1747
                        proc_elem = LNK_DATA(curr2, proc_elem_t, link);
 
1748
 
 
1749
                        if (proc_elem->proc.pd_pid == procs->kp_proc.p_pid) {
 
1750
                           newprocess = 0;
 
1751
                           break;
 
1752
                        }
 
1753
                     }
 
1754
                  }
 
1755
                  if (newprocess) {
 
1756
                     proc_elem = malloc(sizeof(proc_elem_t));
 
1757
                     if (proc_elem == NULL) {
 
1758
                        FREE(procs_begin);
 
1759
                        DRETURN(0);
 
1760
                     }
 
1761
 
 
1762
                     memset(proc_elem, 0, sizeof(proc_elem_t));
 
1763
                     proc_elem->proc.pd_length = sizeof(psProc_t);
 
1764
                     proc_elem->proc.pd_state  = 1; /* active */
 
1765
                     proc_elem->proc.pd_pstart = procs->kp_proc.p_starttime.tv_sec;
 
1766
 
 
1767
                     LNK_ADD(job_elem->procs.prev, &proc_elem->link);
 
1768
                     job_elem->job.jd_proccount++;
 
1769
                  } else {
 
1770
                     /* save previous usage data - needed to build delta usage */
 
1771
                     old_time = proc_elem->proc.pd_utime + proc_elem->proc.pd_stime;
 
1772
                     old_vmem  = proc_elem->vmem;
 
1773
                  }
 
1774
                  proc_elem->proc.pd_tstamp = time_stamp;
 
1775
                  proc_elem->proc.pd_pid    = procs->kp_proc.p_pid;
 
1776
                  DPRINTF(("pid: %d\n", proc_elem->proc.pd_pid));
 
1777
 
 
1778
                  {
 
1779
                     struct task_basic_info t_info;
 
1780
                     struct task_thread_times_info t_times_info;
 
1781
                     mach_port_t task;
 
1782
                     unsigned int info_count = TASK_BASIC_INFO_COUNT;
 
1783
 
 
1784
                     if (task_for_pid(mach_task_self(), proc_elem->proc.pd_pid, &task) != KERN_SUCCESS) {
 
1785
                        DPRINTF(("task_for_pid() error"));
 
1786
                     } else {
 
1787
                        if (task_info(task, TASK_BASIC_INFO, (task_info_t)&t_info, &info_count) != KERN_SUCCESS) {
 
1788
                           DPRINTF(("task_info() error"));
 
1789
                        } else {
 
1790
                           proc_elem->vmem           = t_info.virtual_size/1024;
 
1791
                           DPRINTF(("vmem: %d\n", proc_elem->vmem));
 
1792
                           proc_elem->rss            = t_info.resident_size/1024;
 
1793
                           DPRINTF(("rss: %d\n", proc_elem->rss));
 
1794
                        }
 
1795
 
 
1796
                        info_count = TASK_THREAD_TIMES_INFO_COUNT;
 
1797
                        if (task_info(task, TASK_THREAD_TIMES_INFO, (task_info_t)&t_times_info, &info_count) != KERN_SUCCESS) {
 
1798
                           DPRINTF(("task_info() error\n"));
 
1799
                        } else {
 
1800
                           proc_elem->proc.pd_utime  = t_times_info.user_time.seconds;
 
1801
                           DPRINTF(("user_time: %d\n", proc_elem->proc.pd_utime));
 
1802
                           proc_elem->proc.pd_stime  = t_times_info.system_time.seconds;
 
1803
                           DPRINTF(("system_time: %d\n", proc_elem->proc.pd_stime));
 
1804
                        }
 
1805
                     }
 
1806
                  }
 
1807
 
 
1808
                  proc_elem->proc.pd_uid    = procs->kp_eproc.e_ucred.cr_uid;
 
1809
                  DPRINTF(("uid: %d\n", proc_elem->proc.pd_uid));
 
1810
                  proc_elem->proc.pd_gid    = procs->kp_eproc.e_pcred.p_rgid;
 
1811
                  DPRINTF(("gid: %d\n", proc_elem->proc.pd_gid));
 
1812
                  proc_elem->mem = ((proc_elem->proc.pd_stime + proc_elem->proc.pd_utime) - old_time) *
 
1813
                                         ((old_vmem + proc_elem->vmem)/2);
 
1814
                  DPRINTF(("mem %d\n", proc_elem->mem));
 
1815
               }
 
1816
            }
 
1817
         }
 
1818
      }
 
1819
      FREE(procs_begin);
 
1820
   }
 
1821
#elif defined(NECSX4) || defined(NECSX5)
 
1822
   {
 
1823
      for (curr=job_list.next; curr != &job_list; curr=curr->next) {
 
1824
         job_elem_t *job_elem = LNK_DATA(curr, job_elem_t, link);
 
1825
         psJob_t *job = &job_elem->job;
 
1826
         id_t jid = (id_t) job->jd_jid;
 
1827
         struct jresourcecpu resourcecpu;
 
1828
         struct jresourcemem resourcemem;
 
1829
         struct jresourcetmpf resourcetmpf;
 
1830
         struct jresourceproc resourceproc;
 
1831
         int error;
 
1832
         u_long32 delta_t = 0;
 
1833
 
 
1834
         /* skip precreated jobs */
 
1835
         if (job_elem->precreated)
 
1836
            continue;
 
1837
 
 
1838
         /* try to get resource information */
 
1839
         error = 0;
 
1840
         if (getresourcej(jid, CURR_ALL,  &resourcecpu) == -1) {
 
1841
            error = 1;
 
1842
         } else {
 
1843
            delta_t = MICROSEC2SECS(resourcecpu.jr_ucpu)
 
1844
               + MICROSEC2SECS(resourcecpu.jr_scpu)
 
1845
               - job_elem->utime - job_elem->stime;
 
1846
 
 
1847
            job->jd_utime_a = MICROSEC2SECS(resourcecpu.jr_ucpu);
 
1848
            job->jd_stime_a = MICROSEC2SECS(resourcecpu.jr_scpu);
 
1849
            job->jd_utime_c = 0;
 
1850
            job->jd_stime_c = 0;
 
1851
 
 
1852
            job_elem->utime = job->jd_utime_a;
 
1853
            job_elem->stime = job->jd_stime_a;
 
1854
         }
 
1855
 
 
1856
         if (getresourcej(jid, CURR_UMEM, &resourcemem) == -1) {
 
1857
            error = 1;
 
1858
         } else {
 
1859
            job->jd_mem += resourcemem.jr_umem.mv_used * delta_t;
 
1860
         }
 
1861
 
 
1862
         if (getresourcej(jid, CURR_PROC, &resourceproc) == -1) {
 
1863
            error = 1;
 
1864
         } else {
 
1865
            job->jd_refcnt = resourceproc.jr_proc;
 
1866
         }
 
1867
 
 
1868
         if (!error) {
 
1869
            if (job->jd_tstamp == 0) {
 
1870
               job->jd_gid = -1;
 
1871
               job->jd_uid = -1;
 
1872
            }
 
1873
            job->jd_tstamp = time_stamp;
 
1874
            job->jd_etime = time_stamp - job_elem->starttime;
 
1875
            job->jd_vmem = job->jd_mem;
 
1876
            job->jd_rss = job->jd_vmem;
 
1877
         }
 
1878
      }
 
1879
   }           
 
1880
 
 
1881
#elif defined(CRAY)
 
1882
 
 
1883
   if (clk_tck == 0)
 
1884
      clk_tck = sysconf(_SC_CLK_TCK);
 
1885
 
 
1886
   if (read_kernel_table(SESS, (void **)&st, &st_size, &nsess)<0) {
 
1887
      DRETURN(-1);
 
1888
   }
 
1889
 
 
1890
   if (read_kernel_table(PROCTAB, (void **)&pt, &pt_size, &nproc)<0) {
 
1891
      DRETURN(-1);
 
1892
   }
 
1893
 
 
1894
   /* scan session table */
 
1895
 
 
1896
   for(i=0; i<nsess; i++) {
 
1897
      struct sess *ss = &st[i];
 
1898
      if (ss->s_sid == 0) continue;
 
1899
      for (curr=job_list.next; curr != &job_list; curr=curr->next) {
 
1900
         job_elem_t *job_elem = LNK_DATA(curr, job_elem_t, link);
 
1901
         psJob_t *job = &job_elem->job;
 
1902
         if (job_elem->precreated) continue; /* skip precreated jobs */
 
1903
         if (ss->s_sid == job->jd_jid) {
 
1904
            job->jd_uid = ss->s_uid;
 
1905
            if (job->jd_tstamp == 0)
 
1906
               job->jd_gid = -1;
 
1907
            job->jd_tstamp = time_stamp;
 
1908
            job->jd_refcnt = ss->s_nprocs;
 
1909
            job->jd_etime = time_stamp - job_elem->starttime; /* estimate */
 
1910
            job_elem->utime = CLOCKS2SECS(ss->s_ucputime);
 
1911
            job_elem->stime = CLOCKS2SECS(ss->s_scputime);
 
1912
            job->jd_vmem = ss->s_memuse * NBPC;
 
1913
            job->jd_rss = job->jd_vmem;
 
1914
            job->jd_himem = ss->s_memhiwat * NBPC;
 
1915
            break;
 
1916
         }
 
1917
      }
 
1918
   }
 
1919
 
 
1920
   /* scan process table */
 
1921
 
 
1922
   for(i=0; i<nproc; i++) {
 
1923
      struct proc *pp = &pt[i];
 
1924
      job_elem_t *job_elem;
 
1925
      psJob_t *job;
 
1926
      lnk_link_t *currp;
 
1927
      proc_elem_t *proc_elem;
 
1928
      psProc_t *proc;
 
1929
 
 
1930
      /* skip blank process entries */
 
1931
      if (pp->p_pid == 0) continue;
 
1932
      if (pp->p_pcomm.pc_cred.cr_sid == 0) continue;
 
1933
 
 
1934
      /* search for job based on session ID */
 
1935
      for (curr=job_list.next; curr != &job_list; curr=curr->next) {
 
1936
         job_elem = LNK_DATA(curr, job_elem_t, link);
 
1937
         job = &job_elem->job;
 
1938
         if (job_elem->precreated) continue; /* skip precreated jobs */
 
1939
         if (pp->p_pcomm.pc_cred.cr_sid == job->jd_jid)
 
1940
            break;
 
1941
      }
 
1942
      if (curr == &job_list) /* if not found, go to next proctab entry */
 
1943
         continue;
 
1944
 
 
1945
      /* search job's process list for pid */
 
1946
      for(currp=job_elem->procs.next; currp != &job_elem->procs;
 
1947
          currp=currp->next) {
 
1948
         proc_elem = LNK_DATA(currp, proc_elem_t, link);
 
1949
         if (proc_elem->proc.pd_pid == pp->p_pid)
 
1950
            break;
 
1951
      }
 
1952
 
 
1953
      /* if this process is not in process list, chain on new one */
 
1954
      if (currp == &job_elem->procs) {
 
1955
         proc_elem = (proc_elem_t *)malloc(sizeof(proc_elem_t));
 
1956
         if (!proc_elem) {
 
1957
            DRETURN(-1);
 
1958
         }
 
1959
         memset(proc_elem, 0, sizeof(proc_elem_t));
 
1960
         proc_elem->proc.pd_length = sizeof(psProc_t);
 
1961
         LNK_ADD(job_elem->procs.prev, &proc_elem->link);
 
1962
         job->jd_proccount++;
 
1963
      }
 
1964
 
 
1965
      /* set process fields */
 
1966
      proc = &proc_elem->proc;
 
1967
      proc->pd_tstamp = time_stamp;
 
1968
      proc->pd_pid = pp->p_pid;
 
1969
      proc->pd_uid = pp->p_pcomm.pc_cred.cr_uid;
 
1970
      proc->pd_gid = pp->p_pcomm.pc_cred.cr_groups[0];
 
1971
      proc->pd_acid = pp->p_pcomm.pc_cred.cr_acid;
 
1972
      if (job->jd_gid == -1) {
 
1973
         job->jd_gid = proc->pd_gid; /* job group ID */
 
1974
         job->jd_acid = proc->pd_acid; /* job acct ID */
 
1975
      }
 
1976
      proc->pd_state = 1;
 
1977
      if (proc->pd_pstart == 0) proc->pd_pstart = time_stamp;
 
1978
      proc->pd_utime = CLOCKS2SECS(pp->p_utime);
 
1979
      proc->pd_stime = CLOCKS2SECS(pp->p_stime);
 
1980
      proc_elem->qwtime = (double)pp->p_pcomm.pc_srunwtime;
 
1981
   }
 
1982
 
 
1983
   /* call routine to get pacct data */
 
1984
 
 
1985
   read_pacct(&job_list, time_stamp);
 
1986
 
 
1987
#endif
 
1988
 
 
1989
   for (curr=job_list.next; curr != &job_list; curr=next) {
 
1990
      psJob_t *job;
 
1991
      job_elem_t *job_elem;
 
1992
 
 
1993
      next = curr->next;
 
1994
      job_elem = LNK_DATA(curr, job_elem_t, link);
 
1995
      job = &job_elem->job;
 
1996
 
 
1997
      /* if job has not been watched within 30 seconds of being pre-added
 
1998
         to job list, delete it */
 
1999
 
 
2000
      if (job_elem->precreated) {
 
2001
 
 
2002
         if ((job_elem->precreated + 30) < time_stamp) {
 
2003
 
 
2004
#           if DEBUG
 
2005
 
 
2006
               fprintf(df, "%d deleting precreated "F64"\n", time_stamp,
 
2007
                       job->jd_jid);
 
2008
               fflush(df);
 
2009
 
 
2010
#           endif
 
2011
 
 
2012
            /* remove from list */
 
2013
            LNK_DELETE(curr);
 
2014
            free_job(job_elem);
 
2015
         }
 
2016
 
 
2017
         continue;  /* skip precreated jobs */
 
2018
      }
 
2019
 
 
2020
#if defined(IRIX)
 
2021
 
 
2022
      if ((arse_elem = find_arsess(&arsess_list, job->jd_jid)) == NULL) {
 
2023
 
 
2024
         job->jd_refcnt = 0;
 
2025
         job->jd_proccount = 0;
 
2026
         free_process_list(job_elem);
 
2027
         job->jd_utime_c += job->jd_utime_a;
 
2028
         job->jd_stime_c += job->jd_stime_a;
 
2029
         job->jd_bwtime_c += job->jd_bwtime_a;
 
2030
         job->jd_rwtime_c += job->jd_rwtime_a;
 
2031
         job->jd_srtime_c += job->jd_srtime_a;
 
2032
         job->jd_utime_a = 0;
 
2033
         job->jd_stime_a = 0;
 
2034
         job->jd_bwtime_a = 0;
 
2035
         job->jd_rwtime_a = 0;
 
2036
         job->jd_srtime_a = 0;
 
2037
 
 
2038
      } else {
 
2039
         pid_t pidlist[2048], ses_pidlist[1024];
 
2040
         int pidmax = sizeof(pidlist)/sizeof(pid_t);
 
2041
         int ses_pidmax = sizeof(ses_pidlist)/sizeof(pid_t);
 
2042
         lnk_link_t *curra, *nexta;
 
2043
         pdc_arsess_t *arse = &arse_elem->arse;
 
2044
         static int pagesize;
 
2045
 
 
2046
         if (!pagesize)
 
2047
            pagesize = getpagesize();
 
2048
 
 
2049
         memset(&pidlist, 0, sizeof(pidlist));
 
2050
         memset(&ses_pidlist, 0, sizeof(ses_pidlist));
 
2051
 
 
2052
         /* get pids in the array session */
 
2053
 
 
2054
         syssgi(SGI_PIDSINASH, &job->jd_jid, &pidlist, pidmax);
 
2055
 
 
2056
         if (job->jd_tstamp == 0) {
 
2057
            job->jd_uid = -1;
 
2058
            job->jd_gid = -1;
 
2059
         }
 
2060
         job->jd_tstamp = time_stamp;
 
2061
         job->jd_mem = arse->mem * ((double)pagesize/1024.0/(double)HZ);
 
2062
         job->jd_chars = arse->chr + arse->chw;
 
2063
         /* Account ID of this job */
 
2064
         job->jd_acid = arse->prid;
 
2065
         /* total user time used (completed processes) */
 
2066
         job->jd_utime_c = arse->utime*1E-9;
 
2067
         /* total system time used (completed processes) */
 
2068
         job->jd_stime_c = arse->stime*1E-9;
 
2069
         /* total block-io-wait time used (completed processes) */
 
2070
         job->jd_bwtime_c = arse->bwtime*1E-9;
 
2071
         /* total raw-io-wait time used (completed processes) */
 
2072
         job->jd_rwtime_c = arse->rwtime*1E-9;
 
2073
         /* total srun-wait time used (completed processes) */
 
2074
         job->jd_srtime_c = arse->qwtime*1E-9;
 
2075
         /* Elapsed time of the job */
 
2076
         job->jd_etime = time_stamp - arse->start;
 
2077
         /* attached process count (from OS) */
 
2078
         job->jd_refcnt = (long)arse->refcnt;
 
2079
 
 
2080
         /* get pids in the POSIX session */
 
2081
 
 
2082
         syssgi(SGI_GETSESPID, arse_elem->arse.pid, &ses_pidlist, ses_pidmax);
 
2083
 
 
2084
         /* search for any array sessions created in the POSIX session 
 
2085
            by checking to see if the pid creating the array session
 
2086
            is one of the POSIX session pids. */
 
2087
           
 
2088
         for(curra=arsess_list.next; curra != &arsess_list; curra=nexta) {
 
2089
            arsess_elem_t *arsess_elem = LNK_DATA(curra, arsess_elem_t, link);
 
2090
            pdc_arsess_t *arse = &arsess_elem->arse;
 
2091
            nexta = curra->next;
 
2092
 
 
2093
            if (arse->ash != job->jd_jid &&
 
2094
                in_pidlist(ses_pidlist, ses_pidmax, arse->pid)) {
 
2095
 
 
2096
               arsess_elem_t *elem;
 
2097
 
 
2098
               /* remove array session element from main array session list
 
2099
                  and chain it onto the job array session list */
 
2100
 
 
2101
               LNK_DELETE(curra);
 
2102
               if ((elem=find_arsess(&job_elem->arses, arse->ash))) {
 
2103
                  LNK_DELETE(&elem->link);
 
2104
                  free(elem);
 
2105
               }
 
2106
               LNK_ADD(job_elem->arses.prev, &arsess_elem->link);
 
2107
 
 
2108
               /* attached process count (from OS) */
 
2109
               job->jd_refcnt += arse->refcnt;
 
2110
 
 
2111
            }
 
2112
         }
 
2113
 
 
2114
         /* get pids for all of the array sessions associated with the job */
 
2115
 
 
2116
         for(curra=job_elem->arses.next; curra != &job_elem->arses;
 
2117
             curra=curra->next) {
 
2118
 
 
2119
            arsess_elem_t *arsess_elem = LNK_DATA(curra, arsess_elem_t, link);
 
2120
            pdc_arsess_t *arse = &arsess_elem->arse;
 
2121
            int j;
 
2122
         
 
2123
            /* append pids in this array session to the pidlist */
 
2124
 
 
2125
            for(j=0; pidlist[j] && j<pidmax; j++) ;
 
2126
 
 
2127
            syssgi(SGI_PIDSINASH, &arse->ash, &pidlist[j],
 
2128
                   pidmax-j);
 
2129
         }
 
2130
 
 
2131
         /* if it is not time to collect process data then just
 
2132
            add the process usage times to the job data. */
 
2133
 
 
2134
         if (time_stamp <= pnext_time) {
 
2135
            lnk_link_t *currp;
 
2136
 
 
2137
            /* initialize active process times */
 
2138
            job->jd_utime_a = 0;
 
2139
            job->jd_stime_a = 0;
 
2140
            job->jd_bwtime_a = 0;
 
2141
            job->jd_rwtime_a = 0;
 
2142
            job->jd_srtime_a = 0;
 
2143
 
 
2144
            for(currp=job_elem->procs.next; currp != &job_elem->procs;
 
2145
                currp=currp->next) {
 
2146
 
 
2147
               proc_elem_t *proc_elem = LNK_DATA(currp, proc_elem_t, link);
 
2148
               psProc_t *proc = &proc_elem->proc;
 
2149
 
 
2150
               /* Note: if the process interval is larger than the
 
2151
               job interval, then there is a possibility that the
 
2152
               usage for a completed job will be counted both in the
 
2153
               in the active and complete process usage.  We avoid this by
 
2154
               only adding the process's usage to the job usage if the
 
2155
               process is in the ASH table active pid list of the job. */
 
2156
 
 
2157
               int j;
 
2158
               for (j=0; pidlist[j] && j<sizeof(pidlist)/sizeof(pid_t); j++)
 
2159
               if (pidlist[j] == proc->pd_pid) {
 
2160
 
 
2161
                  /* total user time used (active processes) */
 
2162
                  job->jd_utime_a += proc->pd_utime;
 
2163
 
 
2164
                  /* total system time used (active processes) */
 
2165
                  job->jd_stime_a += proc->pd_stime;
 
2166
 
 
2167
                  /* total block-io-wait time used (active processes) */
 
2168
                  job->jd_bwtime_a += proc_elem->bwtime;
 
2169
 
 
2170
                  /* total raw-io-wait time used (active processes) */
 
2171
                  job->jd_rwtime_a += proc_elem->rwtime;
 
2172
 
 
2173
                  /* total srun-wait time used (active processes) */
 
2174
                  job->jd_srtime_a += proc_elem->qwtime;
 
2175
 
 
2176
                  /* add active process memory usage to job */
 
2177
                  job->jd_mem += proc_elem->mem;
 
2178
 
 
2179
                  /* add active process I/O usage to job */
 
2180
                  job->jd_chars += proc_elem->chars;
 
2181
                  break;
 
2182
               }
 
2183
 
 
2184
            }
 
2185
 
 
2186
         } else {
 
2187
            proc_elem_t *proc_elem;
 
2188
            int j, proccount=0;
 
2189
            lnk_link_t old_procs;
 
2190
 
 
2191
            LNK_INIT(&old_procs);
 
2192
 
 
2193
            /* save old process list */
 
2194
            if (job_elem->procs.next != &job_elem->procs) {
 
2195
               old_procs.next = job_elem->procs.next;
 
2196
               old_procs.prev = job_elem->procs.prev;
 
2197
               old_procs.next->prev = &old_procs;
 
2198
               old_procs.prev->next = &old_procs;
 
2199
               LNK_INIT(&job_elem->procs);
 
2200
            }
 
2201
 
 
2202
            /* build new process list */
 
2203
            
 
2204
            /* initialize active process times */
 
2205
            job->jd_utime_a = 0;
 
2206
            job->jd_stime_a = 0;
 
2207
            job->jd_bwtime_a = 0;
 
2208
            job->jd_rwtime_a = 0;
 
2209
            job->jd_srtime_a = 0;
 
2210
            job->jd_vmem = 0;
 
2211
            job->jd_rss = 0;
 
2212
 
 
2213
            for (j=0; pidlist[j] && j<sizeof(pidlist)/sizeof(pid_t); j++) {
 
2214
 
 
2215
               if ((proc_elem=(proc_elem_t *)malloc(sizeof(proc_elem_t)))) {
 
2216
 
 
2217
                  prpsinfo_t psinfo;
 
2218
                  pracinfo_t prinfo;
 
2219
                  char fname[32];
 
2220
                  int fd;
 
2221
                  psProc_t *proc = &proc_elem->proc;
 
2222
                  
 
2223
                  memset(proc_elem, 0, sizeof(proc_elem_t));
 
2224
                  proc->pd_length = sizeof(psProc_t);
 
2225
 
 
2226
                  /* get data from /proc file system */
 
2227
 
 
2228
                  sprintf(fname, "/proc/%05ld", pidlist[j]);
 
2229
                  fd = open(fname, O_RDONLY);
 
2230
                  if (fd < 0) continue;
 
2231
 
 
2232
                  if (ioctl(fd, PIOCPSINFO, &psinfo) < 0 ||
 
2233
                      ioctl(fd, PIOCACINFO, &prinfo) < 0) {
 
2234
                     close(fd);
 
2235
                     free(proc_elem);
 
2236
                     pidlist[j] = -pidlist[j]; /* force report of old usage */
 
2237
                     continue;
 
2238
                  }
 
2239
 
 
2240
                  proc->pd_tstamp = time_stamp;
 
2241
                  proc->pd_pid = pidlist[j];
 
2242
                  proc->pd_uid = psinfo.pr_uid;
 
2243
                  proc->pd_gid = psinfo.pr_gid;
 
2244
                  if (job->jd_uid == -1) {
 
2245
                     /* user ID of this job */
 
2246
                     job->jd_uid = proc->pd_uid;
 
2247
                     /* group ID of this job */
 
2248
                     job->jd_gid = proc->pd_gid;
 
2249
                  }
 
2250
                  proc->pd_acid = prinfo.pr_prid;
 
2251
                  proc->pd_state = 1;
 
2252
                  proc->pd_pstart = psinfo.pr_start.tv_sec +
 
2253
                        psinfo.pr_start.tv_nsec*1E-9;
 
2254
                  proc->pd_utime = prinfo.pr_timers.ac_utime*1E-9;
 
2255
                  proc->pd_stime = prinfo.pr_timers.ac_stime*1E-9;
 
2256
                  proc_elem->jid = prinfo.pr_ash;
 
2257
                  proc_elem->bwtime = prinfo.pr_timers.ac_bwtime*1E-9;
 
2258
                  proc_elem->rwtime = prinfo.pr_timers.ac_rwtime*1E-9;
 
2259
                  proc_elem->qwtime = prinfo.pr_timers.ac_qwtime*1E-9;
 
2260
                  proc_elem->mem = prinfo.pr_counts.ac_mem *
 
2261
                          ((double)pagesize/1024.0/(double)HZ);
 
2262
                  proc_elem->chars = prinfo.pr_counts.ac_chr +
 
2263
                        prinfo.pr_counts.ac_chw;
 
2264
                  proc_elem->vmem = psinfo.pr_size * pagesize;
 
2265
                  proc_elem->rss = psinfo.pr_rssize * pagesize;
 
2266
 
 
2267
                  job->jd_vmem += proc_elem->vmem;
 
2268
 
 
2269
                  job->jd_rss += proc_elem->rss;
 
2270
 
 
2271
                  /* total user time used (active processes) */
 
2272
                  job->jd_utime_a += proc->pd_utime;
 
2273
 
 
2274
                  /* total system time used (active processes) */
 
2275
                  job->jd_stime_a += proc->pd_stime;
 
2276
 
 
2277
                  /* total block-io-wait time used (active processes) */
 
2278
                  job->jd_bwtime_a += proc_elem->bwtime;
 
2279
 
 
2280
                  /* total raw-io-wait time used (active processes) */
 
2281
                  job->jd_rwtime_a += proc_elem->rwtime;
 
2282
 
 
2283
                  /* total srun-wait time used (active processes) */
 
2284
                  job->jd_srtime_a += proc_elem->qwtime;
 
2285
 
 
2286
                  /* add active process memory usage to job */
 
2287
                  job->jd_mem += proc_elem->mem;
 
2288
 
 
2289
                  /* add active process I/O usage to job */
 
2290
                  job->jd_chars += proc_elem->chars;
 
2291
 
 
2292
                  close(fd);
 
2293
 
 
2294
                  /* add process element to end of process list */
 
2295
                  LNK_ADD(job_elem->procs.prev, &proc_elem->link);
 
2296
 
 
2297
                  proccount++;
 
2298
               }
 
2299
 
 
2300
            }
 
2301
 
 
2302
            job->jd_proccount = proccount;
 
2303
            job->jd_himem = MAX(job->jd_himem, job->jd_vmem);
 
2304
 
 
2305
            /* free old process list. If one of the old processes is not
 
2306
               in the new pid list and the old process belongs to a
 
2307
               different ASH than the main job ASH, then accumulate its
 
2308
               usage. Also if a process is in the pid list but is deleted
 
2309
               before we are able to collect its process usage, then report
 
2310
               its process usage as completed usage. */
 
2311
            {
 
2312
               lnk_link_t *currp;
 
2313
               while((currp=old_procs.next) != &old_procs) {
 
2314
                  proc_elem_t *tproc_elem = LNK_DATA(currp, proc_elem_t, link);
 
2315
                  psProc_t *tproc = &tproc_elem->proc;
 
2316
                  if (!in_pidlist(pidlist, pidmax, tproc->pd_pid)) {
 
2317
                     if (job->jd_jid != tproc_elem->jid) {
 
2318
                        job_elem->utime += tproc->pd_utime;
 
2319
                        job_elem->stime += tproc->pd_stime;
 
2320
                        job_elem->bwtime += tproc_elem->bwtime;
 
2321
                        job_elem->rwtime += tproc_elem->rwtime;
 
2322
                        job_elem->srtime += tproc_elem->qwtime;
 
2323
                        job_elem->mem += tproc_elem->mem;
 
2324
                        job_elem->chars += tproc_elem->chars;
 
2325
                     } else if (in_pidlist(pidlist, pidmax, -tproc->pd_pid)) {
 
2326
                        job->jd_utime_c += tproc->pd_utime;
 
2327
                        job->jd_stime_c += tproc->pd_stime;
 
2328
                        job->jd_bwtime_c += tproc_elem->bwtime;
 
2329
                        job->jd_rwtime_c += tproc_elem->rwtime;
 
2330
                        job->jd_srtime_c += tproc_elem->qwtime;
 
2331
                        job->jd_mem += tproc_elem->mem;
 
2332
                        job->jd_chars += tproc_elem->chars;
 
2333
                     }
 
2334
                  }
 
2335
                  LNK_DELETE(currp);
 
2336
                  free(tproc_elem);
 
2337
               }
 
2338
            }
 
2339
         }
 
2340
 
 
2341
         /* add in usage for completed processes from other ASHes */
 
2342
         job->jd_utime_c += job_elem->utime;
 
2343
         job->jd_stime_c += job_elem->stime;
 
2344
         job->jd_bwtime_c += job_elem->bwtime;
 
2345
         job->jd_rwtime_c += job_elem->rwtime;
 
2346
         job->jd_srtime_c += job_elem->srtime;
 
2347
         job->jd_mem += job_elem->mem;
 
2348
         job->jd_chars += job_elem->chars;
 
2349
 
 
2350
#ifdef notdef
 
2351
         /* add in memory and I/O usage from other ASHes */
 
2352
         for(curra=job_elem->arses.next; curra!=&job_elem->arses;
 
2353
             curra=curra->next) {
 
2354
            arsess_elem_t *arsess_elem = LNK_DATA(curra, arsess_elem_t, link);
 
2355
            pdc_arsess_t *arse = &arsess_elem->arse;
 
2356
 
 
2357
            job->jd_mem += arse->mem;
 
2358
            job->jd_chars += arse->chr + arse->chw;
 
2359
         }
 
2360
#endif
 
2361
 
 
2362
      }
 
2363
 
 
2364
#elif defined(ALPHA) || defined(FREEBSD) || defined(LINUX) || defined(SOLARIS) || defined(HP1164) || defined(DARWIN)
 
2365
      {
 
2366
         int proccount;
 
2367
         lnk_link_t *currp, *nextp;
 
2368
 
 
2369
         /* sum up usage of each processes for this job */
 
2370
         proccount = job->jd_proccount;
 
2371
         job->jd_utime_a = job->jd_stime_a = 0;
 
2372
         job->jd_vmem = 0;
 
2373
         job->jd_rss = 0;
 
2374
 
 
2375
         for(currp=job_elem->procs.next; currp != &job_elem->procs;
 
2376
             currp=nextp) {
 
2377
 
 
2378
            proc_elem_t *proc_elem = LNK_DATA(currp, proc_elem_t, link);
 
2379
            psProc_t *proc = &proc_elem->proc;
 
2380
 
 
2381
            nextp = currp->next; /* in case currp is deleted */
 
2382
 
 
2383
            if (time_stamp == proc->pd_tstamp) { 
 
2384
               /* maybe still living */
 
2385
               job->jd_utime_a += proc->pd_utime;    
 
2386
               job->jd_stime_a += proc->pd_stime;    
 
2387
               job->jd_vmem += proc_elem->vmem;    
 
2388
               job->jd_rss += proc_elem->rss;    
 
2389
               job->jd_mem += (proc_elem->mem/1024.0);    
 
2390
#if defined(ALPHA)
 
2391
               job->jd_chars += proc_elem->delta_chars;     
 
2392
#endif
 
2393
            } else { 
 
2394
               /* most likely exited */
 
2395
               job->jd_utime_c += proc->pd_utime;    
 
2396
               job->jd_stime_c += proc->pd_stime;    
 
2397
               job->jd_proccount--;
 
2398
              
 
2399
               /* remove process entry from list */
 
2400
#ifdef MONITOR_PDC
 
2401
               INFO((SGE_EVENT, "lost process "pid_t_fmt" for job "pid_t_fmt" (utime = %f stime = %f)\n", 
 
2402
                     proc->pd_pid, job->jd_jid, proc->pd_utime, proc->pd_stime));
 
2403
#endif
 
2404
               LNK_DELETE(currp);
 
2405
               free(proc_elem);
 
2406
            }
 
2407
         }
 
2408
         /* estimate high water memory mark */
 
2409
         if (job->jd_vmem > job->jd_himem)
 
2410
            job->jd_himem = job->jd_vmem;
 
2411
      } 
 
2412
 
 
2413
#elif defined(CRAY)
 
2414
 
 
2415
      {
 
2416
         lnk_link_t *currp, *nextp;
 
2417
 
 
2418
         /* If the job was not in the session table, set a timeout after */
 
2419
         /* which we will consider the job complete. The timeout is set */
 
2420
         /* to give us a chance to read the job completion record from */
 
2421
         /* the pacct data during the next interval. */
 
2422
 
 
2423
         if (job->jd_tstamp != time_stamp && job->jd_refcnt) {
 
2424
            if (job_elem->timeout == 0)
 
2425
               job_elem->timeout = time_stamp + 5;
 
2426
            else if (job_elem->timeout < time_stamp)
 
2427
               job->jd_refcnt = 0;
 
2428
         }
 
2429
 
 
2430
         /* set the job's active CPU time to the total CPU time */
 
2431
         /* of the active processes */
 
2432
 
 
2433
         job->jd_utime_a = 0;
 
2434
         job->jd_stime_a = 0;
 
2435
         job->jd_srtime_a = 0;
 
2436
 
 
2437
         for(currp=job_elem->procs.next; currp != &job_elem->procs;
 
2438
             currp=nextp) {
 
2439
            proc_elem_t *proc_elem = LNK_DATA(currp, proc_elem_t, link);
 
2440
            psProc_t *proc = &proc_elem->proc;
 
2441
 
 
2442
            nextp = currp->next; /* in case currp is deleted */
 
2443
 
 
2444
            if (time_stamp == proc->pd_tstamp) { 
 
2445
 
 
2446
               job->jd_utime_a += proc->pd_utime; /* job active user time */
 
2447
               job->jd_stime_a += proc->pd_stime; /* job active system time */
 
2448
               job->jd_srtime_a += proc_elem->qwtime; /* job srun-wait time */
 
2449
 
 
2450
            } else { 
 
2451
 
 
2452
               /* process exited, remove process entry from list */
 
2453
               job->jd_proccount--;
 
2454
               job->jd_srtime_c += proc_elem->qwtime; /* job srun-wait time */
 
2455
               LNK_DELETE(currp);
 
2456
               free(proc_elem);
 
2457
            }
 
2458
         }
 
2459
 
 
2460
         /* set the job's completed CPU time to the session CPU time */
 
2461
         /* minus the job's active CPU time */
 
2462
         
 
2463
         job->jd_utime_c = MAX(job_elem->utime - job->jd_utime_a, 0);
 
2464
         job->jd_stime_c = MAX(job_elem->stime - job->jd_stime_a, 0);
 
2465
      }
 
2466
 
 
2467
#endif
 
2468
   }
 
2469
 
 
2470
#ifdef IRIX
 
2471
   free_arsess_list(&arsess_list);
 
2472
#endif
 
2473
 
 
2474
   if (time_stamp > pnext_time)
 
2475
      pnext_time = time_stamp + ps_config.prc_collection_interval;
 
2476
 
 
2477
   DRETURN(0);
 
2478
}
 
2479
 
 
2480
static time_t start_time;
 
2481
 
 
2482
int psStartCollector(void)
 
2483
{
 
2484
   static int initialized = 0;
 
2485
#ifdef PDC_STANDALONE
 
2486
   int ncpus = 0;
 
2487
#endif   
 
2488
 
 
2489
#if defined(ALPHA)
 
2490
   int start=0;
 
2491
#endif
 
2492
 
 
2493
   if (initialized)
 
2494
      return 0;
 
2495
 
 
2496
   initialized = 1;
 
2497
 
 
2498
#if defined(LINUX)
 
2499
   /* 
 
2500
    * supplementary groups in proc filesystem? 
 
2501
    */
 
2502
   sup_grp_in_proc = groups_in_proc();
 
2503
#endif
 
2504
 
 
2505
   LNK_INIT(&job_list);
 
2506
   start_time = get_gmt();
 
2507
 
 
2508
 
 
2509
#ifdef PDC_STANDALONE
 
2510
   /* Length of struct (set@run-time) */
 
2511
   sysdata.sys_length = sizeof(sysdata);
 
2512
#endif
 
2513
 
 
2514
   /* page size */
 
2515
   pagesize = getpagesize();
 
2516
 
 
2517
   /* retrieve static parameters */
 
2518
#if defined(LINUX) || defined(ALINUX) || defined(IRIX) || defined(SOLARIS) || defined(DARWIN) || defined(FREEBSD) || defined(NETBSD) || defined(HP1164)
 
2519
#ifdef PDC_STANDALONE
 
2520
   ncpus = sge_nprocs();
 
2521
#endif   
 
2522
#elif defined(ALPHA)
 
2523
   {
 
2524
#ifdef PDC_STANDALONE
 
2525
      /* Number of CPUs */
 
2526
      ncpus = sge_nprocs();
 
2527
      if (getsysinfo(GSI_PHYSMEM, (caddr_t)&physical_memory,sizeof(int),0,NULL)==-1) {
 
2528
         return -1;
 
2529
      }
 
2530
 
 
2531
      unixname[0] = '/';
 
2532
      if ((getsysinfo(GSI_BOOTEDFILE, &unixname[1],
 
2533
         sizeof(unixname), NULL, NULL)) <= 0) {
 
2534
         strcpy(unixname, _PATH_UNIX);
 
2535
      }
 
2536
 
 
2537
      if (nlist(unixname, mem_nl) == -1) {
 
2538
         return -1;
 
2539
      }
 
2540
      if (mem_nl[PERFSUM].n_value == 0) {
 
2541
         return -1;
 
2542
      }
 
2543
 
 
2544
      if ((kmem_fd = open(_PATH_KMEM,O_RDONLY,0)) == -1) {
 
2545
         return -1;
 
2546
      }
 
2547
 
 
2548
#endif
 
2549
   } 
 
2550
 
 
2551
#elif defined(CRAY)
 
2552
#ifdef PDC_STANDALONE
 
2553
   ncpus = 0; /* Set in psRetrieveSysData because it is dynamic on Cray */
 
2554
#endif
 
2555
 
 
2556
#endif
 
2557
#ifdef PDC_STANDALONE
 
2558
   sysdata.sys_ncpus = ncpus;
 
2559
#endif   
 
2560
   return 0;
 
2561
}
 
2562
 
 
2563
 
 
2564
int psStopCollector(void)
 
2565
{
 
2566
#if defined(ALPHA)
 
2567
   close(kmem_fd);
 
2568
#endif
 
2569
 
 
2570
   return 0;
 
2571
}
 
2572
 
 
2573
 
 
2574
int psWatchJob(JobID_t JobID)
 
2575
{
 
2576
   lnk_link_t *curr;
 
2577
 
 
2578
#  if DEBUG
 
2579
 
 
2580
      if (df == NULL)
 
2581
         df = fopen("/tmp/pacct.out", "w");
 
2582
      fprintf(df, "%d watching "F64"\n", get_gmt(), JobID);
 
2583
      fflush(df);
 
2584
 
 
2585
#  endif
 
2586
 
 
2587
   /* if job to watch is not already in the list then add it */
 
2588
 
 
2589
   if ((curr=find_job(JobID))) {
 
2590
      LNK_DATA(curr, job_elem_t, link)->precreated = 0;
 
2591
   } else {
 
2592
      job_elem_t *job_elem = (job_elem_t *)malloc(sizeof(job_elem_t));
 
2593
      memset(job_elem, 0, sizeof(job_elem_t));
 
2594
      job_elem->starttime = get_gmt();
 
2595
      job_elem->job.jd_jid = JobID;
 
2596
      job_elem->job.jd_length = sizeof(psJob_t);
 
2597
      LNK_INIT(&job_elem->procs);
 
2598
      LNK_INIT(&job_elem->arses);
 
2599
      /* add to job list */
 
2600
      LNK_ADD(job_list.prev, &job_elem->link);
 
2601
   }
 
2602
 
 
2603
   return 0;
 
2604
}
 
2605
 
 
2606
 
 
2607
int psIgnoreJob(JobID_t JobID) {
 
2608
   lnk_link_t *curr;
 
2609
 
 
2610
   /* if job is in the list, remove it */
 
2611
 
 
2612
   if ((curr = find_job(JobID))) {
 
2613
      LNK_DELETE(curr);
 
2614
      free_job(LNK_DATA(curr, job_elem_t, link));
 
2615
   }
 
2616
 
 
2617
   return 0;
 
2618
}
 
2619
 
 
2620
 
 
2621
struct psStat_s *psStatus(void)
 
2622
{
 
2623
   psStat_t *pstat;
 
2624
   static time_t last_time_stamp;
 
2625
   time_t time_stamp = get_gmt();
 
2626
 
 
2627
   if ((pstat = (psStat_t *)malloc(sizeof(psStat_t)))==NULL) {
 
2628
      return NULL;
 
2629
   }
 
2630
 
 
2631
   /* Length of struct (set@run-time) */
 
2632
   pstat->stat_length = sizeof(psStat_t);
 
2633
 
 
2634
   /* Time of last sample */
 
2635
   pstat->stat_tstamp = last_time_stamp;
 
2636
 
 
2637
   /* our pid */
 
2638
   pstat->stat_ifmpid = getpid();
 
2639
 
 
2640
   /* DC pid */
 
2641
   pstat->stat_DCpid = getpid();
 
2642
 
 
2643
   /* IFM pid */
 
2644
   pstat->stat_IFMpid = getpid();
 
2645
 
 
2646
   /* elapsed time (to *now*, not snap) */
 
2647
   pstat->stat_elapsed = time_stamp - start_time;
 
2648
 
 
2649
   /* user CPU time used by DC */
 
2650
   pstat->stat_DCutime = 0;
 
2651
 
 
2652
   /* sys CPU time used by DC */
 
2653
   pstat->stat_DCstime = 0;
 
2654
 
 
2655
   /* user CPU time used by IFM */
 
2656
   pstat->stat_IFMutime = 0;
 
2657
 
 
2658
   /* sys CPU time used by IFM */
 
2659
   pstat->stat_IFMstime = 0;
 
2660
 
 
2661
   /* number of jobs tracked */
 
2662
   pstat->stat_jobcount = get_numjobs();
 
2663
 
 
2664
   last_time_stamp = time_stamp;
 
2665
 
 
2666
   return pstat;
 
2667
}
 
2668
 
 
2669
 
 
2670
struct psJob_s *psGetOneJob(JobID_t JobID)
 
2671
{
 
2672
   psJob_t *job;
 
2673
   lnk_link_t *curr;
 
2674
   job_elem_t *job_elem = NULL;
 
2675
   int found = 0;
 
2676
   struct rjob_s {
 
2677
      psJob_t job;
 
2678
      psProc_t proc[1];
 
2679
   } *rjob = NULL;
 
2680
 
 
2681
   /* retrieve job data */
 
2682
   psRetrieveOSJobData();
 
2683
 
 
2684
   /* see if job is in list */
 
2685
 
 
2686
   for (curr=job_list.next; curr != &job_list; curr=curr->next) {
 
2687
      job_elem = LNK_DATA(curr, job_elem_t, link);
 
2688
      if (job_elem->precreated) continue; /* skip precreated jobs */
 
2689
      if (job_elem->job.jd_jid == JobID) {
 
2690
         found = 1;
 
2691
         break;
 
2692
      }
 
2693
   }
 
2694
 
 
2695
   if (found) {
 
2696
      unsigned long rsize;
 
2697
 
 
2698
      job = &job_elem->job;
 
2699
      rsize = sizeof(psJob_t) + job->jd_proccount * sizeof(psProc_t);
 
2700
      if ((rjob = (struct rjob_s *)malloc(rsize))) {
 
2701
         memcpy(&rjob->job, job, sizeof(psJob_t));
 
2702
         {
 
2703
            lnk_link_t *currp;
 
2704
            int nprocs = 0;
 
2705
 
 
2706
            for (currp=job_elem->procs.next; currp != &job_elem->procs;
 
2707
                     currp=currp->next) {
 
2708
               psProc_t *proc = &(LNK_DATA(currp, proc_elem_t, link)->proc);
 
2709
               memcpy(&rjob->proc[nprocs++], proc, sizeof(psProc_t));
 
2710
            }
 
2711
         }
 
2712
      }
 
2713
   }
 
2714
 
 
2715
   return (struct psJob_s *)rjob;
 
2716
}
 
2717
 
 
2718
 
 
2719
struct psJob_s *psGetAllJobs(void)
 
2720
{
 
2721
   psJob_t *rjob, *jobs;
 
2722
   lnk_link_t *curr;
 
2723
   long rsize;
 
2724
   uint64 jobcount = 0;
 
2725
 
 
2726
   /* retrieve job data */
 
2727
   psRetrieveOSJobData();
 
2728
 
 
2729
   /* calculate size of return data */
 
2730
#ifndef SOLARIS
 
2731
   rsize = sizeof(uint64);
 
2732
#else
 
2733
   rsize = 8;
 
2734
#endif
 
2735
 
 
2736
   for (curr=job_list.next; curr != &job_list; curr=curr->next) {
 
2737
      job_elem_t *job_elem = LNK_DATA(curr, job_elem_t, link);
 
2738
      psJob_t *job = &job_elem->job;
 
2739
      if (job_elem->precreated) continue; /* skip precreated jobs */
 
2740
      rsize += (sizeof(psJob_t) + (job->jd_proccount*sizeof(psProc_t)));
 
2741
      jobcount++;
 
2742
   }
 
2743
 
 
2744
   /* allocate space for return data */
 
2745
   if ((rjob = (psJob_t *)malloc(rsize)) == NULL)
 
2746
      return rjob;
 
2747
  
 
2748
   /* allign adress */
 
2749
 
 
2750
   /* fill in return data */
 
2751
   jobs = rjob;
 
2752
   *(uint64 *)jobs = jobcount;
 
2753
#ifndef SOLARIS
 
2754
   INCJOBPTR(jobs, sizeof(uint64));
 
2755
#else
 
2756
   INCJOBPTR(jobs, 8);
 
2757
#endif
 
2758
 
 
2759
   /* copy the job data */
 
2760
   for (curr=job_list.next; curr != &job_list; curr=curr->next) {
 
2761
      job_elem_t *job_elem = LNK_DATA(curr, job_elem_t, link);
 
2762
      psJob_t *job = &job_elem->job;
 
2763
      psProc_t *procs;
 
2764
 
 
2765
      if (job_elem->precreated) continue; /* skip precreated jobs */
 
2766
      memcpy(jobs, job, sizeof(psJob_t));
 
2767
      INCJOBPTR(jobs, sizeof(psJob_t));
 
2768
 
 
2769
      /* copy the process data */
 
2770
      procs = (psProc_t *)jobs;
 
2771
      {
 
2772
         lnk_link_t *currp;
 
2773
         for (currp=job_elem->procs.next; currp != &job_elem->procs; currp=currp->next) {
 
2774
            psProc_t *proc = &(LNK_DATA(currp, proc_elem_t, link)->proc);
 
2775
            memcpy(procs, proc, sizeof(psProc_t));
 
2776
            INCPROCPTR(procs, sizeof(psProc_t));
 
2777
         }
 
2778
      }
 
2779
      jobs = (psJob_t *)procs;
 
2780
 
 
2781
   }
 
2782
 
 
2783
   return rjob;
 
2784
}
 
2785
 
 
2786
 
 
2787
#ifdef PDC_STANDALONE
 
2788
struct psSys_s *psGetSysdata(void)
 
2789
{
 
2790
   psSys_t *sd;
 
2791
 
 
2792
   /* go get system data */
 
2793
   psRetrieveSystemData();
 
2794
 
 
2795
   if ((sd = (psSys_t *)malloc(sizeof(psSys_t))) == NULL) {
 
2796
      return NULL;
 
2797
   }
 
2798
   memcpy(sd, &sysdata, sizeof(psSys_t));
 
2799
   return sd;
 
2800
}
 
2801
#endif
 
2802
 
 
2803
int psVerify(void)
 
2804
{
 
2805
   return 0;
 
2806
}
 
2807
 
 
2808
 
 
2809
#ifdef MODULE_TEST
 
2810
 
 
2811
#define INTOMEGS(x) (((double)x)/(1024*1024))
 
2812
 
 
2813
 
 
2814
 
 
2815
void
 
2816
usage(void)
 
2817
{
 
2818
   fprintf(stderr, "\n%s\n\n", MSG_SGE_USAGE);
 
2819
   fprintf(stderr, "\t-s\t%s\n",  MSG_SGE_s_OPT_USAGE);
 
2820
   fprintf(stderr, "\t-n\t%s\n",  MSG_SGE_n_OPT_USAGE);
 
2821
   fprintf(stderr, "\t-p\t%s\n",  MSG_SGE_p_OPT_USAGE);
 
2822
   fprintf(stderr, "\t-i\t%s\n",  MSG_SGE_i_OPT_USAGE);
 
2823
   fprintf(stderr, "\t-g\t%s\n",  MSG_SGE_g_OPT_USAGE);
 
2824
   fprintf(stderr, "\t-j\t%s\n",  MSG_SGE_j_OPT_USAGE);
 
2825
   fprintf(stderr, "\t-J\t%s\n",  MSG_SGE_J_OPT_USAGE);
 
2826
   fprintf(stderr, "\t-k\t%s\n",  MSG_SGE_k_OPT_USAGE);
 
2827
   fprintf(stderr, "\t-K\t%s\n",  MSG_SGE_K_OPT_USAGE);
 
2828
   fprintf(stderr, "\t-P\t%s\n",  MSG_SGE_P_OPT_USAGE);
 
2829
   fprintf(stderr, "\t-S\t%s\n",  MSG_SGE_S_OPT_USAGE);
 
2830
}
 
2831
 
 
2832
 
 
2833
static void
 
2834
print_job_data(psJob_t *job)
 
2835
{
 
2836
   printf("%s\n", MSG_SGE_JOBDATA );
 
2837
   printf("jd_jid="OSJOBID_FMT"\n", job->jd_jid);
 
2838
   printf("jd_length=%d\n", job->jd_length);
 
2839
   printf("jd_uid="uid_t_fmt"\n", job->jd_uid);
 
2840
   printf("jd_gid="uid_t_fmt"\n", job->jd_gid);
 
2841
#if defined(IRIX) || defined(CRAY)
 
2842
   printf("jd_acid="F64"\n", job->jd_acid);
 
2843
#endif
 
2844
   printf("jd_tstamp=%s\n", ctime(&job->jd_tstamp));
 
2845
   printf("jd_proccount=%d\n", (int)job->jd_proccount);
 
2846
   printf("jd_refcnt=%d\n", (int)job->jd_refcnt);
 
2847
   printf("jd_etime=%8.3f\n", job->jd_etime);
 
2848
   printf("jd_utime_a=%8.3f\n", job->jd_utime_a);
 
2849
   printf("jd_stime_a=%8.3f\n", job->jd_stime_a);
 
2850
#if defined(IRIX)
 
2851
   printf("jd_bwtime_a=%8.3f\n", job->jd_bwtime_a);
 
2852
   printf("jd_rwtime_a=%8.3f\n", job->jd_rwtime_a);
 
2853
#endif
 
2854
   printf("jd_srtime_a=%8.3f\n", job->jd_srtime_a);
 
2855
   printf("jd_utime_c=%8.3f\n", job->jd_utime_c);
 
2856
   printf("jd_stime_c=%8.3f\n", job->jd_stime_c);
 
2857
#if defined(IRIX)
 
2858
   printf("jd_bwtime_c=%8.3f\n", job->jd_bwtime_c);
 
2859
   printf("jd_rwtime_c=%8.3f\n", job->jd_rwtime_c);
 
2860
#endif
 
2861
   printf("jd_srtime_c=%8.3f\n", job->jd_srtime_c);
 
2862
   printf("jd_mem="F64"\n", job->jd_mem);
 
2863
   printf("jd_chars=%8.3fM\n", INTOMEGS(job->jd_chars));
 
2864
   printf("jd_vmem=%8.3fM\n", INTOMEGS(job->jd_vmem));
 
2865
   printf("jd_rss=%8.3fM\n", INTOMEGS(job->jd_rss));
 
2866
   printf("jd_himem=%8.3fM\n", INTOMEGS(job->jd_himem));
 
2867
#if defined(CRAY)
 
2868
   printf("jd_fsblks="F64"\n", job->jd_fsblks);
 
2869
#endif
 
2870
}
 
2871
static void
 
2872
print_process_data(psProc_t *proc)
 
2873
{
 
2874
   printf("\t******* Process Data *******\n");
 
2875
   printf("\tpd_pid="pid_t_fmt"\n", proc->pd_pid);
 
2876
   printf("\tpd_length=%d\n", (int)proc->pd_length);
 
2877
   printf("\tpd_tstamp=%s\n", ctime(&proc->pd_tstamp));
 
2878
   printf("\tpd_uid="uid_t_fmt"\n", proc->pd_uid);
 
2879
   printf("\tpd_gid="uid_t_fmt"\n", proc->pd_gid);
 
2880
   printf("\tpd_acid="F64"\n", proc->pd_acid);
 
2881
   printf("\tpd_state=%d\n", (int)proc->pd_state);
 
2882
   printf("\tpd_pstart=%8.3f\n", proc->pd_pstart);
 
2883
   printf("\tpd_utime=%8.3f\n", proc->pd_utime);
 
2884
   printf("\tpd_stime=%8.3f\n", proc->pd_stime);
 
2885
}
 
2886
 
 
2887
 
 
2888
#if 0
 
2889
static void
 
2890
print_system_data(psSys_t *sys)
 
2891
{
 
2892
   printf("%s\n", MSG_SGE_SYSTEMDATA );
 
2893
   printf("sys_length=%d\n", (int)sys->sys_length);
 
2894
   printf("sys_ncpus=%d\n", (int)sys->sys_ncpus);
 
2895
   printf("sys_tstamp=%s\n", ctime(&sys->sys_tstamp));
 
2896
   printf("sys_ttimet=%8.3f\n", sys->sys_ttimet);
 
2897
   printf("sys_ttime=%8.3f\n", sys->sys_ttime);
 
2898
   printf("sys_utimet=%8.3f\n", sys->sys_utimet);
 
2899
   printf("sys_utime=%8.3f\n", sys->sys_utime);
 
2900
   printf("sys_stimet=%8.3f\n", sys->sys_stimet);
 
2901
   printf("sys_stime=%8.3f\n", sys->sys_stime);
 
2902
   printf("sys_itimet=%8.3f\n", sys->sys_itimet);
 
2903
   printf("sys_itime=%8.3f\n", sys->sys_itime);
 
2904
   printf("sys_srtimet=%8.3f\n", sys->sys_srtimet);
 
2905
   printf("sys_srtime=%8.3f\n", sys->sys_srtime);
 
2906
   printf("sys_wtimet=%8.3f\n", sys->sys_wtimet);
 
2907
   printf("sys_wtime=%8.3f\n", sys->sys_wtime);
 
2908
 
 
2909
   printf("sys_swp_total=%8.3fM\n", INTOMEGS(sys->sys_swp_total));
 
2910
   printf("sys_swp_free=%8.3fM\n", INTOMEGS(sys->sys_swp_free));
 
2911
   printf("sys_swp_used=%8.3fM\n", INTOMEGS(sys->sys_swp_used));
 
2912
   printf("sys_swp_virt=%8.3fM\n", INTOMEGS(sys->sys_swp_virt));
 
2913
   printf("sys_swp_rate=%8.3f\n", sys->sys_swp_rate);
 
2914
   printf("sys_mem_avail=%8.3fM\n", INTOMEGS(sys->sys_mem_avail));
 
2915
   printf("sys_mem_used=%8.3fM\n", INTOMEGS(sys->sys_mem_used));
 
2916
 
 
2917
   printf("sys_swpocc=%8.3f\n", sys->sys_swpocc);
 
2918
   printf("sys_swpque=%8.3f\n", sys->sys_swpque);
 
2919
   printf("sys_runocc=%8.3f\n", sys->sys_runocc);
 
2920
   printf("sys_runque=%8.3f\n", sys->sys_runque);
 
2921
   printf("sys_readch="F64"\n", sys->sys_readch);
 
2922
   printf("sys_writech="F64"\n", sys->sys_writech);
 
2923
}
 
2924
#endif
 
2925
 
 
2926
 
 
2927
static void
 
2928
print_status(psStat_t *stat)
 
2929
{
 
2930
   printf("%s\n", MSG_SGE_STATUS );
 
2931
   printf("stat_length=%d\n", (int)stat->stat_length);
 
2932
   printf("stat_tstamp=%s\n", ctime(&stat->stat_tstamp));
 
2933
   printf("stat_ifmpid=%d\n", (int)stat->stat_ifmpid);
 
2934
   printf("stat_DCpid=%d\n", (int)stat->stat_DCpid);
 
2935
   printf("stat_IFMpid=%d\n", (int)stat->stat_IFMpid);
 
2936
   printf("stat_elapsed=%d\n", (int)stat->stat_elapsed);
 
2937
   printf("stat_DCutime=%8.3f\n", stat->stat_DCutime);
 
2938
   printf("stat_DCstime=%8.3f\n", stat->stat_DCstime);
 
2939
   printf("stat_IFMutime=%8.3f\n", stat->stat_IFMutime);
 
2940
   printf("stat_IFMstime=%8.3f\n", stat->stat_IFMstime);
 
2941
   printf("stat_jobcount=%d\n", (int)stat->stat_jobcount);
 
2942
}
 
2943
 
 
2944
 
 
2945
int
 
2946
main(int argc, char **argv)
 
2947
{
 
2948
   char sgeview_bar_title[256] = "";  
 
2949
   char sgeview_window_title[256] = ""; 
 
2950
   int arg;
 
2951
   JobID_t osjobid;
 
2952
   extern int optind;
 
2953
   extern char *optarg;
 
2954
   int verbose = 1;
 
2955
   int showproc = 0;
 
2956
   int interval = 2;
 
2957
   int system = 0;
 
2958
   int use_getonejob = 0;
 
2959
   int sgeview = 0;
 
2960
   int killjob = 0;
 
2961
   int forcekill = 0;
 
2962
   int signo = 15;
 
2963
   int c;
 
2964
   int sysi=-1, jobi=-1, prci=-1;
 
2965
   int numjobs = 0;
 
2966
   double *curr_cpu=NULL, *prev_cpu=NULL, *diff_cpu=NULL;
 
2967
   int jobid_count = 0;
 
2968
   char *jobids[256];
 
2969
   dstring ds;
 
2970
   char buffer[256];
 
2971
 
 
2972
   sge_dstring_init(&ds, buffer, sizeof(buffer));
 
2973
   sprintf(sgeview_bar_title, "%-.250s", MSG_SGE_CPUUSAGE  );
 
2974
   sprintf(sgeview_window_title, "%-.100s %-.150s", feature_get_product_name(FS_SHORT, &ds) ,MSG_SGE_SGEJOBUSAGECOMPARSION );
 
2975
 
 
2976
#ifdef __SGE_COMPILE_WITH_GETTEXT__ 
 
2977
   /* init language output for gettext() , it will use the right language */
 
2978
   install_language_func((gettext_func_type)        gettext,
 
2979
                         (setlocale_func_type)      setlocale,
 
2980
                         (bindtextdomain_func_type) bindtextdomain,
 
2981
                         (textdomain_func_type)     textdomain);
 
2982
   sge_lang_init(NULL,NULL);   
 
2983
#endif /* __SGE_COMPILE_WITH_GETTEXT__  */
 
2984
   
 
2985
   psStartCollector();
 
2986
 
 
2987
   if (argc < 2) {
 
2988
      usage();
 
2989
      exit(1);
 
2990
   }
 
2991
 
 
2992
   while ((c = getopt(argc, argv, "g1snpi:S:J:P:j:k:K:")) != -1)
 
2993
      switch(c) {
 
2994
         case 'g':
 
2995
            sgeview = 1;
 
2996
            break;
 
2997
         case 'j':
 
2998
            jobids[jobid_count++] = optarg;
 
2999
            break;
 
3000
         case 'K':
 
3001
            forcekill = 1;
 
3002
            /* no break here, fall into 'k' case */
 
3003
         case 'k':
 
3004
            killjob = 1;
 
3005
            if (sscanf(optarg, "%d", &signo)!=1) {
 
3006
               fprintf(stderr, MSG_SGE_XISNOTAVALIDSIGNALNUMBER_S , optarg);
 
3007
               fprintf(stderr, "\n");
 
3008
               usage();
 
3009
               exit(6);
 
3010
            }
 
3011
            break;
 
3012
         case '1':
 
3013
            use_getonejob = 1;
 
3014
            break;
 
3015
         case 's':
 
3016
            system = 1;
 
3017
            break;
 
3018
         case 'n':
 
3019
            verbose = 0;
 
3020
            break;
 
3021
         case 'p':
 
3022
            showproc = 1;
 
3023
            break;
 
3024
         case 'S':
 
3025
            if (sscanf(optarg, "%d", &sysi)!=1) {
 
3026
               fprintf(stderr, MSG_SGE_XISNOTAVALIDINTERVAL_S, optarg);
 
3027
               fprintf(stderr, MSG_SGE_XISNOTAVALIDSIGNALNUMBER_S , optarg);
 
3028
               usage();
 
3029
               exit(4);
 
3030
            }
 
3031
            break;
 
3032
         case 'P':
 
3033
            if (sscanf(optarg, "%d", &prci)!=1) {
 
3034
               fprintf(stderr, MSG_SGE_XISNOTAVALIDINTERVAL_S, optarg);
 
3035
               usage();
 
3036
               exit(5);
 
3037
            }
 
3038
            break;
 
3039
         case 'J':
 
3040
            if (sscanf(optarg, "%d", &jobi)!=1) {
 
3041
               fprintf(stderr, MSG_SGE_XISNOTAVALIDINTERVAL_S, optarg);
 
3042
               usage();
 
3043
               exit(6);
 
3044
            }
 
3045
            break;
 
3046
         case 'i':
 
3047
            if (sscanf(optarg, "%d", &interval)!=1) {
 
3048
               fprintf(stderr, MSG_SGE_XISNOTAVALIDINTERVAL_S, optarg);
 
3049
               fprintf(stderr, "\n");
 
3050
               usage();
 
3051
               exit(3);
 
3052
            }
 
3053
            break;
 
3054
         case '?':
 
3055
         default:
 
3056
            usage();
 
3057
            exit(2);
 
3058
      }
 
3059
 
 
3060
   for (arg=optind; arg<argc; arg++) {
 
3061
      if (sscanf(argv[arg], OSJOBID_FMT, &osjobid) != 1) {
 
3062
              fprintf(stderr, MSG_SGE_XISNOTAVALIDJOBID_S , argv[arg]);
 
3063
         fprintf(stderr, "\n");
 
3064
              exit(2);
 
3065
      }
 
3066
      psWatchJob(osjobid);
 
3067
      numjobs++;
 
3068
   }
 
3069
 
 
3070
   psSetCollectionIntervals(jobi, prci, sysi);
 
3071
 
 
3072
   if (sgeview) {
 
3073
      int i;
 
3074
      int base_interval = 2; /* in tenths of a second */
 
3075
      int sample_rate = 1;
 
3076
      int num_samples = 1000;
 
3077
      int use_winsize = 0;
 
3078
 
 
3079
      curr_cpu = (double *)malloc(numjobs * sizeof(double));
 
3080
      memset(curr_cpu, 0, numjobs*sizeof(double));
 
3081
      prev_cpu = (double *)malloc(numjobs * sizeof(double));
 
3082
      memset(prev_cpu, 0, numjobs*sizeof(double));
 
3083
      diff_cpu = (double *)malloc(numjobs * sizeof(double));
 
3084
      memset(diff_cpu, 0, numjobs*sizeof(double));
 
3085
 
 
3086
      printf("%s\n", MSG_SGE_GROSVIEWEXPORTFILE );
 
3087
      printf("=14 3\n");  /* arbsize */
 
3088
      printf("=14 2 1\n");
 
3089
      if (use_winsize)
 
3090
         printf("=14 6 800 100\n"); /* winsize(x,y) */
 
3091
      printf("=14 9 %d\n", base_interval);
 
3092
      printf("=14 7 46\n");
 
3093
      printf("=14 8 0\n");
 
3094
      printf("=11 0  0x20000 0x4 0x%x 0x%x 0.000 1.000 0x%x 0 0 0 0 0 0x%x "
 
3095
             "0 0 0x2e 0 0 0x1 0x7 0x4 0x%x 0x%x 0 0 0 0x4 0x1 0x6 "
 
3096
             "0x%x 0x5 0x2e\n", sample_rate, sample_rate, numjobs+1,
 
3097
             num_samples, sample_rate, sample_rate, numjobs+1);
 
3098
      printf("h%s \n", sgeview_bar_title);
 
3099
      for (i=0; i<numjobs; i++)
 
3100
         if (jobid_count > i)
 
3101
            printf("ljob %s \n", jobids[i]);
 
3102
         else
 
3103
            printf("ljob %d \n", i+1);
 
3104
      printf("l \n");
 
3105
      printf("=8\n");
 
3106
      printf("%s\n", sgeview_window_title);
 
3107
      fflush(stdout);
 
3108
 
 
3109
   }
 
3110
 
 
3111
   while(1) {
 
3112
      psJob_t *jobs, *ojob;
 
3113
      psProc_t *procs;
 
3114
      psStat_t *stat = NULL;
 
3115
      psSys_t *sys = NULL;
 
3116
      int jobcount, proccount, i, j, activeprocs;
 
3117
 
 
3118
      activeprocs = 0;
 
3119
      jobcount = 0;
 
3120
      ojob = NULL;
 
3121
      stat = NULL;
 
3122
      sys = NULL;
 
3123
 
 
3124
      if (!sgeview && system) {
 
3125
 
 
3126
         if ((stat = psStatus()))
 
3127
            if (verbose)
 
3128
               print_status(stat);
 
3129
#if 0
 
3130
         if ((sys = psGetSysdata()))
 
3131
            if (verbose)
 
3132
               print_system_data(sys);
 
3133
#endif      
 
3134
      }
 
3135
 
 
3136
      ojob = jobs = psGetAllJobs();
 
3137
      if (jobs) {
 
3138
         jobcount = *(uint64 *)jobs;
 
3139
         INCJOBPTR(jobs, sizeof(uint64));
 
3140
         for (i=0; i<jobcount; i++) {
 
3141
 
 
3142
            if (sgeview) {
 
3143
               prev_cpu[i] = curr_cpu[i];
 
3144
               curr_cpu[i] = jobs->jd_utime_a + jobs->jd_stime_a +
 
3145
                             jobs->jd_utime_c + jobs->jd_stime_c;
 
3146
            } else if (use_getonejob) {
 
3147
               psJob_t *jp, *ojp;
 
3148
               psProc_t *pp;
 
3149
               if ((ojp = jp = psGetOneJob(jobs->jd_jid))) {
 
3150
                  if (verbose && !killjob)
 
3151
                     print_job_data(jp);
 
3152
                  proccount = jp->jd_proccount;
 
3153
                  INCJOBPTR(jp, jp->jd_length);
 
3154
                  pp = (psProc_t *)jp;
 
3155
                  for (j=0; j<proccount; j++) {
 
3156
                     if (verbose && showproc)
 
3157
                        print_process_data(pp);
 
3158
                     INCPROCPTR(pp, pp->pd_length);
 
3159
                  }
 
3160
                  free(ojp);
 
3161
               } 
 
3162
 
 
3163
            } else if (verbose && !killjob)
 
3164
               print_job_data(jobs);
 
3165
 
 
3166
            proccount = jobs->jd_proccount;
 
3167
            activeprocs += proccount;
 
3168
            INCJOBPTR(jobs, jobs->jd_length);
 
3169
            procs = (psProc_t *)jobs;
 
3170
 
 
3171
            for (j=0; j<proccount; j++) {
 
3172
               if (killjob) {
 
3173
                  if (getuid() == SGE_SUPERUSER_UID ||
 
3174
                      getuid() == procs->pd_uid) {
 
3175
                     if (kill(procs->pd_pid, signo)<0) {
 
3176
                        char buf[128];
 
3177
                        sprintf(buf, "kill("pid_t_fmt", %d)", procs->pd_pid, signo);
 
3178
                        perror(buf);
 
3179
                     } else if (verbose)
 
3180
                        printf("kill("pid_t_fmt", %d) issued\n", procs->pd_pid, signo);
 
3181
                  } else {
 
3182
                     fprintf(stderr, "kill: "pid_t_fmt ": %s\n",
 
3183
                             procs->pd_pid, MSG_SGE_PERMISSIONDENIED);
 
3184
                  }
 
3185
               }
 
3186
               if (verbose && showproc && !use_getonejob)
 
3187
                  print_process_data(procs);
 
3188
               INCPROCPTR(procs, procs->pd_length);
 
3189
            }
 
3190
 
 
3191
            jobs = (psJob_t *)procs;
 
3192
         }
 
3193
 
 
3194
      } else if (verbose)
 
3195
         printf("%s\n", MSG_SGE_NOJOBS );
 
3196
 
 
3197
      if (sgeview && jobcount>0) {
 
3198
         int i;
 
3199
         double cpu_pct, total_cpu = 0, total_cpu_pct = 0;
 
3200
 
 
3201
         for(i=0; i<jobcount; i++) {
 
3202
            diff_cpu[i] = curr_cpu[i] - prev_cpu[i];
 
3203
            total_cpu += diff_cpu[i];
 
3204
         }
 
3205
 
 
3206
         printf("=3 0 ");
 
3207
         for(i=0; i<jobcount; i++) {
 
3208
            cpu_pct = 0;
 
3209
            if (total_cpu > 0)
 
3210
               cpu_pct = diff_cpu[i] / total_cpu;
 
3211
            total_cpu_pct += cpu_pct;
 
3212
            printf("%8.5f ", cpu_pct);
 
3213
         }
 
3214
         printf("%8.5f ", 1.0 - total_cpu_pct);
 
3215
         printf("\n=15\n");
 
3216
         fflush(stdout);
 
3217
      }
 
3218
 
 
3219
      if (ojob) free(ojob);
 
3220
      if (stat) free(stat);
 
3221
      if (sys) free(sys);
 
3222
 
 
3223
      if (killjob && (!forcekill || activeprocs == 0))
 
3224
         break;
 
3225
 
 
3226
      sleep(interval);
 
3227
   }
 
3228
   return 0;
 
3229
}
 
3230
 
 
3231
#endif
 
3232
 
 
3233
#endif /* !defined(COMPILE_DC) */