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

« back to all changes in this revision

Viewing changes to source/libs/sched/sge_support.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
#include <stdio.h>
 
33
#include <stdlib.h>
 
34
#include <string.h>
 
35
#include <signal.h>
 
36
#include <sys/types.h>
 
37
#include <unistd.h>
 
38
#include <limits.h>
 
39
#include <math.h>
 
40
 
 
41
#ifndef NO_SGE_COMPILE_DEBUG   
 
42
#   define NO_SGE_COMPILE_DEBUG
 
43
#endif
 
44
 
 
45
#include "sge_all_listsL.h"
 
46
#include "commlib.h"
 
47
#include "sgermon.h"
 
48
#include "sge_prog.h"
 
49
#include "sge_time.h"
 
50
#include "sge_orders.h"
 
51
#include "sge_job_schedd.h"
 
52
#include "sgeee.h"
 
53
#include "sge_support.h"
 
54
#include "sge_schedd_conf.h"
 
55
#include "sge_usageL.h"
 
56
#include "sge_userprj.h"
 
57
#include "sgeobj/sge_sharetree.h"
 
58
#include "valid_queue_user.h"
 
59
 
 
60
static const long sge_usage_interval = SGE_USAGE_INTERVAL;
 
61
 
 
62
/*--------------------------------------------------------------------
 
63
 * decay_usage - decay usage for the passed usage list
 
64
 *--------------------------------------------------------------------*/
 
65
 
 
66
static void
 
67
decay_usage( lList *usage_list,
 
68
             const lList *decay_list,
 
69
             u_long curr_time,
 
70
             u_long usage_time_stamp )
 
71
{
 
72
   lListElem *usage = NULL;
 
73
 
 
74
   if (usage_list) {
 
75
      double decay = 0;
 
76
      double default_decay = 0;
 
77
 
 
78
      if (curr_time > usage_time_stamp) {
 
79
 
 
80
         default_decay = pow(sconf_get_decay_constant(),
 
81
                     (double)(curr_time - usage_time_stamp) /
 
82
                     (double)sge_usage_interval);
 
83
 
 
84
         for_each(usage, usage_list) {
 
85
            lListElem *decay_elem;
 
86
            if (decay_list &&
 
87
                ((decay_elem = lGetElemStr(decay_list, UA_name,
 
88
                      lGetPosString(usage, UA_name_POS))))) {
 
89
 
 
90
               decay = pow(lGetPosDouble(decay_elem, UA_value_POS),
 
91
                     (double)(curr_time - usage_time_stamp) /
 
92
                     (double)sge_usage_interval);
 
93
            } else {
 
94
               decay = default_decay;
 
95
            }
 
96
            lSetPosDouble(usage, UA_value_POS,
 
97
                          lGetPosDouble(usage, UA_value_POS) * decay);
 
98
         }
 
99
      }
 
100
   }
 
101
   return;
 
102
}
 
103
 
 
104
/*--------------------------------------------------------------------
 
105
 * decay_userprj_usage - decay usage for the passed user/project object
 
106
 *--------------------------------------------------------------------*/
 
107
 
 
108
void
 
109
decay_userprj_usage( lListElem *userprj,
 
110
                     bool is_user,
 
111
                     const lList *decay_list,
 
112
                     u_long seqno,
 
113
                     u_long curr_time )
 
114
{
 
115
   u_long usage_time_stamp;
 
116
   int obj_usage_seqno_POS = is_user ? UU_usage_seqno_POS : PR_usage_seqno_POS;
 
117
   int obj_usage_time_stamp_POS = is_user ? UU_usage_time_stamp_POS : PR_usage_time_stamp_POS;
 
118
   int obj_usage_POS = is_user ? UU_usage_POS : PR_usage_POS;
 
119
   int obj_project_POS = is_user ? UU_project_POS : PR_project_POS;
 
120
 
 
121
   if (userprj && seqno != lGetPosUlong(userprj, obj_usage_seqno_POS)) {
 
122
 
 
123
   /*-------------------------------------------------------------
 
124
    * Note: In order to decay usage once per decay interval, we
 
125
    * keep a time stamp in the user/project of when it was last
 
126
    * decayed and then apply the approriate decay based on the time
 
127
    * stamp. This allows the usage to be decayed on the scheduling
 
128
    * interval, even though the decay interval is different than
 
129
    * the scheduling interval.
 
130
    *-------------------------------------------------------------*/
 
131
 
 
132
      usage_time_stamp = lGetPosUlong(userprj, obj_usage_time_stamp_POS);
 
133
 
 
134
      if (usage_time_stamp > 0) {
 
135
         lListElem *upp;
 
136
 
 
137
         decay_usage(lGetPosList(userprj, obj_usage_POS), decay_list,
 
138
                     curr_time, usage_time_stamp);
 
139
 
 
140
         for_each(upp, lGetPosList(userprj, obj_project_POS)) {
 
141
            decay_usage(lGetPosList(upp, UPP_usage_POS), decay_list,
 
142
                        curr_time, usage_time_stamp);
 
143
         }
 
144
 
 
145
      }
 
146
 
 
147
      lSetPosUlong(userprj, obj_usage_time_stamp_POS, curr_time);
 
148
      if (seqno != (u_long) -1) {
 
149
        lSetPosUlong(userprj, obj_usage_seqno_POS, seqno);
 
150
      }
 
151
 
 
152
   }
 
153
 
 
154
   return;
 
155
}
 
156
 
 
157
 
 
158
/*--------------------------------------------------------------------
 
159
 * calculate_decay_constant - calculates decay rate and constant based
 
160
 * on the decay half life and usage interval. The halftime argument
 
161
 * is in minutes.
 
162
 *--------------------------------------------------------------------*/
 
163
 
 
164
void
 
165
calculate_decay_constant( double halftime,
 
166
                          double *decay_rate,
 
167
                          double *decay_constant )
 
168
{
 
169
   if (halftime < 0) {
 
170
      *decay_rate = 1.0;
 
171
      *decay_constant = 0;
 
172
   } else if (halftime == 0) {
 
173
      *decay_rate = 0;
 
174
      *decay_constant = 1.0;
 
175
   } else {
 
176
      *decay_rate = - log(0.5) / (halftime * 60);
 
177
      *decay_constant = 1 - (*decay_rate * sge_usage_interval);
 
178
   }
 
179
   return;
 
180
}
 
181
 
 
182
 
 
183
/*--------------------------------------------------------------------
 
184
 * calculate_default_decay_constant - calculates the default decay
 
185
 * rate and constant based on the decay half life and usage interval.
 
186
 * The halftime argument is in hours.
 
187
 *--------------------------------------------------------------------*/
 
188
 
 
189
void
 
190
calculate_default_decay_constant( int halftime )
 
191
{
 
192
   double sge_decay_rate = 0.0;
 
193
   double sge_decay_constant = 0.0;
 
194
   
 
195
   calculate_decay_constant(halftime*60.0, &sge_decay_rate, &sge_decay_constant); 
 
196
   
 
197
   sconf_set_decay_constant(sge_decay_constant);
 
198
}
 
199
 
 
200
 
 
201
/*--------------------------------------------------------------------
 
202
 * sge_for_each_node - visit each node and call the supplied function
 
203
 * until a non-zero return code is returned.
 
204
 *--------------------------------------------------------------------*/
 
205
 
 
206
int
 
207
sge_for_each_share_tree_node( lListElem *node,
 
208
                              sge_node_func_t func,
 
209
                              void *ptr )
 
210
{
 
211
   int retcode=0;
 
212
   lList *children = NULL;
 
213
   lListElem *child_node = NULL;
 
214
 
 
215
   if (node == NULL) {
 
216
      return 0;
 
217
   }
 
218
 
 
219
   if ((retcode = (*func)(node, ptr))) {
 
220
      return retcode;
 
221
   }
 
222
 
 
223
   if ((children = lGetPosList(node, STN_children_POS))) {
 
224
      for_each(child_node, children) {
 
225
         if ((retcode = sge_for_each_share_tree_node(child_node, func, ptr))) {
 
226
            break;
 
227
         }   
 
228
      }
 
229
   }
 
230
 
 
231
   return retcode;
 
232
}
 
233
 
 
234
 
 
235
/*--------------------------------------------------------------------
 
236
 * zero_node_fields - zero out the share tree node fields that are 
 
237
 * passed to the qmaster from schedd and are displayed at qmon
 
238
 *--------------------------------------------------------------------*/
 
239
 
 
240
int
 
241
sge_zero_node_fields( lListElem *node,
 
242
                      void *ptr )
 
243
{
 
244
   lSetPosDouble(node, STN_m_share_POS, 0);
 
245
   lSetPosDouble(node, STN_adjusted_current_proportion_POS, 0);
 
246
   lSetPosUlong(node, STN_job_ref_count_POS, 0);
 
247
 
 
248
   return 0;
 
249
}
 
250
 
 
251
 
 
252
/*--------------------------------------------------------------------
 
253
 * sge_init_node_fields - zero out the share tree node fields that are 
 
254
 * passed to the qmaster from schedd and are displayed at qmon
 
255
 *--------------------------------------------------------------------*/
 
256
 
 
257
int
 
258
sge_init_node_fields( lListElem *root )
 
259
{
 
260
   return sge_for_each_share_tree_node(root, sge_zero_node_fields, NULL);
 
261
}
 
262
 
 
263
 
 
264
/*--------------------------------------------------------------------
 
265
 * sge_calc_node_usage - calculate usage for this share tree node
 
266
 * and all descendant nodes.
 
267
 *--------------------------------------------------------------------*/
 
268
 
 
269
double
 
270
sge_calc_node_usage( lListElem *node,
 
271
                     const lList *user_list,
 
272
                     const lList *project_list,
 
273
                     const lList *decay_list,
 
274
                     u_long curr_time,
 
275
                     const char *projname,
 
276
                     u_long seqno )
 
277
{
 
278
   double usage_value = 0;
 
279
   int project_node = 0;
 
280
   lListElem *child_node;
 
281
   lList *children;
 
282
   lListElem *userprj = NULL;
 
283
   lList *usage_list=NULL;
 
284
   lListElem *usage_weight, *usage_elem;
 
285
   double sum_of_usage_weights = 0;
 
286
   const char *usage_name;
 
287
   bool is_user = false;
 
288
 
 
289
   DENTER(TOP_LAYER, "sge_calc_node_usage");
 
290
 
 
291
   children = lGetPosList(node, STN_children_POS);
 
292
   if (!children) {
 
293
      
 
294
 
 
295
      if (projname) {
 
296
 
 
297
         /*-------------------------------------------------------------
 
298
          * Get usage from project usage sub-list in user object
 
299
          *-------------------------------------------------------------*/
 
300
 
 
301
 
 
302
         if ((userprj = user_list_locate(user_list, 
 
303
                                      lGetPosString(node, STN_name_POS)))) {
 
304
            lList *projects = lGetList(userprj, UU_project);
 
305
            lListElem *upp;
 
306
 
 
307
            is_user = true;
 
308
            if (projects) {
 
309
               if ((upp=lGetElemStr(projects, UPP_name, projname))) {
 
310
                  usage_list = lGetList(upp, UPP_usage);
 
311
               }
 
312
            }   
 
313
         }
 
314
 
 
315
      } else {
 
316
 
 
317
         /*-------------------------------------------------------------
 
318
          * Get usage directly from corresponding user or project object
 
319
          *-------------------------------------------------------------*/
 
320
 
 
321
         if ((userprj = user_list_locate(user_list, 
 
322
                                            lGetPosString(node, STN_name_POS)))) {
 
323
 
 
324
            is_user = true;
 
325
            usage_list = lGetList(userprj, UU_usage);
 
326
 
 
327
         } else if ((userprj = prj_list_locate(project_list, 
 
328
                                                   lGetPosString(node, STN_name_POS)))) {
 
329
 
 
330
            is_user = false;
 
331
            usage_list = lGetList(userprj, PR_usage);
 
332
 
 
333
         }
 
334
      }
 
335
   } else {
 
336
 
 
337
      /*-------------------------------------------------------------
 
338
       * If this is a project node, then return the project usage
 
339
       * rather than the children's usage
 
340
       *-------------------------------------------------------------*/
 
341
      if (!projname) {
 
342
         if ((userprj = prj_list_locate(project_list, 
 
343
                                            lGetPosString(node, STN_name_POS)))) {
 
344
            project_node = 1;
 
345
            is_user = false;
 
346
            usage_list = lGetList(userprj, PR_usage);
 
347
            projname = lGetString(userprj, PR_name);
 
348
         }
 
349
      }
 
350
 
 
351
   }
 
352
 
 
353
   if (usage_list) {
 
354
      lList *usage_weight_list = NULL;
 
355
 
 
356
      /*-------------------------------------------------------------
 
357
       * Decay usage
 
358
       *-------------------------------------------------------------*/
 
359
 
 
360
      if (curr_time && userprj) {
 
361
         decay_userprj_usage(userprj, is_user, decay_list, seqno, curr_time);
 
362
      }  
 
363
 
 
364
      /*-------------------------------------------------------------
 
365
       * Sum usage weighting factors
 
366
       *-------------------------------------------------------------*/
 
367
 
 
368
      if (sconf_is()) {
 
369
         usage_weight_list = sconf_get_usage_weight_list();
 
370
         if (usage_weight_list) {
 
371
            for_each(usage_weight, usage_weight_list)
 
372
               sum_of_usage_weights +=
 
373
                     lGetPosDouble(usage_weight, UA_value_POS);
 
374
         }
 
375
      }
 
376
 
 
377
      /*-------------------------------------------------------------
 
378
       * Combine user/project usage based on usage weighting factors
 
379
       *-------------------------------------------------------------*/
 
380
 
 
381
      if (usage_weight_list) {
 
382
         for_each(usage_elem, usage_list) {
 
383
            usage_name = lGetPosString(usage_elem, UA_name_POS);
 
384
            usage_weight = lGetElemStr(usage_weight_list, UA_name,
 
385
                                       usage_name);
 
386
            if (usage_weight && sum_of_usage_weights>0) {
 
387
               usage_value += lGetPosDouble(usage_elem, UA_value_POS) *
 
388
                  (lGetPosDouble(usage_weight, UA_value_POS) /
 
389
                   sum_of_usage_weights);
 
390
            }
 
391
         }
 
392
      }
 
393
 
 
394
      lFreeList(&usage_weight_list);
 
395
 
 
396
      /*-------------------------------------------------------------
 
397
       * Store other usage values in node usage list
 
398
       *-------------------------------------------------------------*/
 
399
 
 
400
      for_each(usage_elem, usage_list) {
 
401
         const char *nm = lGetPosString(usage_elem, UA_name_POS);
 
402
         lListElem *u;
 
403
         if (strcmp(nm, USAGE_ATTR_CPU) != 0 &&
 
404
             strcmp(nm, USAGE_ATTR_MEM) != 0 &&
 
405
             strcmp(nm, USAGE_ATTR_IO) != 0) {
 
406
            if (((u=lGetElemStr(lGetPosList(node, STN_usage_list_POS),
 
407
                                UA_name, nm))) ||
 
408
                ((u = lAddSubStr(node, UA_name, nm, STN_usage_list, UA_Type))))
 
409
               lSetPosDouble(u, UA_value_POS,
 
410
                             lGetPosDouble(u, UA_value_POS) +
 
411
                             lGetPosDouble(usage_elem, UA_value_POS));
 
412
         }
 
413
      }
 
414
   }
 
415
 
 
416
   if (children) {
 
417
      double child_usage = 0;
 
418
 
 
419
      /*-------------------------------------------------------------
 
420
       * Sum child usage
 
421
       *-------------------------------------------------------------*/
 
422
 
 
423
      for_each(child_node, children) {
 
424
         lListElem *nu;
 
425
         child_usage += sge_calc_node_usage(child_node, user_list,
 
426
                                            project_list, decay_list, curr_time,
 
427
                                            projname, seqno);
 
428
 
 
429
         /*-------------------------------------------------------------
 
430
          * Sum other usage values
 
431
          *-------------------------------------------------------------*/
 
432
 
 
433
         if (!project_node)
 
434
            for_each(nu, lGetPosList(child_node, STN_usage_list_POS)) {
 
435
               const char *nm = lGetPosString(nu, UA_name_POS);
 
436
               lListElem *u;
 
437
               if (((u=lGetElemStr(lGetPosList(node, STN_usage_list_POS),
 
438
                                   UA_name, nm))) ||
 
439
                   ((u=lAddSubStr(node, UA_name, nm, STN_usage_list, UA_Type))))
 
440
                  lSetPosDouble(u, UA_value_POS,
 
441
                                lGetPosDouble(u, UA_value_POS) +
 
442
                                lGetPosDouble(nu, UA_value_POS));
 
443
            }
 
444
      }
 
445
 
 
446
      if (!project_node)
 
447
 
 
448
         /* if this is not a project node, we include the child usage */
 
449
 
 
450
         usage_value += child_usage;
 
451
 
 
452
      else {
 
453
 
 
454
         /* If this is a project node, then we calculate the usage
 
455
            being used by all users which map to the "default" user node
 
456
            by subtracting the sum of all the child usage from the
 
457
            project usage. Then, we add this usage to all of the nodes
 
458
            leading to the "default" user node. */
 
459
 
 
460
         ancestors_t ancestors;
 
461
         int i;
 
462
         if (search_ancestors(node, "default", &ancestors, 1)) {
 
463
            double default_usage = usage_value - child_usage;
 
464
            if (default_usage > 1.0) {
 
465
               for(i=1; i<ancestors.depth; i++) {
 
466
                  double u = lGetPosDouble(ancestors.nodes[i], STN_combined_usage_POS);
 
467
                  lSetPosDouble(ancestors.nodes[i], STN_combined_usage_POS, u + default_usage);
 
468
               }
 
469
            }
 
470
            free_ancestors(&ancestors);
 
471
         }
 
472
      }
 
473
 
 
474
#ifdef notdef
 
475
      else {
 
476
         lListElem *default_node;
 
477
         if ((default_node=search_named_node(node, "default")))
 
478
            lSetPosDouble(default_node, STN_combined_usage_POS,
 
479
               MAX(usage_value - child_usage, 0));
 
480
      }
 
481
#endif
 
482
 
 
483
   }
 
484
 
 
485
   /*-------------------------------------------------------------
 
486
    * Set combined usage in the node
 
487
    *-------------------------------------------------------------*/
 
488
 
 
489
   lSetPosDouble(node, STN_combined_usage_POS, usage_value);
 
490
 
 
491
   DEXIT;
 
492
   return usage_value;
 
493
}
 
494
 
 
495
 
 
496
/*--------------------------------------------------------------------
 
497
 * sge_calc_node_proportions - calculate share tree node proportions
 
498
 * for this node and all descendant nodes.
 
499
 *--------------------------------------------------------------------*/
 
500
 
 
501
void
 
502
sge_calc_node_proportion( lListElem *node,
 
503
                          double total_usage )
 
504
{
 
505
   lList *children = NULL;
 
506
   lListElem *child_node = NULL;
 
507
 
 
508
   /*-------------------------------------------------------------
 
509
    * Calculate node proportions for all children
 
510
    *-------------------------------------------------------------*/
 
511
 
 
512
   if ((children = lGetPosList(node, STN_children_POS))) {
 
513
      for_each(child_node, children) {
 
514
         sge_calc_node_proportion(child_node, total_usage);
 
515
      }
 
516
   }  
 
517
 
 
518
   /*-------------------------------------------------------------
 
519
    * Set proportion in the node
 
520
    *-------------------------------------------------------------*/
 
521
 
 
522
   if (total_usage == 0) {
 
523
      lSetPosDouble(node, STN_actual_proportion_POS, 0);
 
524
   }   
 
525
   else {
 
526
      lSetPosDouble(node, STN_actual_proportion_POS,
 
527
                    lGetPosDouble(node, STN_combined_usage_POS) / total_usage);
 
528
   }      
 
529
 
 
530
   return;
 
531
}
 
532
 
 
533
 
 
534
/*--------------------------------------------------------------------
 
535
 * sge_calc_share_tree_proportions - calculate share tree node
 
536
 * usage and proportions.
 
537
 *
 
538
 * Sets STN_combined_usage and STN_actual_proportion in each share
 
539
 * tree node contained in the passed-in share_tree argument.
 
540
 *--------------------------------------------------------------------*/
 
541
 
 
542
void
 
543
_sge_calc_share_tree_proportions( lList *share_tree,
 
544
                                  const lList *user_list,
 
545
                                  const lList *project_list,
 
546
                                  const lList *decay_list,
 
547
                                  u_long curr_time )
 
548
{
 
549
   lListElem *root;
 
550
   double total_usage;
 
551
 
 
552
   DENTER(TOP_LAYER, "sge_calc_share_tree_proportions");
 
553
 
 
554
   if (!share_tree || !((root=lFirst(share_tree)))) {
 
555
      DEXIT;
 
556
      return;
 
557
   }
 
558
 
 
559
   calculate_default_decay_constant( sconf_get_halftime());
 
560
 
 
561
   total_usage = sge_calc_node_usage(root,
 
562
                                     user_list,
 
563
                                     project_list,
 
564
                                     decay_list,
 
565
                                     curr_time,
 
566
                                                       NULL,
 
567
                                     -1);
 
568
 
 
569
   sge_calc_node_proportion(root, total_usage);
 
570
 
 
571
   DEXIT;
 
572
   return;
 
573
}
 
574
 
 
575
 
 
576
void
 
577
sge_calc_share_tree_proportions( lList *share_tree,
 
578
                                 const lList *user_list,
 
579
                                 const lList *project_list,
 
580
                                 const lList *decay_list )
 
581
{
 
582
   _sge_calc_share_tree_proportions(share_tree, user_list, project_list,
 
583
                                    decay_list, sge_get_gmt());
 
584
   return;
 
585
}
 
586
 
 
587
 
 
588
/*--------------------------------------------------------------------
 
589
 * set_share_tree_project_flags - set the share tree project flag for
 
590
 *       node and descendants
 
591
 *--------------------------------------------------------------------*/
 
592
 
 
593
void
 
594
set_share_tree_project_flags( const lList *project_list,
 
595
                              lListElem *node )
 
596
{
 
597
   lList *children;
 
598
   lListElem *child;
 
599
 
 
600
   if (!project_list || !node)
 
601
      return;
 
602
 
 
603
   if (prj_list_locate(project_list, lGetString(node, STN_name)))
 
604
      lSetUlong(node, STN_project, 1);
 
605
   else
 
606
      lSetUlong(node, STN_project, 0);
 
607
 
 
608
   children = lGetList(node, STN_children);
 
609
   if (children) {
 
610
      for_each(child, children) {
 
611
         set_share_tree_project_flags(project_list, child);
 
612
      }
 
613
   }
 
614
   return;
 
615
}
 
616
 
 
617
 
 
618
void
 
619
sge_add_default_user_nodes( lListElem *root_node,
 
620
                            const lList *user_list,
 
621
                            const lList *project_list,
 
622
                            const lList *userset_list)
 
623
{
 
624
   lListElem *user, *project, *pnode, *dnode;
 
625
   const char *proj_name, *user_name;
 
626
 
 
627
   /*
 
628
    * do for each project and for no project
 
629
    *    if default node exists
 
630
    *       do for each user
 
631
    *          if user maps to default node
 
632
    *             add temp node as sibling to default node
 
633
    *          endif
 
634
    *       end do
 
635
    *    endif
 
636
    * end do
 
637
    */
 
638
 
 
639
   set_share_tree_project_flags(project_list, root_node);
 
640
 
 
641
   for_each(project, project_list) {
 
642
      /*
 
643
      ** check acl and xacl of project for the temp users
 
644
      ** only users that are allowed for the project are shown
 
645
      */
 
646
      lList *xacl = lGetList(project, PR_xacl);
 
647
      lList *acl = lGetList(project, PR_acl);
 
648
 
 
649
      proj_name = lGetString(project, PR_name);
 
650
 
 
651
      if (search_userprj_node(root_node, "default", proj_name, NULL)) {
 
652
         for_each(user, user_list) {
 
653
            int has_access = 1;
 
654
            
 
655
            user_name = lGetString(user, UU_name);
 
656
 
 
657
            /*
 
658
            ** check if user would be allowed
 
659
            */
 
660
            has_access = sge_has_access_(user_name, NULL, acl, xacl, userset_list);
 
661
 
 
662
            if (has_access && 
 
663
                ((dnode=search_userprj_node(root_node, user_name, 
 
664
                                            proj_name, &pnode))) &&
 
665
                !strcmp("default", lGetString(dnode, STN_name))) {
 
666
 
 
667
               lListElem *node = lCopyElem(dnode);
 
668
               lSetString(node, STN_name, user_name);
 
669
               lSetList(node, STN_children, NULL);
 
670
               lSetUlong(node, STN_temp, 1);
 
671
               if (lGetList(dnode,STN_children) == NULL) {
 
672
                  lList *children = lCreateList("display", STN_Type);
 
673
                  lSetList(dnode, STN_children, children);
 
674
               }   
 
675
               lAppendElem(lGetList(dnode,STN_children), node);
 
676
            }
 
677
         }
 
678
      }
 
679
   }
 
680
 
 
681
   proj_name = NULL;
 
682
   if (search_userprj_node(root_node, "default", proj_name, NULL)) {
 
683
      for_each(user, user_list) {
 
684
         user_name = lGetString(user, UU_name);
 
685
         if (((dnode=search_userprj_node(root_node, user_name, proj_name, &pnode))) &&
 
686
             strcmp("default", lGetString(dnode, STN_name)) == 0) {
 
687
            lListElem *node = lCopyElem(dnode);
 
688
            lSetString(node, STN_name, user_name);
 
689
            lSetList(node, STN_children, NULL);
 
690
            lSetUlong(node, STN_temp, 1);
 
691
            if (lGetList(dnode,STN_children) == NULL) {
 
692
               lList *children = lCreateList("display", STN_Type);
 
693
               lSetList(dnode, STN_children, children);
 
694
            }   
 
695
            lAppendElem(lGetList(dnode,STN_children), node);
 
696
         }
 
697
      }
 
698
   }
 
699
 
 
700
}
 
701
 
 
702
 
 
703
/********************************************************
 
704
 Search the share tree for the node corresponding to the
 
705
 user / project combination
 
706
 ********************************************************/
 
707
static lListElem *
 
708
search_userprj_node_work( lListElem *ep,      /* branch to search */
 
709
                          const char *username,
 
710
                          const char *projname,
 
711
                          lListElem **pep,    /* parent of found node */
 
712
                          lListElem *root )
 
713
 
 
714
{
 
715
   lListElem *cep, *fep;
 
716
   const char *nodename;
 
717
   lList *children;
 
718
 
 
719
   if (ep == NULL || (username == NULL && projname == NULL)) {
 
720
      return NULL;
 
721
   }
 
722
 
 
723
   nodename = lGetPosString(ep, STN_name_POS);
 
724
 
 
725
   /*
 
726
    * skip project nodes which don't match
 
727
    */
 
728
 
 
729
   if (lGetPosUlong(ep, STN_project_POS) &&
 
730
        ep != root &&
 
731
       (!projname || strcmp(nodename, projname))) {
 
732
      return NULL;
 
733
   }
 
734
 
 
735
   children = lGetPosList(ep, STN_children_POS);
 
736
 
 
737
   /*
 
738
    * if project name is supplied, look for the project
 
739
    */
 
740
 
 
741
   if (projname != NULL) {
 
742
 
 
743
      if (strcmp(nodename, projname) == 0) {
 
744
 
 
745
         /*
 
746
          * We have found the project node, now find the user node
 
747
          * within the project sub-tree. If there are no children,
 
748
          * return the project node.
 
749
          */
 
750
 
 
751
         if (children == NULL) {
 
752
            return ep;
 
753
         }
 
754
 
 
755
         return search_userprj_node_work(ep, username, NULL, pep, ep);
 
756
      } 
 
757
      else {
 
758
          /* search the child nodes for the project */
 
759
         for_each(cep, children) {
 
760
            if ((fep = search_userprj_node_work(cep, username, projname, pep, root))) {
 
761
               if (pep && (cep == fep)) {
 
762
                  *pep = ep;
 
763
               }   
 
764
               return fep;
 
765
            }
 
766
         }
 
767
         /* project was not found, fall thru and return NULL */
 
768
      }
 
769
   } 
 
770
   else {
 
771
 
 
772
      if (strcmp(nodename, username) == 0) {
 
773
         return ep;
 
774
      }
 
775
 
 
776
      /*
 
777
       * no project name supplied, so search for child node
 
778
       */
 
779
 
 
780
      for_each(cep, children) {
 
781
         if ((fep = search_userprj_node_work(cep, username, projname, pep, root))) {
 
782
            if (pep && (cep == fep)) {
 
783
               *pep = ep;
 
784
            }   
 
785
            return fep;
 
786
         }
 
787
      }
 
788
 
 
789
      /*
 
790
       * if we've searched the entire tree, search for default user
 
791
       */
 
792
 
 
793
      if (ep == root && strcmp(username, "default")) {
 
794
         return search_userprj_node(ep, "default", NULL, pep);
 
795
       }   
 
796
 
 
797
      /*
 
798
       * user was not found, fall thru and return NULL
 
799
       */
 
800
 
 
801
   }
 
802
 
 
803
   return NULL;
 
804
}
 
805
 
 
806
 
 
807
/********************************************************
 
808
 Search the share tree for the node corresponding to the
 
809
 user / project combination
 
810
 ********************************************************/
 
811
lListElem *
 
812
search_userprj_node( lListElem *ep,      /* root of the tree */
 
813
                     const char *username,
 
814
                     const char *projname,
 
815
                     lListElem **pep )   /* parent of found node */
 
816
{
 
817
   return search_userprj_node_work(ep, username, projname, pep, ep);
 
818
}
 
819
 
 
820
 
 
821
/*--------------------------------------------------------------------
 
822
 * sgeee_sort_jobs - sort jobs according the task-priority and job number 
 
823
 *--------------------------------------------------------------------*/
 
824
 
 
825
void sgeee_sort_jobs( lList **job_list )              /* JB_Type */
 
826
{
 
827
  sgeee_sort_jobs_by(job_list, SGEJ_priority, SGEJ_sort_decending , SGEJ_sort_ascending); /* decreasing priority then increasing job number */
 
828
}
 
829
 
 
830
void sgeee_sort_jobs_by( lList **job_list , int by_SGEJ_field, int field_sort_direction, int jobnum_sort_direction) /* JB_Type */
 
831
{
 
832
 
 
833
   lListElem *job = NULL, *nxt_job = NULL;     
 
834
   lList *tmp_list = NULL;    /* SGEJ_Type */
 
835
   char *sortorder = NULL;
 
836
 
 
837
   DENTER(TOP_LAYER, "sgeee_sort_jobs");
 
838
 
 
839
   if (!job_list || !*job_list) {
 
840
      DEXIT;
 
841
      return;
 
842
   }
 
843
 
 
844
#if 0
 
845
   DPRINTF(("+ + + + + + + + + + + + + + + + \n"));
 
846
   DPRINTF(("     SORTING SGEEE JOB LIST     \n"));
 
847
   DPRINTF(("+ + + + + + + + + + + + + + + + \n"));
 
848
#endif
 
849
 
 
850
   /*-----------------------------------------------------------------
 
851
    * Create tmp list 
 
852
    *-----------------------------------------------------------------*/
 
853
   tmp_list = lCreateList("tmp list", SGEJ_Type);
 
854
 
 
855
   nxt_job = lFirst(*job_list); 
 
856
   while((job=nxt_job)) {
 
857
      lListElem *tmp_sge_job = NULL;   /* SGEJ_Type */
 
858
      
 
859
      nxt_job = lNext(nxt_job);
 
860
      tmp_sge_job = lCreateElem(SGEJ_Type);
 
861
 
 
862
      {
 
863
         lListElem *tmp_task; /* JAT_Type */
 
864
 
 
865
         /* 
 
866
          * First try to find an enrolled task 
 
867
          * It will have the highest priority
 
868
          */
 
869
         tmp_task = lFirst(lGetList(job, JB_ja_tasks));
 
870
 
 
871
         /* 
 
872
          * If there is no enrolled task than take the template element 
 
873
          */
 
874
         if (tmp_task == NULL) {
 
875
            tmp_task = lFirst(lGetList(job, JB_ja_template));
 
876
         }
 
877
 
 
878
         lSetDouble(tmp_sge_job, SGEJ_priority,
 
879
                    lGetDouble(tmp_task, JAT_prio));
 
880
         if (by_SGEJ_field != SGEJ_priority) { 
 
881
            lSetUlong(tmp_sge_job, SGEJ_state,
 
882
                       lGetUlong(tmp_task, JAT_state));
 
883
            lSetString(tmp_sge_job, SGEJ_master_queue,
 
884
                       lGetString(tmp_task, JAT_master_queue));
 
885
         }           
 
886
      }
 
887
 
 
888
      /*
 
889
      ** JB_job_number    (Ulong)
 
890
      ** JAT_prio         (Double)
 
891
      ** JB_job_name      (String)
 
892
      ** JB_owner         (String)
 
893
      ** JAT_status       (Ulong)
 
894
      ** JAT_master_queue (String)
 
895
      */
 
896
 
 
897
      lSetUlong(tmp_sge_job, SGEJ_job_number, lGetUlong(job, JB_job_number));
 
898
      if (by_SGEJ_field != SGEJ_priority) { 
 
899
         lSetString(tmp_sge_job, SGEJ_job_name, lGetString(job, JB_job_name));
 
900
         lSetString(tmp_sge_job, SGEJ_owner, lGetString(job, JB_owner));
 
901
      }
 
902
      lSetRef(tmp_sge_job, SGEJ_job_reference, job);
 
903
#if 0
 
904
      DPRINTF(("JOB: "sge_u32" PRIORITY: %f NAME: %s OWNER: %s QUEUE: %s STATUS: "sge_u32"\n", 
 
905
         lGetUlong(tmp_sge_job, SGEJ_job_number), 
 
906
         lGetDouble(tmp_sge_job, SGEJ_priority),
 
907
         lGetString(tmp_sge_job, SGEJ_job_name) ? lGetString(tmp_sge_job, SGEJ_job_name) : "",
 
908
         lGetString(tmp_sge_job, SGEJ_owner) ? lGetString(tmp_sge_job, SGEJ_owner) : "",
 
909
         lGetString(tmp_sge_job, SGEJ_master_queue) ? lGetString(tmp_sge_job, SGEJ_master_queue) :"", 
 
910
         lGetUlong(tmp_sge_job, SGEJ_state)));
 
911
#endif
 
912
      lAppendElem(tmp_list, tmp_sge_job);
 
913
      
 
914
      lDechainElem(*job_list, job);
 
915
   }
 
916
 
 
917
   /*-----------------------------------------------------------------
 
918
    * Sort tmp list
 
919
    *-----------------------------------------------------------------*/
 
920
   if ((field_sort_direction) && (jobnum_sort_direction)) {
 
921
      sortorder = "%I+ %I+";
 
922
   } else if (!field_sort_direction) {
 
923
      sortorder = "%I- %I+";
 
924
   } else if (!jobnum_sort_direction) {
 
925
      sortorder = "%I+ %I-";
 
926
   } else {
 
927
      sortorder = "%I- %I-";
 
928
   }
 
929
 
 
930
   lPSortList(tmp_list, sortorder, by_SGEJ_field, SGEJ_job_number);
 
931
 
 
932
   /*-----------------------------------------------------------------
 
933
    * rebuild job_list according sort order
 
934
    *-----------------------------------------------------------------*/
 
935
   for_each(job, tmp_list) {
 
936
      lAppendElem(*job_list, lGetRef(job, SGEJ_job_reference)); 
 
937
   } 
 
938
 
 
939
   /*-----------------------------------------------------------------
 
940
    * Release tmp list
 
941
    *-----------------------------------------------------------------*/
 
942
   lFreeList(&tmp_list);
 
943
 
 
944
   DEXIT;
 
945
   return;
 
946
}
 
947
 
 
948