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

« back to all changes in this revision

Viewing changes to source/daemons/qmaster/sge_cqueue_qmaster.c

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

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*___INFO__MARK_BEGIN__*/
 
2
/*************************************************************************
 
3
 * 
 
4
 *  The Contents of this file are made available subject to the terms of
 
5
 *  the Sun Industry Standards Source License Version 1.2
 
6
 * 
 
7
 *  Sun Microsystems Inc., March, 2001
 
8
 * 
 
9
 * 
 
10
 *  Sun Industry Standards Source License Version 1.2
 
11
 *  =================================================
 
12
 *  The contents of this file are subject to the Sun Industry Standards
 
13
 *  Source License Version 1.2 (the "License"); You may not use this file
 
14
 *  except in compliance with the License. You may obtain a copy of the
 
15
 *  License at http://gridengine.sunsource.net/Gridengine_SISSL_license.html
 
16
 * 
 
17
 *  Software provided under this License is provided on an "AS IS" basis,
 
18
 *  WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
 
19
 *  WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
 
20
 *  MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
 
21
 *  See the License for the specific provisions governing your rights and
 
22
 *  obligations concerning the Software.
 
23
 * 
 
24
 *   The Initial Developer of the Original Code is: Sun Microsystems, Inc.
 
25
 * 
 
26
 *   Copyright: 2001 by Sun Microsystems, Inc.
 
27
 * 
 
28
 *   All Rights Reserved.
 
29
 * 
 
30
 ************************************************************************/
 
31
/*___INFO__MARK_END__*/
 
32
 
 
33
#include <stdio.h>
 
34
#include <stdlib.h>
 
35
#include <ctype.h>
 
36
#include <string.h>
 
37
#include <unistd.h>
 
38
#include <errno.h>
 
39
#include <limits.h>
 
40
#include <pthread.h>
 
41
 
 
42
#include "sge.h"
 
43
#include "sgermon.h"
 
44
#include "sge_time.h"
 
45
#include "sge_conf.h"
 
46
#include "sge_log.h"
 
47
#include "sge_c_gdi.h"
 
48
#include "sge_string.h"
 
49
#include "sge_answer.h"
 
50
#include "sge_utility.h"
 
51
#include "sge_utility_qmaster.h"
 
52
#include "sge_unistd.h"
 
53
#include "sge_hgroup.h"
 
54
#include "sge_cqueue.h"
 
55
#include "sge_job.h"
 
56
#include "sge_ja_task.h"
 
57
#include "sge_qinstance.h"
 
58
#include "sge_qinstance_state.h"
 
59
#include "sge_userset.h"
 
60
#include "sge_host.h"
 
61
#include "sge_href.h"
 
62
#include "sge_str.h"
 
63
#include "sge_event_master.h"
 
64
#include "sge_persistence_qmaster.h"
 
65
#include "sge_attr.h"
 
66
#include "sge_userprj.h"
 
67
#include "sge_feature.h"
 
68
#include "sge_cqueue_qmaster.h"
 
69
#include "sge_qinstance_qmaster.h"
 
70
#include "sge_host_qmaster.h"
 
71
#include "sge_qmod_qmaster.h"
 
72
#include "sched/sge_select_queue.h"
 
73
#include "sched/valid_queue_user.h"
 
74
#include "sge_queue_event_master.h"
 
75
#include "sge_signal.h"
 
76
#include "sge_mtutil.h"
 
77
#include "sgeobj/sge_load.h"
 
78
#include "sgeobj/sge_advance_reservation.h"
 
79
 
 
80
#include "sge_userprj_qmaster.h"
 
81
#include "sge_userset_qmaster.h"
 
82
 
 
83
#include "spool/sge_spooling.h"
 
84
 
 
85
#include "msg_common.h"
 
86
#include "msg_qmaster.h"
 
87
#include "msg_sgeobjlib.h"
 
88
 
 
89
 
 
90
static bool
 
91
cqueue_mod_hostlist(lListElem *cqueue, lList **answer_list,
 
92
                    lListElem *reduced_elem, int sub_command, 
 
93
                    lList **add_hosts, lList **rem_hosts);
 
94
 
 
95
static bool
 
96
cqueue_mod_attributes(lListElem *cqueue, lList **answer_list,
 
97
                      lListElem *reduced_elem, int sub_command);
 
98
 
 
99
static bool
 
100
cqueue_mark_qinstances(lListElem *cqueue, lList **answer_list, 
 
101
                       lList *del_hosts);
 
102
 
 
103
static bool
 
104
cqueue_add_qinstances(sge_gdi_ctx_class_t *ctx, lListElem *cqueue, lList **answer_list, lList *add_hosts, monitoring_t *monitor);
 
105
 
 
106
static lListElem * 
 
107
qinstance_create(sge_gdi_ctx_class_t *ctx,
 
108
                 const lListElem *cqueue, lList **answer_list,
 
109
                 const char *hostname, bool *is_ambiguous, monitoring_t *monitor);
 
110
 
 
111
static void
 
112
cqueue_update_categories(const lListElem *new_cq, const lListElem *old_cq);
 
113
 
 
114
static void
 
115
qinstance_check_unknown_state(lListElem *this_elem, lList *master_exechost_list);
 
116
 
 
117
static lListElem * 
 
118
qinstance_create(sge_gdi_ctx_class_t *ctx,
 
119
                 const lListElem *cqueue, lList **answer_list,
 
120
                 const char *hostname, bool *is_ambiguous, monitoring_t *monitor) 
 
121
{
 
122
   dstring buffer = DSTRING_INIT;
 
123
   const char *cqueue_name = lGetString(cqueue, CQ_name);
 
124
   lList *centry_list = *(object_type_get_master_list(SGE_TYPE_CENTRY));
 
125
   lListElem *ret = NULL;
 
126
   int index;
 
127
 
 
128
   DENTER(TOP_LAYER, "qinstance_create");
 
129
   
 
130
   ret = lCreateElem(QU_Type);
 
131
 
 
132
   /*
 
133
    * Pre-initialize some fields: hostname, full_name
 
134
    */
 
135
   lSetHost(ret, QU_qhostname, hostname);
 
136
   lSetString(ret, QU_qname, cqueue_name);
 
137
   sge_dstring_sprintf(&buffer, "%s@%s", cqueue_name, hostname);
 
138
   lSetString(ret, QU_full_name, sge_dstring_get_string(&buffer));
 
139
   sge_dstring_free(&buffer);
 
140
 
 
141
   /*
 
142
    * Initialize configuration attributes from CQ
 
143
    */
 
144
   *is_ambiguous = false;
 
145
   index = 0;
 
146
   while (cqueue_attribute_array[index].cqueue_attr != NoName) {
 
147
      bool tmp_is_ambiguous = false;
 
148
      bool tmp_has_changed_conf_attr = false;
 
149
      bool tmp_has_changed_state_attr = false;
 
150
      const char *matching_host_or_group = NULL;
 
151
      const char *matching_group = NULL;
 
152
 
 
153
      qinstance_modify_attribute(ctx,
 
154
                       ret, answer_list, cqueue, 
 
155
                       cqueue_attribute_array[index].qinstance_attr,
 
156
                       cqueue_attribute_array[index].cqueue_attr, 
 
157
                       cqueue_attribute_array[index].href_attr,
 
158
                       cqueue_attribute_array[index].value_attr,
 
159
                       cqueue_attribute_array[index].primary_key_attr,
 
160
                       &matching_host_or_group,
 
161
                       &matching_group,
 
162
                       &tmp_is_ambiguous, 
 
163
                       &tmp_has_changed_conf_attr,
 
164
                       &tmp_has_changed_state_attr,
 
165
                       true, NULL, monitor);
 
166
 
 
167
      *is_ambiguous |= tmp_is_ambiguous;
 
168
 
 
169
      index++;
 
170
   }
 
171
 
 
172
   qinstance_set_conf_slots_used(ret);
 
173
   qinstance_debit_consumable(ret, NULL, centry_list, 0);
 
174
 
 
175
   /*
 
176
    * Change qinstance state
 
177
    */
 
178
   sge_qmaster_qinstance_state_set_ambiguous(ret, *is_ambiguous);
 
179
   if (*is_ambiguous) {
 
180
      DPRINTF(("Qinstance "SFN"@"SFN" has ambiguous configuration\n",
 
181
               cqueue_name, hostname));
 
182
   } else {
 
183
      DPRINTF(("Qinstance "SFN"@"SFN" has non-ambiguous configuration\n",
 
184
               cqueue_name, hostname));
 
185
   }
 
186
 
 
187
   /*
 
188
    * For new qinstances we have to set some internal fields which
 
189
    * will be spooled later on:
 
190
    *    - state (modification according to initial state)
 
191
    *    - qversion
 
192
    */
 
193
   sge_qmaster_qinstance_state_set_unknown(ret, true);
 
194
   qinstance_check_unknown_state(ret, *object_type_get_master_list(SGE_TYPE_EXECHOST));
 
195
   sge_qmaster_qinstance_set_initial_state(ret, false);
 
196
   qinstance_increase_qversion(ret);
 
197
 
 
198
   DRETURN(ret);
 
199
}
 
200
 
 
201
static bool
 
202
cqueue_add_qinstances(sge_gdi_ctx_class_t *ctx, lListElem *cqueue, lList **answer_list, lList *add_hosts, monitoring_t *monitor)
 
203
{
 
204
   bool ret = true;
 
205
 
 
206
   DENTER(TOP_LAYER, "cqueue_add_qinstances");
 
207
   if (cqueue != NULL && add_hosts != NULL) {
 
208
      lListElem *href = NULL;
 
209
 
 
210
      for_each(href, add_hosts) {
 
211
         const char *hostname = lGetHost(href, HR_name);
 
212
         lList *list = lGetList(cqueue, CQ_qinstances);
 
213
         lListElem* qinstance = lGetElemHost(list, QU_qhostname, hostname);
 
214
 
 
215
         if (qinstance != NULL) {
 
216
            if (qinstance_state_is_orphaned(qinstance)) {
 
217
               sge_qmaster_qinstance_state_set_orphaned(qinstance, false);
 
218
               lSetUlong(qinstance, QU_tag, SGE_QI_TAG_MOD);
 
219
            } else {
 
220
               /*
 
221
                * We might already have this QI if it is in orphaned state.
 
222
                * If this is not true, than there is a bug!
 
223
                */
 
224
               ERROR((SGE_EVENT, MSG_QINSTANCE_QIALREADYHERE_S, hostname));
 
225
               answer_list_add(answer_list, SGE_EVENT, STATUS_ESYNTAX,
 
226
                               ANSWER_QUALITY_ERROR);
 
227
            }
 
228
         } else {
 
229
            bool is_ambiguous = false;
 
230
 
 
231
            if (list == NULL) {
 
232
               list = lCreateList("", QU_Type);
 
233
               lSetList(cqueue, CQ_qinstances, list);
 
234
            }
 
235
            qinstance = qinstance_create(ctx,
 
236
                                         cqueue, answer_list,
 
237
                                         hostname, &is_ambiguous, monitor);
 
238
            if (is_ambiguous) {
 
239
               DPRINTF(("qinstance %s has ambiguous conf\n", hostname));
 
240
            }
 
241
            lSetUlong(qinstance, QU_tag, SGE_QI_TAG_ADD);
 
242
            lAppendElem(list, qinstance);
 
243
         }
 
244
      }
 
245
   }
 
246
   DEXIT;
 
247
   return ret;
 
248
}
 
249
 
 
250
static bool
 
251
cqueue_mark_qinstances(lListElem *cqueue, lList **answer_list, lList *del_hosts)
 
252
{
 
253
   bool ret = true;
 
254
 
 
255
   DENTER(TOP_LAYER, "cqueue_mark_qinstances");
 
256
   if (cqueue != NULL) {
 
257
      lList *qinstance_list = lGetList(cqueue, CQ_qinstances);
 
258
      lListElem *qinstance = NULL;
 
259
 
 
260
      for_each(qinstance, qinstance_list) {
 
261
         const char *hostname = lGetHost(qinstance, QU_qhostname);
 
262
         lListElem *href = lGetElemHost(del_hosts, HR_name, hostname);
 
263
 
 
264
         if (href != NULL) {
 
265
            if (qinstance_slots_used(qinstance) > 0 || qinstance_slots_reserved(qinstance) > 0) {
 
266
               /*
 
267
                * Jobs are currently running in this queue. Therefore
 
268
                * it is not possible to delete the queue but we
 
269
                * will set it into the "orphaned" state 
 
270
                */
 
271
               sge_qmaster_qinstance_state_set_orphaned(qinstance, true);
 
272
               lSetUlong(qinstance, QU_tag, SGE_QI_TAG_MOD);
 
273
            } else {
 
274
               lSetUlong(qinstance, QU_tag, SGE_QI_TAG_DEL);
 
275
            }
 
276
         } else {
 
277
            lSetUlong(qinstance, QU_tag, SGE_QI_TAG_DEFAULT);
 
278
         }
 
279
      }
 
280
   }
 
281
   DRETURN(ret);
 
282
}
 
283
 
 
284
static bool
 
285
cqueue_mod_attributes(lListElem *cqueue, lList **answer_list,
 
286
                      lListElem *reduced_elem, int sub_command)
 
287
{
 
288
   bool ret = true;
 
289
 
 
290
   DENTER(TOP_LAYER, "cqueue_mod_attributes");
 
291
   if (cqueue != NULL && reduced_elem != NULL) {
 
292
      const char *cqueue_name = lGetString(cqueue, CQ_name);
 
293
      int index = 0;
 
294
 
 
295
      while (cqueue_attribute_array[index].cqueue_attr != NoName && ret) {
 
296
         int pos = lGetPosViaElem(reduced_elem,
 
297
                                  cqueue_attribute_array[index].cqueue_attr, SGE_NO_ABORT);
 
298
 
 
299
         if (pos >= 0) {
 
300
            ret &= cqueue_mod_sublist(cqueue, answer_list, reduced_elem,
 
301
                             sub_command,
 
302
                             cqueue_attribute_array[index].cqueue_attr,
 
303
                             cqueue_attribute_array[index].href_attr,
 
304
                             cqueue_attribute_array[index].value_attr,
 
305
                             cqueue_attribute_array[index].primary_key_attr,
 
306
                             cqueue_attribute_array[index].name,
 
307
                             cqueue_name);
 
308
         }
 
309
         index++;
 
310
      }
 
311
   }
 
312
   DRETURN(ret);
 
313
}
 
314
 
 
315
static bool
 
316
cqueue_mod_hostlist(lListElem *cqueue, lList **answer_list,
 
317
                    lListElem *reduced_elem, int sub_command, 
 
318
                    lList **add_hosts, lList **rem_hosts)
 
319
{
 
320
   bool ret = true;
 
321
 
 
322
   DENTER(TOP_LAYER, "cqueue_mod_hostlist");
 
323
   if (cqueue != NULL && reduced_elem != NULL) {
 
324
      int pos = lGetPosViaElem(reduced_elem, CQ_hostlist, SGE_NO_ABORT);
 
325
 
 
326
      if (pos >= 0) {
 
327
         const char *cqueue_name = lGetString(cqueue, CQ_name);
 
328
         lList *list = lGetPosList(reduced_elem, pos);
 
329
         lList *old_href_list = lCopyList("", lGetList(cqueue, CQ_hostlist));
 
330
         lList *master_list = *(hgroup_list_get_master_list());
 
331
         lList *href_list = NULL;
 
332
         lList *add_groups = NULL;
 
333
         lList *rem_groups = NULL;
 
334
 
 
335
         if (ret) {
 
336
            ret &= href_list_resolve_hostnames(list, answer_list, true);
 
337
         }
 
338
         if (ret) {
 
339
            ret = attr_mod_sub_list(answer_list, cqueue, CQ_hostlist, HR_name, 
 
340
                                    reduced_elem, sub_command, 
 
341
                                    SGE_ATTR_HOST_LIST,
 
342
                                    cqueue_name, 0);         
 
343
            href_list = lGetList(cqueue, CQ_hostlist);
 
344
         }
 
345
         if (ret) {
 
346
            ret &= href_list_find_diff(href_list, answer_list, old_href_list, 
 
347
                                       add_hosts, rem_hosts, &add_groups,
 
348
                                       &rem_groups);
 
349
         }
 
350
         if (ret && add_groups != NULL) {
 
351
            ret &= hgroup_list_exists(master_list, answer_list, add_groups);
 
352
         }
 
353
         if (ret) {
 
354
            ret &= href_list_find_effective_diff(answer_list, add_groups, 
 
355
                                                 rem_groups, master_list, 
 
356
                                                 add_hosts, rem_hosts);
 
357
         }
 
358
         if (ret) {
 
359
            ret &= href_list_resolve_hostnames(*add_hosts, answer_list, false);
 
360
         }
 
361
 
 
362
         /*
 
363
          * Make sure that:
 
364
          *   - added hosts where not already part the old hostlist
 
365
          *   - removed hosts are not part of the new hostlist
 
366
          */
 
367
         if (ret) {
 
368
            lList *tmp_hosts = NULL;
 
369
 
 
370
            ret &= href_list_find_all_references(old_href_list, answer_list,
 
371
                                                 master_list, &tmp_hosts, NULL);
 
372
            ret &= href_list_remove_existing(add_hosts, answer_list, tmp_hosts);
 
373
            lFreeList(&tmp_hosts);
 
374
 
 
375
            ret &= href_list_find_all_references(href_list, answer_list,
 
376
                                                 master_list, &tmp_hosts, NULL);
 
377
            ret &= href_list_remove_existing(rem_hosts, answer_list, tmp_hosts);
 
378
            lFreeList(&tmp_hosts);
 
379
         }
 
380
 
 
381
#if 0 /* EB: DEBUG */
 
382
         if (ret) {
 
383
            href_list_debug_print(*add_hosts, "add_hosts: ");
 
384
            href_list_debug_print(*rem_hosts, "rem_hosts: ");
 
385
         }
 
386
#endif
 
387
 
 
388
         lFreeList(&old_href_list);
 
389
         lFreeList(&add_groups);
 
390
         lFreeList(&rem_groups);
 
391
      }
 
392
   }
 
393
   DEXIT;
 
394
   return ret;
 
395
}
 
396
 
 
397
bool
 
398
cqueue_mod_qinstances(sge_gdi_ctx_class_t *ctx,
 
399
                      lListElem *cqueue, lList **answer_list,
 
400
                      lListElem *reduced_elem, bool refresh_all_values, bool is_startup, monitoring_t *monitor)
 
401
{
 
402
   dstring buffer = DSTRING_INIT;
 
403
   bool ret = true;
 
404
   
 
405
   DENTER(TOP_LAYER, "cqueue_mod_qinstances");
 
406
 
 
407
   if (cqueue != NULL && reduced_elem != NULL) {
 
408
      lList *qinstance_list = lGetList(cqueue, CQ_qinstances);
 
409
      lListElem *qinstance = NULL;
 
410
 
 
411
      /*
 
412
       * Try to find changes for all qinstances ...
 
413
       */
 
414
      for_each(qinstance, qinstance_list) {
 
415
         const char *qinstance_name = qinstance_get_name(qinstance, &buffer);
 
416
         bool is_ambiguous = qinstance_state_is_ambiguous(qinstance);
 
417
         bool is_del = (lGetUlong(qinstance, QU_tag) == SGE_QI_TAG_DEL) ? true : false;
 
418
         bool will_be_ambiguous = false;
 
419
         bool state_changed = false;
 
420
         bool conf_changed = false;
 
421
         int index = 0;
 
422
         bool need_reinitialize = false;
 
423
 
 
424
         /*
 
425
          * Set full name of QI if it is not set
 
426
          */
 
427
         if (refresh_all_values &&
 
428
             lGetString(qinstance, QU_full_name) == NULL) {
 
429
            qinstance_set_full_name(qinstance);
 
430
         }
 
431
   
 
432
         /* 
 
433
          * Clear all messages which explain ambiguous state
 
434
          */
 
435
         qinstance_message_trash_all_of_type_X(qinstance, QI_AMBIGUOUS);
 
436
 
 
437
         /*
 
438
          * Handle each cqueue attribute as long as there was no error
 
439
          * and only if the qinstance won't be deleted afterward.
 
440
          */
 
441
 
 
442
         while (ret && !is_del &&
 
443
                cqueue_attribute_array[index].cqueue_attr != NoName) {
 
444
            const char *matching_host_or_group = NULL;
 
445
            const char *matching_group = NULL;
 
446
 
 
447
            int pos = lGetPosViaElem(reduced_elem,
 
448
                                 cqueue_attribute_array[index].cqueue_attr, SGE_NO_ABORT);
 
449
 
 
450
 
 
451
            /*
 
452
             * We try to find changes only for attributes which were 
 
453
             * sent by the client. Only for those attributes 'pos' will
 
454
             * be >= 0.
 
455
             *
 
456
             * There are two situations which make it absolutely necessary
 
457
             * to have a look on ALL attributes:
 
458
             *
 
459
             * 1) refresh_all_values == true
 
460
             *    The hostlist of "cqueue" changed. As a result it
 
461
             *    might be possible that a value for an attribute is
 
462
             *    now ambiguous. 
 
463
             * 
 
464
             * 2) is_ambiguous == true
 
465
             *    The qinstance is currently in the ambiguous state.
 
466
             *    It is not enough to test only modified attributes if
 
467
             *    they are nonambigous. It is also necesssary to check
 
468
             *    if all attributes which are not changed now are
 
469
             *    nonambigous to clear the ambigous-state from qinstance. 
 
470
             */
 
471
            if (pos >= 0 || refresh_all_values || is_ambiguous) {
 
472
               bool tmp_is_ambiguous = false;
 
473
               bool tmp_has_changed_conf_attr = false;
 
474
               bool tmp_has_changed_state_attr = false;
 
475
 
 
476
               ret &= qinstance_modify_attribute(ctx,
 
477
                          qinstance,
 
478
                          answer_list, cqueue,
 
479
                          cqueue_attribute_array[index].qinstance_attr,
 
480
                          cqueue_attribute_array[index].cqueue_attr,
 
481
                          cqueue_attribute_array[index].href_attr,
 
482
                          cqueue_attribute_array[index].value_attr,
 
483
                          cqueue_attribute_array[index].primary_key_attr,
 
484
                          &matching_host_or_group,
 
485
                          &matching_group,
 
486
                          &tmp_is_ambiguous,
 
487
                          &tmp_has_changed_conf_attr,
 
488
                          &tmp_has_changed_state_attr,
 
489
                          is_startup,
 
490
                          &need_reinitialize,
 
491
                          monitor);
 
492
 
 
493
               if (tmp_is_ambiguous) {
 
494
                  /*
 
495
                   * Add a message which explains the reason for
 
496
                   * ambiguous state
 
497
                   */   
 
498
                  sprintf(SGE_EVENT, MSG_ATTR_HASAMBVAL_SSS, 
 
499
                          cqueue_attribute_array[index].name,
 
500
                          matching_host_or_group, matching_group);
 
501
                  qinstance_message_add(qinstance, QI_AMBIGUOUS, SGE_EVENT);
 
502
               }
 
503
 
 
504
               will_be_ambiguous |= tmp_is_ambiguous;
 
505
               state_changed |= tmp_has_changed_state_attr;
 
506
               conf_changed |= tmp_has_changed_conf_attr;
 
507
            }
 
508
            
 
509
            index++;
 
510
         }
 
511
 
 
512
         if (need_reinitialize) {
 
513
            qinstance_reinit_consumable_actual_list(qinstance, answer_list);
 
514
         }
 
515
 
 
516
         /*
 
517
          * Change qinstance state
 
518
          */
 
519
         sge_qmaster_qinstance_state_set_ambiguous(qinstance, will_be_ambiguous);
 
520
         if (will_be_ambiguous && !is_ambiguous) {
 
521
            state_changed = true;
 
522
            DPRINTF(("Qinstance "SFQ" has ambiguous configuration\n",
 
523
                     qinstance_name));
 
524
         } else if (!will_be_ambiguous && is_ambiguous) {
 
525
            state_changed = true;
 
526
            DPRINTF(("Qinstance "SFQ" has non-ambiguous configuration\n",
 
527
                     qinstance_name));
 
528
         }
 
529
 
 
530
         /*
 
531
          * Tag the qinstance as modified if the internal state changed. 
 
532
          * This will result in spooling the qinstance. Also mod-events wiil 
 
533
          * be sent. If only the configuration changed than it is only 
 
534
          * necessary to send mod-events.
 
535
          */
 
536
         if (state_changed) {
 
537
            DPRINTF(("Internal state of qinstance "SFQ" has been changed\n",
 
538
                     qinstance_name));
 
539
            lSetUlong(qinstance, QU_tag, SGE_QI_TAG_MOD);
 
540
            qinstance_increase_qversion(qinstance);
 
541
         } else if (conf_changed) {
 
542
            DPRINTF(("Only config value of qinstance "SFQ" has been changed\n",
 
543
                     qinstance_name));
 
544
            lSetUlong(qinstance, QU_tag, SGE_QI_TAG_MOD_ONLY_CONFIG);
 
545
            qinstance_increase_qversion(qinstance);
 
546
         }
 
547
 
 
548
         if (ret && !is_startup) {
 
549
            lListElem *ar;
 
550
            lList *master_userset_list = *(object_type_get_master_list(SGE_TYPE_USERSET));
 
551
 
 
552
            for_each(ar, *(object_type_get_master_list(SGE_TYPE_AR))) {
 
553
               if (lGetElemStr(lGetList(ar, AR_granted_slots), JG_qname, qinstance_name)) {
 
554
                  if (!sge_ar_have_users_access(NULL, ar, lGetString(qinstance, QU_full_name), 
 
555
                                                lGetList(qinstance, QU_acl),
 
556
                                                lGetList(qinstance, QU_xacl),
 
557
                                                master_userset_list)) {
 
558
                     ERROR((SGE_EVENT, MSG_PARSE_MOD3_REJECTED_DUE_TO_AR_SU, 
 
559
                            SGE_ATTR_USER_LISTS, sge_u32c(lGetUlong(ar, AR_id))));
 
560
                     answer_list_add(answer_list, SGE_EVENT, 
 
561
                                     STATUS_ESYNTAX, ANSWER_QUALITY_ERROR);
 
562
                     ret = false;
 
563
                     break;
 
564
                  }
 
565
               }
 
566
            }
 
567
         }
 
568
 
 
569
         if (!ret) {
 
570
            /*
 
571
             * Skip remaining qinstances if an error occured.
 
572
             */
 
573
            break;
 
574
         }
 
575
      }
 
576
   }
 
577
   sge_dstring_free(&buffer);
 
578
 
 
579
   DRETURN(ret);
 
580
}
 
581
 
 
582
bool
 
583
cqueue_handle_qinstances(sge_gdi_ctx_class_t *ctx, 
 
584
                         lListElem *cqueue, lList **answer_list,
 
585
                         lListElem *reduced_elem, lList *add_hosts,
 
586
                         lList *rem_hosts, bool refresh_all_values,
 
587
                         monitoring_t *monitor) 
 
588
{
 
589
   bool ret = true;
 
590
 
 
591
   DENTER(TOP_LAYER, "cqueue_handle_qinstances");
 
592
 
 
593
   if (ret) { 
 
594
      ret = cqueue_mark_qinstances(cqueue, answer_list, rem_hosts);
 
595
   }
 
596
   if (ret) {
 
597
      ret = cqueue_mod_qinstances(ctx, cqueue, answer_list, reduced_elem, 
 
598
                                   refresh_all_values, false, monitor);
 
599
   }
 
600
   if (ret) {
 
601
      ret = cqueue_add_qinstances(ctx, cqueue, answer_list, add_hosts, monitor);
 
602
   }
 
603
   DRETURN(ret);
 
604
}
 
605
 
 
606
int cqueue_mod(sge_gdi_ctx_class_t *ctx,
 
607
               lList **answer_list, lListElem *cqueue, lListElem *reduced_elem, 
 
608
               int add, const char *remote_user, const char *remote_host,
 
609
               gdi_object_t *object, int sub_command, monitoring_t *monitor) 
 
610
{
 
611
   bool ret = true;
 
612
   lList *add_hosts = NULL;
 
613
   lList *rem_hosts = NULL;
 
614
 
 
615
 
 
616
   DENTER(TOP_LAYER, "cqueue_mod");
 
617
 
 
618
   if (ret) {
 
619
      int pos = lGetPosViaElem(reduced_elem, CQ_name, SGE_NO_ABORT);
 
620
 
 
621
      if (pos >= 0) {
 
622
         const char *name = lGetPosString(reduced_elem, pos);
 
623
 
 
624
         if (add) {
 
625
            if (verify_str_key(
 
626
                  answer_list, name, MAX_VERIFY_STRING, "cqueue", KEY_TABLE) == STATUS_OK) {
 
627
               DTRACE;
 
628
               lSetString(cqueue, CQ_name, name);
 
629
            } else {
 
630
               ERROR((SGE_EVENT, MSG_CQUEUE_NAMENOTGUILTY_S, name));
 
631
               answer_list_add(answer_list, SGE_EVENT, STATUS_ESYNTAX,
 
632
                               ANSWER_QUALITY_ERROR);
 
633
               ret = false;
 
634
            }
 
635
         } else {
 
636
            const char *old_name = lGetString(cqueue, CQ_name);
 
637
 
 
638
            if (strcmp(old_name, name)) {
 
639
               ERROR((SGE_EVENT, MSG_CQUEUE_NONAMECHANGE));
 
640
               answer_list_add(answer_list, SGE_EVENT, STATUS_ESYNTAX,
 
641
                               ANSWER_QUALITY_ERROR);
 
642
               ret = false;
 
643
            }
 
644
         }
 
645
      } else {
 
646
         ERROR((SGE_EVENT, MSG_SGETEXT_MISSINGCULLFIELD_SS,
 
647
                lNm2Str(CQ_name), SGE_FUNC));
 
648
         answer_list_add(answer_list, SGE_EVENT, STATUS_EUNKNOWN,
 
649
                         ANSWER_QUALITY_ERROR);
 
650
         ret = false;
 
651
      }
 
652
   } 
 
653
 
 
654
   /*
 
655
    * Find differences of hostlist configuration
 
656
    */
 
657
   if (ret) {
 
658
      ret &= cqueue_mod_hostlist(cqueue, answer_list, reduced_elem,
 
659
                                 sub_command, &add_hosts, &rem_hosts);
 
660
   }
 
661
 
 
662
   /*
 
663
    * Its time to do the cqueue modifications:
 
664
    *    - change the attribute lists in the cqueue object
 
665
    *    - verify the attribute lists
 
666
    */
 
667
   if (ret) {
 
668
      ret &= cqueue_mod_attributes(cqueue, answer_list, 
 
669
                                   reduced_elem, sub_command);
 
670
   }
 
671
   if (ret) {
 
672
      ret &= cqueue_verify_attributes(cqueue, answer_list, 
 
673
                                      reduced_elem, true);
 
674
   }
 
675
 
 
676
   /*
 
677
    * Now we have to add/mod/del all qinstances
 
678
    */ 
 
679
   if (ret) {
 
680
      bool refresh_all_values = ((add_hosts != NULL) || (rem_hosts != NULL)) ? true : false;
 
681
 
 
682
      ret &= cqueue_handle_qinstances(ctx, 
 
683
                                      cqueue, answer_list, reduced_elem, 
 
684
                                      add_hosts, rem_hosts, refresh_all_values, monitor);
 
685
   }
 
686
 
 
687
   /*
 
688
    * Client and scheduler code expects existing EH_Type elements
 
689
    * for all hosts used in CQ_hostlist. Therefore it is neccessary
 
690
    * to create all not existing EH_Type elements.
 
691
    */
 
692
   if (ret) {
 
693
      lList *list = *(object_type_get_master_list(SGE_TYPE_EXECHOST));
 
694
 
 
695
      ret &= host_list_add_missing_href(ctx, list, answer_list, add_hosts, monitor);
 
696
   }
 
697
 
 
698
   /*
 
699
    * Cleanup
 
700
    */
 
701
   lFreeList(&add_hosts);
 
702
   lFreeList(&rem_hosts);
 
703
 
 
704
   if (ret) {
 
705
      DRETURN(0);
 
706
   } else {
 
707
      DRETURN(STATUS_EUNKNOWN);
 
708
   }
 
709
}
 
710
 
 
711
int cqueue_success(sge_gdi_ctx_class_t *ctx,
 
712
                   lListElem *cqueue, lListElem *old_cqueue, 
 
713
                   gdi_object_t *object, lList **ppList, monitoring_t *monitor) 
 
714
{
 
715
   lList *qinstances;
 
716
   lListElem *qinstance; 
 
717
   DENTER(TOP_LAYER, "cqueue_success");
 
718
 
 
719
   cqueue_update_categories(cqueue, old_cqueue);
 
720
 
 
721
   /*
 
722
    * CQ modify or add event
 
723
    */
 
724
   sge_add_event(0, old_cqueue?sgeE_CQUEUE_MOD:sgeE_CQUEUE_ADD, 0, 0, 
 
725
                 lGetString(cqueue, CQ_name), NULL, NULL, cqueue);
 
726
 
 
727
   /*
 
728
    * QI modify, add or delete event. Finalize operation.
 
729
    */
 
730
   cqueue_commit(ctx, cqueue);
 
731
 
 
732
   /*
 
733
    * Handle jobs which were supended due to suspend threshold
 
734
    */
 
735
   qinstances = lGetList(cqueue, CQ_qinstances);
 
736
 
 
737
   for_each(qinstance, qinstances) {
 
738
      if (lGetUlong(qinstance, QU_gdi_do_later) == GDI_DO_LATER) {
 
739
         bool is_qinstance_mod = false;
 
740
         const char *full_name = lGetString(qinstance, QU_full_name);
 
741
         lList *master_job_list = *(object_type_get_master_list(SGE_TYPE_JOB));
 
742
         lListElem *job;
 
743
 
 
744
         lSetUlong(qinstance, QU_gdi_do_later, 0);
 
745
 
 
746
         /* in case the thresholds are set to none, we have to unsuspend all jobs because
 
747
            the scheduler is not able to do that. If the suspend threshold is still set; 
 
748
            just changed, the scheduler can easily deal with it.*/
 
749
         if (lGetList(qinstance, QU_suspend_thresholds) == NULL) { 
 
750
            for_each(job, master_job_list) {
 
751
               lList *ja_tasks = lGetList(job, JB_ja_tasks);
 
752
               lListElem *ja_task;
 
753
 
 
754
               for_each(ja_task, ja_tasks) {
 
755
                  u_long32 state = lGetUlong(ja_task, JAT_state);
 
756
 
 
757
                  if (ISSET(state, JSUSPENDED_ON_THRESHOLD)) {
 
758
                     /* this does most likely not work with pe jobs, which run in different queues.
 
759
                        Issue: 831*/
 
760
                     const char *queue_name = lGetString(lFirst(lGetList(ja_task,
 
761
                                 JAT_granted_destin_identifier_list)), JG_qname);
 
762
 
 
763
                     if (!strcmp(queue_name, full_name)) {
 
764
 
 
765
                        if (!ISSET(state, JSUSPENDED)) {
 
766
                           sge_signal_queue(ctx, SGE_SIGCONT, qinstance, job, ja_task, monitor);
 
767
                           SETBIT(JRUNNING, state); 
 
768
                           is_qinstance_mod = true;
 
769
                        }
 
770
 
 
771
                        CLEARBIT(JSUSPENDED_ON_THRESHOLD, state);
 
772
                        
 
773
                        lSetUlong(ja_task, JAT_state, state);
 
774
 
 
775
                        sge_event_spool(ctx, NULL, 0, sgeE_JATASK_MOD,
 
776
                                        lGetUlong(job,JB_job_number), 
 
777
                                        lGetUlong(ja_task, JAT_task_number), NULL, NULL, NULL,
 
778
                                        job, ja_task, NULL, true, true);
 
779
                        
 
780
                     }
 
781
                  }
 
782
               }
 
783
            }
 
784
         }
 
785
         
 
786
         if (is_qinstance_mod) {
 
787
               const char *hostname = lGetHost(qinstance, QU_qhostname);
 
788
               const char *cqueue_name = lGetString(qinstance, QU_qname);         
 
789
               sge_event_spool(ctx, NULL, 0, sgeE_QINSTANCE_MOD,
 
790
                               0, 0, cqueue_name, hostname, NULL,
 
791
                               qinstance, NULL, NULL, true, true);         
 
792
         }
 
793
      }
 
794
   }
 
795
 
 
796
   DRETURN(0);
 
797
}
 
798
 
 
799
void cqueue_commit(sge_gdi_ctx_class_t *ctx, lListElem *cqueue) 
 
800
{
 
801
   lList *qinstances = lGetList(cqueue, CQ_qinstances);
 
802
   lListElem *next_qinstance = NULL;
 
803
   lListElem *qinstance = NULL;
 
804
 
 
805
   DENTER(TOP_LAYER, "cqueue_commit"); 
 
806
 
 
807
   /*
 
808
    * QI modify, add or delete event
 
809
    */
 
810
   next_qinstance = lFirst(qinstances);
 
811
   while ((qinstance = next_qinstance)) {
 
812
      u_long32 tag = lGetUlong(qinstance, QU_tag);
 
813
      const char *name = lGetString(qinstance, QU_qname);
 
814
      const char *hostname = lGetHost(qinstance, QU_qhostname);
 
815
 
 
816
      next_qinstance = lNext(qinstance);
 
817
 
 
818
      /*
 
819
       * Reset QI tag
 
820
       */
 
821
      lSetUlong(qinstance, QU_tag, SGE_QI_TAG_DEFAULT);
 
822
 
 
823
      if (tag == SGE_QI_TAG_ADD) {
 
824
         sge_add_event( 0, sgeE_QINSTANCE_ADD, 0, 0,
 
825
                       name, hostname, NULL, qinstance);
 
826
      } else if (tag == SGE_QI_TAG_MOD ||
 
827
                 tag == SGE_QI_TAG_MOD_ONLY_CONFIG) {
 
828
         sge_add_event( 0, sgeE_QINSTANCE_MOD, 0, 0,
 
829
                       name, hostname, NULL, qinstance);
 
830
      } else if (tag == SGE_QI_TAG_DEL) {
 
831
         sge_event_spool(ctx, NULL, 0, sgeE_QINSTANCE_DEL,
 
832
                         0, 0, name, hostname,
 
833
                         NULL, NULL, NULL, NULL, true, true);
 
834
 
 
835
         /*
 
836
          * Now we can remove the qinstance.
 
837
          */
 
838
         lRemoveElem(qinstances, &qinstance);
 
839
      }
 
840
   }
 
841
   if (lGetNumberOfElem(qinstances) == 0) {
 
842
      lSetList(cqueue, CQ_qinstances, NULL);
 
843
   }
 
844
   DEXIT;
 
845
}
 
846
 
 
847
int cqueue_spool(sge_gdi_ctx_class_t *ctx, lList **answer_list, lListElem *cqueue, gdi_object_t *object) 
 
848
{  
 
849
   int ret = 0;
 
850
   const char *name = lGetString(cqueue, CQ_name);
 
851
   lListElem *qinstance;
 
852
   dstring key_dstring = DSTRING_INIT;
 
853
   bool dbret;
 
854
   lList *spool_answer_list = NULL;
 
855
   bool job_spooling = ctx->get_job_spooling(ctx);
 
856
 
 
857
   DENTER(TOP_LAYER, "cqueue_spool");
 
858
   dbret = spool_write_object(&spool_answer_list, spool_get_default_context(), 
 
859
                              cqueue, name, SGE_TYPE_CQUEUE,
 
860
                              job_spooling);
 
861
   answer_list_output(&spool_answer_list);
 
862
 
 
863
   if (!dbret) {
 
864
      answer_list_add_sprintf(answer_list, STATUS_EUNKNOWN, 
 
865
                              ANSWER_QUALITY_ERROR, 
 
866
                              MSG_PERSISTENCE_WRITE_FAILED_S,
 
867
                              name);
 
868
      ret = 1;
 
869
   }
 
870
 
 
871
   for_each(qinstance, lGetList(cqueue, CQ_qinstances)) {
 
872
      u_long32 tag = lGetUlong(qinstance, QU_tag);
 
873
      
 
874
      if (tag == SGE_QI_TAG_ADD || tag == SGE_QI_TAG_MOD) {
 
875
         const char *key = 
 
876
               sge_dstring_sprintf(&key_dstring, "%s/%s", name,
 
877
                                   lGetHost(qinstance, QU_qhostname));
 
878
         dbret = spool_write_object(&spool_answer_list, 
 
879
                                    spool_get_default_context(), qinstance,
 
880
                                    key, SGE_TYPE_QINSTANCE,
 
881
                                    job_spooling);
 
882
         answer_list_output(&spool_answer_list);
 
883
 
 
884
         if (!dbret) {
 
885
            answer_list_add_sprintf(answer_list, STATUS_EUNKNOWN, 
 
886
                                    ANSWER_QUALITY_ERROR, 
 
887
                                    MSG_PERSISTENCE_WRITE_FAILED_S,
 
888
                                    key);
 
889
            ret = 1;
 
890
         }
 
891
      }
 
892
   }
 
893
 
 
894
   sge_dstring_free(&key_dstring);
 
895
   
 
896
   DEXIT;
 
897
   return ret;
 
898
}
 
899
 
 
900
int cqueue_del(sge_gdi_ctx_class_t *ctx, lListElem *this_elem, lList **answer_list, 
 
901
               char *remote_user, char *remote_host) 
 
902
{
 
903
   bool ret = true;
 
904
 
 
905
   DENTER(TOP_LAYER, "cqueue_del");
 
906
 
 
907
   if (this_elem != NULL && remote_user != NULL && remote_host != NULL) {
 
908
      const char* name = lGetString(this_elem, CQ_name);
 
909
 
 
910
      if (name != NULL) {
 
911
         lList *master_list = *(object_type_get_master_list(SGE_TYPE_CQUEUE));
 
912
         lListElem *cqueue = cqueue_list_locate(master_list, name);
 
913
 
 
914
         if (cqueue != NULL) {
 
915
            lList *qinstances = lGetList(cqueue, CQ_qinstances);
 
916
            lListElem *qinstance = NULL;
 
917
            const char *cq_name = lGetString(cqueue, CQ_name);
 
918
            dstring dir = DSTRING_INIT;
 
919
            bool do_del = true;
 
920
 
 
921
 
 
922
            /*
 
923
             * test if the CQ can be removed
 
924
             */
 
925
            for_each(qinstance, qinstances) {
 
926
               if (qinstance_slots_used(qinstance) > 0 || qinstance_slots_reserved(qinstance) > 0) {
 
927
                  ERROR((SGE_EVENT, MSG_QINSTANCE_STILLJOBS)); 
 
928
                  answer_list_add(answer_list, SGE_EVENT, STATUS_EEXIST,
 
929
                                  ANSWER_QUALITY_ERROR);
 
930
                  do_del = false;
 
931
                  break; 
 
932
               }
 
933
            }
 
934
 
 
935
            /*
 
936
             * check for references of this cqueue in other cqueues subordinate
 
937
             * lists
 
938
             */
 
939
            if (do_del) {
 
940
               lListElem *tmp_cqueue;
 
941
               
 
942
               for_each(tmp_cqueue, master_list) {
 
943
               
 
944
                  if (cqueue_is_used_in_subordinate(name, tmp_cqueue)) {
 
945
                     ERROR((SGE_EVENT, MSG_CQUEUE_DEL_ISREFASSUBORDINATE_SS, 
 
946
                           name, lGetString(tmp_cqueue, CQ_name)));
 
947
                     answer_list_add(answer_list, SGE_EVENT, STATUS_EUNKNOWN, 
 
948
                            ANSWER_QUALITY_ERROR);
 
949
                     do_del = false;
 
950
                     break;
 
951
                  }
 
952
               }
 
953
            }
 
954
            
 
955
            if (do_del) {
 
956
               /*
 
957
                * delete QIs
 
958
                */
 
959
               dstring key = DSTRING_INIT;
 
960
               sge_dstring_sprintf(&dir, "%s/%s", QINSTANCES_DIR, cq_name); 
 
961
 
 
962
               for_each(qinstance, qinstances) {
 
963
                  const char *qi_name = lGetHost(qinstance, QU_qhostname);
 
964
 
 
965
                  sge_dstring_sprintf(&key, "%s/%s", cq_name, qi_name); 
 
966
                  if (sge_event_spool(ctx, answer_list, 0, sgeE_QINSTANCE_DEL,
 
967
                                      0, 0, cq_name, qi_name,
 
968
                                      NULL, NULL, NULL, NULL, true, true)) {
 
969
                     ; 
 
970
                  }
 
971
               }
 
972
               sge_dstring_free(&key);
 
973
               sge_rmdir(sge_dstring_get_string(&dir), NULL);
 
974
               sge_dstring_free(&dir);
 
975
 
 
976
               /*
 
977
                * delete CQ
 
978
                */
 
979
               if (sge_event_spool(ctx, answer_list, 0, sgeE_CQUEUE_DEL,
 
980
                                   0, 0, name, NULL, NULL,
 
981
                                   NULL, NULL, NULL, true, true)) {
 
982
                  cqueue_update_categories(NULL, cqueue);
 
983
                  lRemoveElem(*(object_type_get_master_list(SGE_TYPE_CQUEUE)), &cqueue);
 
984
 
 
985
                  INFO((SGE_EVENT, MSG_SGETEXT_REMOVEDFROMLIST_SSSS,
 
986
                        remote_user, remote_host, name , "cluster queue"));
 
987
                  answer_list_add(answer_list, SGE_EVENT, STATUS_OK,
 
988
                                  ANSWER_QUALITY_INFO);
 
989
               } else {
 
990
                  ERROR((SGE_EVENT, MSG_CANTSPOOL_SS, "cluster queue",
 
991
                         name )); 
 
992
                  answer_list_add(answer_list, SGE_EVENT, STATUS_EEXIST,
 
993
                                  ANSWER_QUALITY_ERROR);
 
994
                  ret = false;
 
995
               }
 
996
            } else {
 
997
               ret = false;
 
998
            }
 
999
         } else {
 
1000
            ERROR((SGE_EVENT, MSG_SGETEXT_DOESNOTEXIST_SS,
 
1001
                   "cluster queue", name));
 
1002
            answer_list_add(answer_list, SGE_EVENT, STATUS_EEXIST,
 
1003
                            ANSWER_QUALITY_ERROR);
 
1004
            ret = false;
 
1005
         }
 
1006
      } else {
 
1007
         ERROR((SGE_EVENT, MSG_SGETEXT_MISSINGCULLFIELD_SS,
 
1008
                lNm2Str(CQ_name), SGE_FUNC));
 
1009
         answer_list_add(answer_list, SGE_EVENT, STATUS_EUNKNOWN,
 
1010
                         ANSWER_QUALITY_ERROR);
 
1011
         ret = false;
 
1012
      }
 
1013
   } else {
 
1014
      CRITICAL((SGE_EVENT, MSG_SGETEXT_NULLPTRPASSED_S, SGE_FUNC));
 
1015
      answer_list_add(answer_list, SGE_EVENT, STATUS_EUNKNOWN,
 
1016
                      ANSWER_QUALITY_ERROR);
 
1017
      ret = false;
 
1018
   }
 
1019
 
 
1020
   DEXIT;
 
1021
   if (ret) {
 
1022
      return STATUS_OK;
 
1023
   } else {
 
1024
      return STATUS_EUNKNOWN;
 
1025
   } 
 
1026
}
 
1027
 
 
1028
bool
 
1029
cqueue_del_all_orphaned(sge_gdi_ctx_class_t *ctx, lListElem *this_elem, lList **answer_list, const char *ehname)
 
1030
{
 
1031
   bool ret = true;
 
1032
 
 
1033
   DENTER(TOP_LAYER, "cqueue_del_all_orphaned");
 
1034
 
 
1035
   if (this_elem != NULL) {
 
1036
      dstring dir = DSTRING_INIT;
 
1037
      const char* cq_name = lGetString(this_elem, CQ_name);
 
1038
      lList *qinstance_list = lGetList(this_elem, CQ_qinstances);
 
1039
      lListElem *qinstance = NULL;
 
1040
 
 
1041
      if (ehname) {
 
1042
         if ((qinstance = lGetElemHost(qinstance_list, QU_qhostname, ehname)) &&
 
1043
             qinstance_state_is_orphaned(qinstance) &&
 
1044
             qinstance_slots_used(qinstance) == 0 && 
 
1045
             qinstance_slots_reserved(qinstance) == 0) {
 
1046
            const char *qi_name = lGetHost(qinstance, QU_qhostname);
 
1047
      
 
1048
            /*
 
1049
             * This qinstance should be deleted. There are not jobs anymore.
 
1050
             */
 
1051
            sge_dstring_sprintf(&dir, "%s/%s", QINSTANCES_DIR, cq_name);
 
1052
            if (sge_event_spool(ctx, answer_list, 0, sgeE_QINSTANCE_DEL,
 
1053
                                0, 0, cq_name, qi_name,
 
1054
                                NULL, NULL, NULL, NULL, true, true)) {
 
1055
               lRemoveElem(qinstance_list, &qinstance);
 
1056
               if (lGetNumberOfElem(qinstance_list) == 0) {
 
1057
                  sge_rmdir(sge_dstring_get_string(&dir), NULL);
 
1058
               }
 
1059
            }
 
1060
         }
 
1061
      } else {
 
1062
         lListElem *next_qinstance = NULL;
 
1063
 
 
1064
         next_qinstance = lFirst(qinstance_list);
 
1065
         while ((qinstance = next_qinstance) != NULL) {
 
1066
            next_qinstance = lNext(qinstance);
 
1067
 
 
1068
            if (qinstance_state_is_orphaned(qinstance) &&
 
1069
                qinstance_slots_used(qinstance) == 0 && 
 
1070
                qinstance_slots_reserved(qinstance) == 0) {
 
1071
               const char *qi_name = lGetHost(qinstance, QU_qhostname);
 
1072
         
 
1073
               /*
 
1074
                * This qinstance should be deleted. There are not jobs anymore.
 
1075
                */
 
1076
               sge_dstring_sprintf(&dir, "%s/%s", QINSTANCES_DIR, cq_name);
 
1077
               if (sge_event_spool(ctx, answer_list, 0, sgeE_QINSTANCE_DEL,
 
1078
                                   0, 0, cq_name, qi_name,
 
1079
                                   NULL, NULL, NULL, NULL, true, true)) {
 
1080
                  lRemoveElem(qinstance_list, &qinstance);
 
1081
                  if (lGetNumberOfElem(qinstance_list) == 0) {
 
1082
                     sge_rmdir(sge_dstring_get_string(&dir), NULL);
 
1083
                  }
 
1084
               }
 
1085
            }
 
1086
         }
 
1087
      }
 
1088
      sge_dstring_free(&dir);
 
1089
   }
 
1090
 
 
1091
   DEXIT;
 
1092
   return ret;
 
1093
}
 
1094
 
 
1095
bool
 
1096
cqueue_list_del_all_orphaned(sge_gdi_ctx_class_t *ctx, lList *this_list, lList **answer_list, const char *cqname, const char *ehname)
 
1097
{
 
1098
   bool ret = true;
 
1099
   lListElem *cqueue;
 
1100
 
 
1101
   DENTER(TOP_LAYER, "cqueue_list_del_all_orphaned");
 
1102
 
 
1103
   if (cqname) {
 
1104
      cqueue = lGetElemStr(this_list, CQ_name, cqname);
 
1105
      ret &= cqueue_del_all_orphaned(ctx, cqueue, answer_list, ehname);
 
1106
   } else {
 
1107
      for_each(cqueue, this_list) {
 
1108
         ret &= cqueue_del_all_orphaned(ctx, cqueue, answer_list, ehname);
 
1109
         if (!ret) {
 
1110
            break;
 
1111
         }
 
1112
      }
 
1113
   }
 
1114
 
 
1115
   DEXIT;
 
1116
   return ret;
 
1117
}
 
1118
 
 
1119
void
 
1120
cqueue_list_set_unknown_state(lList *this_list, const char *hostname,  
 
1121
                              bool send_events, bool is_unknown)
 
1122
{
 
1123
   lListElem *cqueue = NULL;
 
1124
 
 
1125
   for_each(cqueue, this_list) {
 
1126
      if (hostname != NULL) {
 
1127
         lList *qinstance_list = lGetList(cqueue, CQ_qinstances);
 
1128
         lListElem *qinstance = lGetElemHost(qinstance_list, QU_qhostname,
 
1129
                                             hostname);
 
1130
         if (qinstance != NULL &&
 
1131
             qinstance_state_is_unknown(qinstance) != is_unknown) {
 
1132
            sge_qmaster_qinstance_state_set_unknown(qinstance, is_unknown);
 
1133
            if (send_events) {
 
1134
               qinstance_add_event(qinstance, sgeE_QINSTANCE_MOD);
 
1135
            }
 
1136
         }
 
1137
      } else {
 
1138
         lListElem *qinstance = NULL;
 
1139
         for_each (qinstance, lGetList(cqueue, CQ_qinstances)) {
 
1140
            if (qinstance_state_is_unknown(qinstance) != is_unknown) {
 
1141
               sge_qmaster_qinstance_state_set_unknown(qinstance, is_unknown);
 
1142
               if (send_events) {
 
1143
                  qinstance_add_event(qinstance, sgeE_QINSTANCE_MOD);
 
1144
               }
 
1145
            }
 
1146
         }
 
1147
      }
 
1148
   }
 
1149
}
 
1150
 
 
1151
 
 
1152
/****** sge_cqueue_qmaster/cqueue_diff_sublist() *******************************
 
1153
*  NAME
 
1154
*     cqueue_diff_sublist() -- Diff cluster queue sublists
 
1155
*
 
1156
*  SYNOPSIS
 
1157
*     static void cqueue_diff_sublist(const lListElem *new, const lListElem
 
1158
*     *old, int snm1, int snm2, int sublist_nm, int key_nm, const lDescr *dp,
 
1159
*     lList **new_sublist, lList **old_sublist)
 
1160
*
 
1161
*  FUNCTION
 
1162
*     Determine new/old refereneces in a cluster queue configuration sublist.
 
1163
*
 
1164
*  INPUTS
 
1165
*     const lListElem *new - New cluster queue (CQ_Type)
 
1166
*     const lListElem *old - Old cluster queue (CQ_Type)
 
1167
*     int snm1             - First cluster queue sublist field
 
1168
*     int snm2             - Second cluster queue sublist field
 
1169
*     int sublist_nm       - Subsub list field
 
1170
*     int key_nm           - Field with key in subsublist
 
1171
*     const lDescr *dp     - Type for outgoing sublist arguments
 
1172
*     lList **new_sublist  - List of new references
 
1173
*     lList **old_sublist  - List of old references
 
1174
*
 
1175
*  NOTES
 
1176
*     MT-NOTE: cqueue_diff_sublist() is MT safe
 
1177
*******************************************************************************/
 
1178
static void cqueue_diff_sublist(const lListElem *new, const lListElem *old,
 
1179
      int snm1, int snm2, int sublist_nm, int key_nm, const lDescr *dp,
 
1180
      lList **new_sublist, lList **old_sublist)
 
1181
{
 
1182
   const lListElem *qc, *ep;
 
1183
   const char *p;
 
1184
 
 
1185
   DENTER(TOP_LAYER, "cqueue_diff_sublist");
 
1186
 
 
1187
   /* collect 'old' entries in 'old_sublist' */
 
1188
   if (old && old_sublist) {
 
1189
      for_each (qc, lGetList(old, snm1)) {
 
1190
         for_each (ep, lGetList(qc, sublist_nm)) {
 
1191
            p = lGetString(ep, key_nm);
 
1192
            if (!lGetElemStr(*old_sublist, key_nm, p))
 
1193
               lAddElemStr(old_sublist, key_nm, p, dp);
 
1194
         }
 
1195
      }
 
1196
      for_each (qc, lGetList(old, snm2)) {
 
1197
         for_each (ep, lGetList(qc, sublist_nm)) {
 
1198
            p = lGetString(ep, key_nm);
 
1199
            if (!lGetElemStr(*old_sublist, key_nm, p))
 
1200
               lAddElemStr(old_sublist, key_nm, p, dp);
 
1201
         }
 
1202
      }
 
1203
   }
 
1204
 
 
1205
   /* collect 'new' entries in 'new_sublist' */
 
1206
   if (new && new_sublist) {
 
1207
      for_each (qc, lGetList(new, snm1)) {
 
1208
         for_each (ep, lGetList(qc, sublist_nm)) {
 
1209
            p = lGetString(ep, key_nm);
 
1210
            if (!lGetElemStr(*new_sublist, key_nm, p))
 
1211
               lAddElemStr(new_sublist, key_nm, p, dp);
 
1212
         }
 
1213
      }
 
1214
      for_each (qc, lGetList(new, snm2)) {
 
1215
         for_each (ep, lGetList(qc, sublist_nm)) {
 
1216
            p = lGetString(ep, key_nm);
 
1217
            if (!lGetElemStr(*new_sublist, key_nm, p))
 
1218
               lAddElemStr(new_sublist, key_nm, p, dp);
 
1219
         }
 
1220
      }
 
1221
   }
 
1222
 
 
1223
   DEXIT;
 
1224
   return;
 
1225
}
 
1226
 
 
1227
/****** sge_cqueue_qmaster/cqueue_diff_projects() ******************************
 
1228
*  NAME
 
1229
*     cqueue_diff_projects() -- Diff old/new cluster queue projects
 
1230
*
 
1231
*  SYNOPSIS
 
1232
*     void cqueue_diff_projects(const lListElem *new, const lListElem *old,
 
1233
*     lList **new_prj, lList **old_prj)
 
1234
*
 
1235
*  FUNCTION
 
1236
*     A diff new/old is made regarding cluster queue projects/xprojects.
 
1237
*     Project references are returned in new_prj/old_prj.
 
1238
*
 
1239
*  INPUTS
 
1240
*     const lListElem *new - New cluster queue (CQ_Type)
 
1241
*     const lListElem *old - Old cluster queue (CQ_Type)
 
1242
*     lList **new_prj      - New project references (PR_Type)
 
1243
*     lList **old_prj      - Old project references (PR_Type)
 
1244
*
 
1245
*  NOTES
 
1246
*     MT-NOTE: cqueue_diff_projects() is MT safe
 
1247
*******************************************************************************/
 
1248
void cqueue_diff_projects(const lListElem *new,
 
1249
         const lListElem *old, lList **new_prj, lList **old_prj)
 
1250
{
 
1251
   cqueue_diff_sublist(new, old, CQ_projects, CQ_xprojects,
 
1252
         APRJLIST_value, PR_name, PR_Type, new_prj, old_prj);
 
1253
   lDiffListStr(PR_name, new_prj, old_prj);
 
1254
}
 
1255
 
 
1256
/****** sge_cqueue_qmaster/cqueue_diff_usersets() ******************************
 
1257
*  NAME
 
1258
*     cqueue_diff_projects() -- Diff old/new cluster queue usersets
 
1259
*
 
1260
*  SYNOPSIS
 
1261
*     void cqueue_diff_projects(const lListElem *new, const lListElem *old,
 
1262
*     lList **new_prj, lList **old_prj)
 
1263
*
 
1264
*  FUNCTION
 
1265
*     A diff new/old is made regarding cluster queue acl/xacl.
 
1266
*     Userset references are returned in new_acl/old_acl.
 
1267
*
 
1268
*  INPUTS
 
1269
*     const lListElem *new - New cluster queue (CQ_Type)
 
1270
*     const lListElem *old - Old cluster queue (CQ_Type)
 
1271
*     lList **new_acl      - New userset references (US_Type)
 
1272
*     lList **old_acl      - Old userset references (US_Type)
 
1273
*
 
1274
*  NOTES
 
1275
*     MT-NOTE: cqueue_diff_usersets() is MT safe
 
1276
*******************************************************************************/
 
1277
void cqueue_diff_usersets(const lListElem *new,
 
1278
      const lListElem *old, lList **new_acl, lList **old_acl)
 
1279
{
 
1280
   cqueue_diff_sublist(new, old, CQ_acl, CQ_xacl,
 
1281
         AUSRLIST_value, US_name, US_Type, new_acl, old_acl);
 
1282
   lDiffListStr(US_name, new_acl, old_acl);
 
1283
}
 
1284
 
 
1285
 
 
1286
/****** sge_cqueue_qmaster/cqueue_update_categories() **************************
 
1287
*  NAME
 
1288
*     cqueue_update_categories() -- Update categories wrts userset/project
 
1289
*
 
1290
*  SYNOPSIS
 
1291
*     static void cqueue_update_categories(const lListElem *new_cq, const
 
1292
*     lListElem *old_cq)
 
1293
*
 
1294
*  FUNCTION
 
1295
*     The userset/project information wrts categories is updated based
 
1296
*     on new/old cluster queue configuration and events are sent upon
 
1297
*     changes.
 
1298
*
 
1299
*  INPUTS
 
1300
*     const lListElem *new_cq - New cluster queue (CQ_Type)
 
1301
*     const lListElem *old_cq - Old cluster queue (CQ_Type)
 
1302
*
 
1303
*  NOTES
 
1304
*     MT-NOTE: cqueue_update_categories() is not MT safe
 
1305
*******************************************************************************/
 
1306
static void cqueue_update_categories(const lListElem *new_cq, const lListElem *old_cq)
 
1307
{
 
1308
   lList *old = NULL, *new = NULL;
 
1309
 
 
1310
   cqueue_diff_projects(new_cq, old_cq, &new, &old);
 
1311
   project_update_categories(new, old);
 
1312
   lFreeList(&old);
 
1313
   lFreeList(&new);
 
1314
 
 
1315
   cqueue_diff_usersets(new_cq, old_cq, &new, &old);
 
1316
   userset_update_categories(new, old);
 
1317
   lFreeList(&old);
 
1318
   lFreeList(&new);
 
1319
}
 
1320
 
 
1321
/****** sgeobj/qinstance/qinstance_check_unknown_state() **********************
 
1322
*  NAME
 
1323
*     qinstance_check_unknown_state() -- Modifies the number of used slots 
 
1324
*
 
1325
*  SYNOPSIS
 
1326
*     void
 
1327
*     qinstance_check_unknown_state(lListElem *this_elem)
 
1328
*
 
1329
*  FUNCTION
 
1330
*     Checks if there are nonstatic load values available for the
 
1331
*     qinstance. If this is the case, then then the "unknown" state 
 
1332
*     of that machine will be released. 
 
1333
*
 
1334
*  INPUTS
 
1335
*     lListElem *this_elem - QU_Type 
 
1336
*
 
1337
*  RESULT
 
1338
*     void - NONE 
 
1339
*
 
1340
*  NOTES
 
1341
*     MT-NOTE: qinstance_check_unknown_state() is MT safe 
 
1342
*******************************************************************************/
 
1343
static void
 
1344
qinstance_check_unknown_state(lListElem *this_elem, lList *master_exechost_list)
 
1345
{
 
1346
   const char *hostname = NULL;
 
1347
   lListElem *host = NULL;
 
1348
 
 
1349
   DENTER(TOP_LAYER, "qinstance_check_unknown_state");
 
1350
   hostname = lGetHost(this_elem, QU_qhostname);
 
1351
   host = host_list_locate(master_exechost_list, hostname);
 
1352
   if (host != NULL) {
 
1353
      u_long32 last_heard = lGetUlong(host, EH_lt_heard_from);
 
1354
 
 
1355
      if (last_heard != 0) {
 
1356
         sge_qmaster_qinstance_state_set_unknown(this_elem, false);
 
1357
      }
 
1358
   }
 
1359
   DRETURN_VOID;
 
1360
}