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

« back to all changes in this revision

Viewing changes to source/libs/sgeobj/sge_attr.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 <math.h>
 
34
#include <string.h>
 
35
#include <sys/types.h>
 
36
 
 
37
#include "basis_types.h"
 
38
#include "sgermon.h" 
 
39
#include "sge_string.h"
 
40
#include "sge_str.h"
 
41
#include "sge_log.h"
 
42
#include "sge_answer.h"
 
43
#include "sge_hostname.h"
 
44
#include "sge_attr.h"
 
45
#include "sge_href.h"
 
46
#include "sge_hgroup.h"
 
47
#include "sge_object.h"
 
48
#include "sge_stdlib.h"
 
49
#include "commlib.h"
 
50
 
 
51
#include "msg_common.h"
 
52
#include "msg_sgeobjlib.h"
 
53
 
 
54
#define HOSTATTR_LAYER BASIS_LAYER
 
55
 
 
56
#define TEMPLATE_ATTR_IMPL(PREFIX, TYPE, INTERNAL_TYPE,                       \
 
57
                           DESCRIPTOR, HREF_NM, VALUE_NM)                     \
 
58
                                                                              \
 
59
lListElem *                                                                   \
 
60
PREFIX##_create(lList **answer_list, const char *href, TYPE value)            \
 
61
{                                                                             \
 
62
   return attr_create(answer_list, href, &value,                              \
 
63
                      DESCRIPTOR, HREF_NM, VALUE_NM);                         \
 
64
}                                                                             \
 
65
                                                                              \
 
66
lListElem *                                                                   \
 
67
PREFIX##_list_find(const lList *this_list, const char *href)                  \
 
68
{                                                                             \
 
69
   return lGetElemHost(this_list, HREF_NM, href);                             \
 
70
}                                                                             \
 
71
                                                                              \
 
72
bool                                                                          \
 
73
PREFIX##_list_add(lList **this_list, lList **answer_list, lListElem **attr,   \
 
74
                  int flags, lList **ambiguous_href_list)                     \
 
75
{                                                                             \
 
76
   return attr_list_add(this_list, answer_list, attr, flags,                  \
 
77
                        ambiguous_href_list,                                  \
 
78
                        DESCRIPTOR, HREF_NM, VALUE_NM);                       \
 
79
}                                                                             \
 
80
                                                                              \
 
81
bool                                                                          \
 
82
PREFIX##_list_add_set_del(lList **this_list, lList **answer_list,             \
 
83
                         const char *hostname, void *value, bool remove)      \
 
84
{                                                                             \
 
85
   return attr_list_add_set_del(this_list, answer_list, hostname,             \
 
86
                        value, remove, DESCRIPTOR, HREF_NM, VALUE_NM);        \
 
87
}                                                                             \
 
88
                                                                              \
 
89
bool                                                                          \
 
90
PREFIX##_list_find_value(const lList *this_list, lList **answer_list,         \
 
91
                         const char *hostname, INTERNAL_TYPE *value,          \
 
92
                         const char **mastching_host_or_group,                \
 
93
                         const char **matching_group,                         \
 
94
                         bool *is_ambiguous)                                  \
 
95
{                                                                             \
 
96
   return attr_list_find_value(this_list, answer_list, hostname,              \
 
97
                               value, mastching_host_or_group,                \
 
98
                               matching_group, is_ambiguous,                  \
 
99
                               DESCRIPTOR, HREF_NM, VALUE_NM);                \
 
100
}                                                                             \
 
101
                                                                              \
 
102
bool                                                                          \
 
103
PREFIX##_list_find_value_href(const lList *this_list, lList **answer_list,    \
 
104
                         const char *hostname, INTERNAL_TYPE *value,          \
 
105
                         bool *found)                                         \
 
106
{                                                                             \
 
107
   return attr_list_find_value_href(this_list, answer_list, hostname,         \
 
108
                               value, found, DESCRIPTOR, HREF_NM,             \
 
109
                               VALUE_NM);                                     \
 
110
}                                                                             \
 
111
                                                                              \
 
112
bool                                                                          \
 
113
PREFIX##_list_append_to_dstring(const lList *this_list, dstring *string)      \
 
114
{                                                                             \
 
115
   return attr_list_append_to_dstring(this_list, string,                      \
 
116
                                      DESCRIPTOR, HREF_NM, VALUE_NM);         \
 
117
}                                                                             \
 
118
                                                                              \
 
119
bool                                                                          \
 
120
PREFIX##_list_parse_from_string(lList **this_list, lList **answer_list,       \
 
121
                                const char *string, int flags)                \
 
122
{                                                                             \
 
123
   return attr_list_parse_from_string(this_list, answer_list, string,         \
 
124
                                      flags, DESCRIPTOR, HREF_NM, VALUE_NM);  \
 
125
}                                                                             \
 
126
                                                                              \
 
127
lListElem *                                                                   \
 
128
PREFIX##_list_locate(const lList *this_list, const char *host_or_group)       \
 
129
{                                                                             \
 
130
   return attr_list_locate(this_list, host_or_group, HREF_NM);                \
 
131
}                                                                             
 
132
 
 
133
static lListElem *
 
134
attr_create(lList **answer_list, const char *href, void *value,
 
135
            const lDescr *descriptor, int href_nm, int value_nm);
 
136
 
 
137
static bool 
 
138
attr_list_add(lList **this_list, lList **answer_list, lListElem **attr, 
 
139
              int flags, lList **ambiguous_href_list,
 
140
              const lDescr *descriptor, int href_nm, int value_nm);
 
141
 
 
142
static bool 
 
143
attr_list_add_set_del(lList **this_list, lList **answer_list, 
 
144
              const char *hostname, void *value_buffer, bool remove,
 
145
              const lDescr *descriptor, int href_nm, int value_nm);
 
146
 
 
147
static bool
 
148
attr_list_find_value(const lList *this_list, lList **answer_list, 
 
149
                     const char *hostname, void *value_buffer, 
 
150
                     const char **matching_host_or_group,
 
151
                     const char **matching_group,
 
152
                     bool *is_ambiguous, const lDescr *descriptor, 
 
153
                     int href_nm, int value_nm);
 
154
 
 
155
static bool
 
156
attr_list_find_value_href(const lList *this_list, lList **answer_list, 
 
157
                     const char *hostname, void *value_buffer, 
 
158
                     bool *found, const lDescr *descriptor, 
 
159
                     int href_nm, int value_nm);
 
160
 
 
161
static bool
 
162
attr_list_parse_from_string(lList **this_list, lList **answer_list,
 
163
                            const char *string, int flags,
 
164
                            const lDescr *descriptor, int href_nm, 
 
165
                            int value_nm);
 
166
 
 
167
static lListElem *
 
168
attr_list_locate(const lList *this_list, const char *host_or_group, 
 
169
                 int href_nm);
 
170
 
 
171
/****** sgeobj/attr/attr_create() *********************************************
 
172
*  NAME
 
173
*     attr_create() -- Returns a new attribute element 
 
174
*
 
175
*  SYNOPSIS
 
176
*     static lListElem *
 
177
*     attr_create(lList **answer_list, const char *href, void *value, 
 
178
*                 const lDescr *descriptor, int href_nm, int value_nm) 
 
179
*
 
180
*  FUNCTION
 
181
*     If an error occures "answer_list" will be filled with an error
 
182
*     message. "href" is the hostname or hgroupname of the new element.
 
183
*     "value" is a pointer to the new value for that attribute. "descriptor"
 
184
*     is the CULL descriptor wich will be used to create the new element.
 
185
*     "href_nm" is the CULL name of the field where the "href" name will
 
186
*     be stored and "value_nm" defines the value of the field which 
 
187
*     will be filled with the "value".
 
188
*
 
189
*  INPUTS
 
190
*     lList **answer_list      - AN_Type list 
 
191
*     const char *href         - host oder hgroupname 
 
192
*     void *value              - pointer to the attributes value 
 
193
*     const lDescr *descriptor - CULL descriptor 
 
194
*     int href_nm              - CULL field name host or hgroupname
 
195
*     int value_nm             - CULL field name for the value 
 
196
*
 
197
*  RESULT
 
198
*     lListElem * - new CULL element or NULL in case on an error
 
199
*
 
200
*  NOTES
 
201
*     There are typesafe versions of this function. Have a look into 
 
202
*     the headerfile and look for TEMPLATE_ATTR_PROTO. These macro
 
203
*     creates the typesafe versions. E.g.
 
204
*
 
205
*        str_attr_create()
 
206
*        ulng_attr_create()
 
207
*        bool_attr_create()
 
208
*        ...
 
209
*        strlist_attr_create()
 
210
*
 
211
*     MT-NOTE: attr_create() is MT safe 
 
212
******************************************************************************/
 
213
static lListElem *
 
214
attr_create(lList **answer_list, const char *href, void *value,
 
215
            const lDescr *descriptor, int href_nm, int value_nm)
 
216
{
 
217
   lListElem *ret = NULL;
 
218
 
 
219
   DENTER(HOSTATTR_LAYER, "attr_create");
 
220
   if (href != NULL) {
 
221
      lListElem *new_attr = lCreateElem(descriptor);
 
222
 
 
223
      if (new_attr != NULL) {
 
224
         lSetHost(new_attr, href_nm, href);
 
225
         if (value != NULL) {
 
226
            object_set_any_type(new_attr, value_nm, value);
 
227
         }
 
228
         ret = new_attr;
 
229
      } else {
 
230
         SGE_ADD_MSG_ID(sprintf(SGE_EVENT, MSG_ATTR_NONEWATTRSETTING_S, href));
 
231
         answer_list_add(answer_list, SGE_EVENT, 
 
232
                         STATUS_ERROR1, ANSWER_QUALITY_ERROR);
 
233
      }
 
234
   } else {
 
235
      SGE_ADD_MSG_ID(sprintf(SGE_EVENT, MSG_INAVLID_PARAMETER_IN_S, SGE_FUNC));
 
236
      answer_list_add(answer_list, SGE_EVENT, 
 
237
                      STATUS_ERROR1, ANSWER_QUALITY_ERROR);
 
238
   }
 
239
   DEXIT;
 
240
   return ret;
 
241
}
 
242
 
 
243
/****** sgeobj/attr/attr_list_add() *******************************************
 
244
*  NAME
 
245
*     attr_list_add() -- Add a new attribute entry to a list 
 
246
*
 
247
*  SYNOPSIS
 
248
*     static bool 
 
249
*     attr_list_add(lList **this_list, lList **answer_list, lListElem **attr, 
 
250
*                   int flags, lList **ambiguous_href_list, 
 
251
*                   const lDescr *descriptor, int href_nm, int value_nm) 
 
252
*
 
253
*  FUNCTION
 
254
*     "this_list" and "attr" must have the same "descriptor". "href_nm"
 
255
*     defines one cull field within "attr" which containes a hostname 
 
256
*     or hgroup-name. "value_nm" containes the value of that concerned 
 
257
*     attribute.
 
258
*     "answer_list" will be filled in case of an error.
 
259
*     "flags" can be used to influence the behaviour of this function
 
260
*     in case of duplicates or other ambiguities within the resulting
 
261
*     list.
 
262
*     "ambiguous_href_list" might be used as output parameter for this
 
263
*     function. Find more detailes in the description of the flags
 
264
*     parameter below.
 
265
*
 
266
*  INPUTS
 
267
*     lList **this_list           - attribute list 
 
268
*     lList **answer_list         - AN_Type list 
 
269
*     lListElem **attr            - attribute pointer 
 
270
*     int flags                   - behaviour bitmask
 
271
*
 
272
*        HOSTATTR_OVERWRITE - If there is already an element in "this_list"
 
273
*           which has the same hostname or hgroup, then the value of this
 
274
*           element will be overwritten if this flag is set. 
 
275
*           If this flag is not given and the function should add a
 
276
*           duplicate, then this will be counted as function error.
 
277
*
 
278
*        HOSTATTR_ALLOW_AMBIGUITY - If the resulting "this_list" would 
 
279
*           result in an ambigous configuration for a ceratin host then 
 
280
*           this is allowed if the flag is given. Otherwise it will
 
281
*           be rejected. In that case "ambiguous_href_list" will be
 
282
*           filled with the conflicting hostnames.
 
283
*
 
284
*     lList **ambiguous_href_list - HR_Type list 
 
285
*     const lDescr *descriptor    - CULL descriptor 
 
286
*     int href_nm                 - CULL field name 
 
287
*     int value_nm                - CULL value name 
 
288
*
 
289
*  RESULT
 
290
*     static bool - error state
 
291
*        true  - success
 
292
*        false - error
 
293
*
 
294
*  NOTES
 
295
*     MT-NOTE: attr_list_add() is not MT safe 
 
296
*******************************************************************************/
 
297
static bool 
 
298
attr_list_add(lList **this_list, lList **answer_list, lListElem **attr, 
 
299
              int flags, lList **ambiguous_href_list,
 
300
              const lDescr *descriptor, int href_nm, int value_nm)
 
301
{
 
302
   bool ret = false;
 
303
 
 
304
   DENTER(HOSTATTR_LAYER, "attr_list_add");
 
305
 
 
306
   if (this_list != NULL && attr != NULL && *attr != NULL) {
 
307
      lListElem *attr_elem = NULL; 
 
308
      const char *href = NULL;
 
309
      bool is_hgroup = false; 
 
310
      bool created_list = false;
 
311
 
 
312
      href = lGetHost(*attr, href_nm);
 
313
      is_hgroup = is_hgroup_name(href);
 
314
 
 
315
      if (*this_list == NULL) {
 
316
         *this_list = lCreateList("", descriptor);
 
317
         created_list = true;
 
318
      } else {
 
319
         attr_elem = attr_list_locate(*this_list, href, href_nm);
 
320
      }
 
321
 
 
322
      /*
 
323
       * HOSTREF_DEFAULT and host reference values can be added/changed
 
324
       * Hostgroup entries already contained in the list might be changed.
 
325
`      *
 
326
       * New hostgroup references might cause a conflict. We have to
 
327
       * make additional checks.
 
328
       */
 
329
      if (!strcmp(href, HOSTREF_DEFAULT) || 
 
330
          !is_hgroup ||
 
331
          (is_hgroup && attr_elem != NULL)) {
 
332
         const char *value = NULL; 
 
333
 
 
334
         object_get_any_type(*attr, value_nm, &value);
 
335
         if (attr_elem != NULL) {
 
336
            if (flags & HOSTATTR_OVERWRITE) {
 
337
               object_set_any_type(attr_elem, value_nm, &value);
 
338
               lFreeElem(attr);
 
339
               *attr = attr_elem;
 
340
               ret = true;
 
341
            } else {
 
342
               SGE_ADD_MSG_ID(sprintf(SGE_EVENT, 
 
343
                              MSG_ATTR_VALUEMULDEFINED_S, href));
 
344
               answer_list_add(answer_list, SGE_EVENT,
 
345
                               STATUS_ERROR1, ANSWER_QUALITY_ERROR);
 
346
            }
 
347
         } else {
 
348
            lAppendElem(*this_list, *attr);
 
349
            ret = true;
 
350
         }
 
351
      } else {
 
352
         lList *href_list = NULL;
 
353
         lList *host_list = NULL;
 
354
         lList *new_host_list = NULL;
 
355
         bool lret = true;
 
356
       
 
357
         /*
 
358
          * Create list of ambiguous hosts only 
 
359
          *  - if ambiguious entries are not allowed or
 
360
          *  - if the the caller of this functions expects this
 
361
          *    function to return it
 
362
          */ 
 
363
         if (!(flags & HOSTATTR_ALLOW_AMBIGUITY) && 
 
364
             ambiguous_href_list != NULL) {
 
365
 
 
366
            /*
 
367
             * Create host reference list of all used hostgroups
 
368
             * (except HOSTREF_DEFAULT, and host entries)
 
369
             */
 
370
            if (lret) {
 
371
               for_each(attr_elem, *this_list) {
 
372
                  const char *href = lGetHost(attr_elem, ASTR_href); 
 
373
 
 
374
                  if (strcmp(href, HOSTREF_DEFAULT) && 
 
375
                      is_hgroup_name(href)) {
 
376
                     lret &= href_list_add(&href_list, NULL, href);
 
377
                  }
 
378
               }
 
379
            }
 
380
 
 
381
            /*
 
382
             * Find all directly or indirectly referenced hosts for all 
 
383
             * hostgroups
 
384
             */
 
385
            if (lret && href_list != NULL) {
 
386
               lList *master_list = *(hgroup_list_get_master_list());
 
387
               lList *tmp_href_list = NULL; 
 
388
 
 
389
               lret &= href_list_find_all_references(href_list, NULL, 
 
390
                                                     master_list, &host_list, 
 
391
                                                     NULL); 
 
392
               lret &= href_list_add(&tmp_href_list, NULL, href);
 
393
               lret &= href_list_find_all_references(tmp_href_list, NULL,
 
394
                                                     master_list, 
 
395
                                                     &new_host_list, NULL);
 
396
               lFreeList(&tmp_href_list);
 
397
            }
 
398
 
 
399
            /*
 
400
             * Find all host references which already have a value attached.
 
401
             * For all these hosts the new value in ambiguious.
 
402
             */
 
403
            if (lret && ambiguous_href_list != NULL && host_list != NULL &&
 
404
                new_host_list != NULL) { 
 
405
               lret = href_list_compare(new_host_list, NULL, host_list,
 
406
                                           NULL, NULL, ambiguous_href_list,
 
407
                                           NULL);
 
408
            }
 
409
         } 
 
410
 
 
411
         if (ambiguous_href_list != NULL &&
 
412
               lGetNumberOfElem(*ambiguous_href_list) >= 1 &&
 
413
               !(flags & HOSTATTR_ALLOW_AMBIGUITY)) {
 
414
            SGE_ADD_MSG_ID(sprintf(SGE_EVENT, MSG_ATTR_RESULTUNAMBIGUOUS_S));
 
415
            answer_list_add(answer_list, SGE_EVENT,
 
416
                            STATUS_ERROR1, ANSWER_QUALITY_ERROR);
 
417
         } else {
 
418
            lAppendElem(*this_list, *attr);
 
419
            ret = true;
 
420
         }
 
421
      }
 
422
 
 
423
      if (created_list == true && ret == false) {
 
424
         lFreeList(this_list);
 
425
      }
 
426
   } 
 
427
   DRETURN(ret);
 
428
}
 
429
 
 
430
/****** sgeobj/attr/attr_list_add_set_del() ***********************************
 
431
*  NAME
 
432
*     attr_list_add_set_del() -- add/replace/delete an attribute entry 
 
433
*
 
434
*  SYNOPSIS
 
435
*     static bool 
 
436
*     attr_list_add_set_del(lList **this_list, lList **answer_list, 
 
437
*                           const char *hostname, void *value, 
 
438
*                           bool remove, const lDescr *descriptor, 
 
439
*                           int href_nm, int value_nm) 
 
440
*
 
441
*  FUNCTION
 
442
*     This function can be used to remove an entry from "this_list"
 
443
*     or it can add a new entry or replace an existing one. Find a
 
444
*     more detailed description in sgeobj/attr/attr_create()
 
445
*
 
446
*  INPUTS
 
447
*     lList **this_list        - cull list of type "descriptor" 
 
448
*     lList **answer_list      - AN_Type list 
 
449
*     const char *hostname     - hostname or hgroup name 
 
450
*     void *value              - pointer to value 
 
451
*     bool remove              - true -> remove the element 
 
452
*     const lDescr *descriptor - CULL descriptor 
 
453
*     int href_nm              - CULL field name 
 
454
*     int value_nm             - CULL value name 
 
455
*
 
456
*  RESULT
 
457
*     static bool - error status
 
458
*        true  - success
 
459
*        false - error 
 
460
*
 
461
*  NOTES
 
462
*     MT-NOTE: attr_list_add_set_del() is MT safe 
 
463
*
 
464
*  SEE ALSO
 
465
*     sgeobj/attr/attr_create()
 
466
*******************************************************************************/
 
467
static bool 
 
468
attr_list_add_set_del(lList **this_list, lList **answer_list, 
 
469
              const char *hostname, void *value, bool remove,
 
470
              const lDescr *descriptor, 
 
471
              int href_nm, int value_nm)
 
472
{
 
473
   bool ret = true;
 
474
   lListElem *attr = NULL;
 
475
 
 
476
   if (this_list && *this_list) {
 
477
      if (remove) {
 
478
         attr = attr_list_locate(*this_list, hostname, href_nm);
 
479
         lRemoveElem(*this_list, &attr);
 
480
      } else {
 
481
         attr = attr_create(answer_list, hostname, value, descriptor, 
 
482
                            href_nm, value_nm);
 
483
         ret = attr_list_add(this_list, answer_list,
 
484
                             &attr, HOSTATTR_OVERWRITE, NULL,
 
485
                             descriptor, href_nm, value_nm);
 
486
      }
 
487
   }
 
488
   return ret;
 
489
}
 
490
 
 
491
/*
 
492
descriptor        ASTR_Type
 
493
href_nm           ASTR_href
 
494
value_nm          ASTR_value
 
495
*/
 
496
static bool
 
497
attr_list_find_value(const lList *this_list, lList **answer_list, 
 
498
                     const char *hostname, void *value_buffer,
 
499
                     const char **matching_host_or_group,
 
500
                     const char **matching_group,
 
501
                     bool *is_ambiguous, const lDescr *descriptor, 
 
502
                     int href_nm, int value_nm)
 
503
{
 
504
   bool ret = false;
 
505
 
 
506
   DENTER(HOSTATTR_LAYER, "attr_list_find_value");
 
507
 
 
508
   if (this_list != NULL && hostname != NULL) {
 
509
      lListElem *href = NULL;
 
510
   
 
511
      /*
 
512
       * Try to find a value for the concerned host
 
513
       */ 
 
514
      href = attr_list_locate(this_list, hostname, href_nm);
 
515
      if (href != NULL) {  
 
516
         object_get_any_type(href, value_nm, value_buffer);
 
517
         DPRINTF(("Found value for host "SFQ"\n", hostname));
 
518
         ret = true;
 
519
      } else {
 
520
         bool already_found = false;
 
521
 
 
522
         *is_ambiguous = false;
 
523
         /*
 
524
          * Try to find a value for all hgroup definitions
 
525
          * if there was no host related value
 
526
          *
 
527
          * Exit the loop as soon as possible! This will be the case if
 
528
          * an ambiguous value for the concerned host will be found.
 
529
          */
 
530
         for_each(href, this_list) {
 
531
            const char *href_name = lGetHost(href, href_nm);
 
532
            lList *master_list = *(hgroup_list_get_master_list());
 
533
            bool lret = true;
 
534
 
 
535
            if (strcmp(href_name, HOSTREF_DEFAULT) && 
 
536
                is_hgroup_name(href_name)) {
 
537
               lList *tmp_href_list = NULL;
 
538
               lListElem *tmp_href = NULL;
 
539
               lList *host_list = NULL;
 
540
 
 
541
               href_list_add(&tmp_href_list, NULL, href_name);
 
542
               lret &= href_list_find_all_references(tmp_href_list, NULL,
 
543
                                                     master_list, &host_list,
 
544
                                                     NULL); 
 
545
               tmp_href = href_list_locate(host_list, hostname);
 
546
               if (tmp_href != NULL) {
 
547
                  if (already_found == false) {
 
548
                     already_found = true;
 
549
                     object_get_any_type(href, value_nm, value_buffer);
 
550
                     *matching_host_or_group = href_name;
 
551
                     DPRINTF(("Found value for domain "SFQ"\n", href_name));
 
552
                     ret = true;
 
553
                  } else {
 
554
                     *is_ambiguous = true;
 
555
                     *matching_group = href_name;
 
556
                     DPRINTF(("Found ambiguous value in domain "SFQ"\n", 
 
557
                               href_name));
 
558
                     ret = false;
 
559
                     lFreeList(&host_list);
 
560
                     lFreeList(&tmp_href_list);
 
561
                     break; /* leave for_each loop */
 
562
                  }
 
563
               }
 
564
               lFreeList(&host_list);
 
565
               lFreeList(&tmp_href_list);
 
566
            }
 
567
         }
 
568
         if (ret == false) {
 
569
            lListElem *tmp_href = NULL;
 
570
 
 
571
            /*
 
572
             * Use the default value
 
573
             */
 
574
            tmp_href = attr_list_locate(this_list, HOSTREF_DEFAULT, href_nm);
 
575
            if (tmp_href != NULL) {
 
576
               DPRINTF(("Using default value\n"));
 
577
               object_get_any_type(tmp_href, value_nm, value_buffer);
 
578
               ret = true;
 
579
            } else {
 
580
               /*
 
581
                * Should never happen.
 
582
                */
 
583
               SGE_ADD_MSG_ID(sprintf(SGE_EVENT, MSG_ATTR_NOCONFVALUE));
 
584
               answer_list_add(answer_list, SGE_EVENT,
 
585
                               STATUS_ERROR1, ANSWER_QUALITY_ERROR);            
 
586
            }
 
587
         }
 
588
      }
 
589
      if (ret) {
 
590
         DTRACE;
 
591
      }
 
592
   }
 
593
   DEXIT;
 
594
   return ret;
 
595
}
 
596
 
 
597
/*
 
598
descriptor        ASTR_Type
 
599
href_nm           ASTR_href
 
600
value_nm          ASTR_value
 
601
*/
 
602
static bool
 
603
attr_list_find_value_href(const lList *this_list, lList **answer_list, 
 
604
                     const char *hostname, void *value_buffer,
 
605
                     bool *found, const lDescr *descriptor, 
 
606
                     int href_nm, int value_nm)
 
607
{
 
608
   bool ret = false;
 
609
 
 
610
   DENTER(HOSTATTR_LAYER, "attr_list_find_value");
 
611
 
 
612
   if (this_list != NULL && hostname != NULL) {
 
613
      lListElem *href = NULL;
 
614
   
 
615
      /*
 
616
       * Try to find a value for the concerned host
 
617
       */ 
 
618
      href = attr_list_locate(this_list, hostname, href_nm);
 
619
      if (href != NULL) {  
 
620
         object_get_any_type(href, value_nm, value_buffer);
 
621
         *found = true;
 
622
         DTRACE;
 
623
         ret = true;
 
624
      } else {
 
625
         lListElem *tmp_href = NULL;
 
626
 
 
627
         /*
 
628
          * Use the default value
 
629
          */
 
630
         tmp_href = attr_list_locate(this_list, HOSTREF_DEFAULT, href_nm);
 
631
         if (tmp_href != NULL) {
 
632
            object_get_any_type(tmp_href, value_nm, value_buffer);
 
633
            *found = false;
 
634
            DTRACE;
 
635
            ret = true;
 
636
         } else {
 
637
            /*
 
638
             * Should never happen.
 
639
             */
 
640
            SGE_ADD_MSG_ID(sprintf(SGE_EVENT, MSG_ATTR_NOCONFVALUE));
 
641
            answer_list_add(answer_list, SGE_EVENT,
 
642
                            STATUS_ERROR1, ANSWER_QUALITY_ERROR);            
 
643
         }
 
644
      }
 
645
   }
 
646
   DRETURN(ret);
 
647
}
 
648
 
 
649
/*
 
650
descriptor        ASTR_Type
 
651
href_nm           ASTR_href
 
652
value_nm          ASTR_value
 
653
*/
 
654
bool
 
655
attr_list_append_to_dstring(const lList *this_list, dstring *string,
 
656
                            const lDescr *descriptor, int href_nm, int value_nm)
 
657
{
 
658
   bool found_default = false;
 
659
   bool found_group = false;
 
660
   bool found_host = false;
 
661
   lListElem *attr = NULL;
 
662
   dstring host_string = DSTRING_INIT;
 
663
 
 
664
   DENTER(HOSTATTR_LAYER, "attr_list_append_to_dstring");
 
665
 
 
666
   if ((attr = attr_list_locate(this_list, HOSTREF_DEFAULT, href_nm)) != NULL) {
 
667
      found_default = true;
 
668
      object_append_field_to_dstring(attr, NULL, string, value_nm,
 
669
                                     '\0');
 
670
   }
 
671
   
 
672
   for_each(attr, this_list) {
 
673
      const char *href;
 
674
 
 
675
      href = lGetHost(attr, href_nm);
 
676
 
 
677
      if (href == NULL || (found_default && !strcmp(href, HOSTREF_DEFAULT))) {
 
678
         continue;
 
679
      } else {
 
680
         dstring *ds; /* will be reference to the corresponding dstring container */
 
681
        
 
682
         if (is_hgroup_name(href)) {
 
683
            ds = string;
 
684
            if (found_group || found_default) {
 
685
               sge_dstring_append_char(ds, ',');
 
686
            }
 
687
            found_group = true;
 
688
         } else {
 
689
            ds = &host_string;
 
690
            if (found_host) {
 
691
               sge_dstring_append_char(ds, ',');
 
692
            }
 
693
            found_host = true;
 
694
         }
 
695
 
 
696
         sge_dstring_append_char(ds, '[');
 
697
         sge_dstring_append(ds, href);
 
698
         sge_dstring_append_char(ds, '=');
 
699
         object_append_field_to_dstring(attr, NULL, ds, value_nm, 
 
700
                                        '\0');
 
701
         sge_dstring_append_char(ds, ']');
 
702
      }
 
703
   }
 
704
   if (found_host) {
 
705
      if (found_default || found_group) {
 
706
         sge_dstring_append_char(string, ',');
 
707
      }
 
708
      sge_dstring_append_dstring(string, &host_string);
 
709
   }
 
710
   if (!found_default && !found_group && !found_host) {
 
711
      sge_dstring_append(string, "NONE");
 
712
   }
 
713
   sge_dstring_free(&host_string);
 
714
   DRETURN(true);
 
715
}
 
716
 
 
717
/*
 
718
descriptor        ASTR_Type
 
719
href_nm           ASTR_href
 
720
value_nm          ASTR_value
 
721
*/
 
722
static bool
 
723
attr_list_parse_from_string(lList **this_list, lList **answer_list,
 
724
                            const char *string, int flags,
 
725
                            const lDescr *descriptor, int href_nm, 
 
726
                            int value_nm)
 
727
{
 
728
   bool ret = true;
 
729
   DENTER(TOP_LAYER, "attr_list_parse_from_string");
 
730
  
 
731
   if (this_list != NULL && string != NULL) { 
 
732
      struct saved_vars_s *strtok_context = NULL;
 
733
      char *token = NULL;
 
734
      char *next_token = NULL;
 
735
      bool is_first_token = true;
 
736
      bool is_last_token = false;
 
737
 
 
738
      /* 
 
739
       * start         := value {',' group_value} .
 
740
       * group_value   := '[' group_or_host '=' value ']' . 
 
741
       * group_or_host := ['@'] name .
 
742
       * value         := <depends on listtype>
 
743
       * 
 
744
       * example: lic=5,fast=1,[@group=lic=4,fast=0],[b=lic=0] 
 
745
       *
 
746
       * lic=5,fast=1, 
 
747
       * @group=lic=4,fast=0], 
 
748
       * b=lic=0]
 
749
       * 
 
750
       * lic=5,fast=1
 
751
       * @group=lic=4,fast=0
 
752
       * b=lic=0
 
753
       *
 
754
       * default  lic=5,fast=1
 
755
       * @group   lic=4,fast=0
 
756
       * b        lic=0
 
757
       * 
 
758
       */
 
759
 
 
760
      next_token = sge_strtok_r(string, "[", &strtok_context);
 
761
      while (ret && (token = next_token)) {
 
762
         size_t length; 
 
763
 
 
764
         next_token = sge_strtok_r(NULL, "[", &strtok_context);
 
765
         if (next_token == NULL) {
 
766
            is_last_token = true;
 
767
         }
 
768
 
 
769
         /*
 
770
          * There might be white space at the end of each token.
 
771
          */
 
772
         sge_strip_white_space_at_eol(token);
 
773
         length = strlen(token);
 
774
 
 
775
         if (length >= 1) {
 
776
            const char *href_name = NULL;
 
777
            char *value = NULL;
 
778
            bool first_is_default = true;
 
779
  
 
780
            /* 
 
781
             * All except the last token has to conatin a ',' as last
 
782
             * character in the string. This ',' has to be removed.
 
783
             */
 
784
            if (ret && !is_last_token) {
 
785
               if (token[length - 1] == ',') {
 
786
                  token[length - 1] = '\0';
 
787
                  length--;
 
788
               } else {
 
789
                  SGE_ADD_MSG_ID(sprintf(SGE_EVENT, MSG_ATTR_MISSINGCOMMA_S,
 
790
                                         string));
 
791
                  answer_list_add(answer_list, SGE_EVENT,
 
792
                                  STATUS_ERROR1, ANSWER_QUALITY_ERROR);
 
793
                  ret = false;
 
794
               }
 
795
            }
 
796
            else if (ret && is_last_token && (token[length - 1] == ',')) {
 
797
               SGE_ADD_MSG_ID(sprintf(SGE_EVENT, MSG_ATTR_TRAILINGCOMMA_S,
 
798
                                      string));
 
799
               answer_list_add(answer_list, SGE_EVENT,
 
800
                               STATUS_ERROR1, ANSWER_QUALITY_ERROR);
 
801
               ret = false;
 
802
            }
 
803
 
 
804
            /*
 
805
             * There might be space after a closing brace ']'
 
806
             */
 
807
            sge_strip_white_space_at_eol(token);
 
808
            length = strlen(token);
 
809
 
 
810
            /* 
 
811
             * All except the first token has to end with a ']'. Also
 
812
             * this charcter has to be removed.
 
813
             */
 
814
            if (ret && !is_first_token) {
 
815
               if (token[length - 1] == ']') {
 
816
                  token[length - 1] = '\0';
 
817
                  length--;
 
818
               } else {
 
819
                  SGE_ADD_MSG_ID(sprintf(SGE_EVENT, MSG_ATTR_MISSINGBRACKET_S,
 
820
                                         string));
 
821
                  answer_list_add(answer_list, SGE_EVENT,
 
822
                                  STATUS_ERROR1, ANSWER_QUALITY_ERROR);
 
823
                  ret = false;
 
824
               }
 
825
            }
 
826
 
 
827
            /*
 
828
             * If the first token containes a ']' as last charcter than
 
829
             * a default value is missing! This is not a error but
 
830
             * we have to parse a group or host additionally
 
831
             */ 
 
832
            if (ret && is_first_token) {
 
833
               if (token[length - 1] == ']') {
 
834
                  token[length - 1] = '\0';
 
835
                  length--;
 
836
                  first_is_default = false;
 
837
               } 
 
838
            }
 
839
 
 
840
            /*
 
841
             * All but the first token has to contain a hostgroup
 
842
             * or a host reference in the beginning of the string 
 
843
             */
 
844
            if (ret) {
 
845
               if (!is_first_token || !first_is_default) {
 
846
                  value = strchr(token, '=');
 
847
                  href_name = token;
 
848
 
 
849
                  if (value != NULL) {
 
850
                     value[0] = '\0';
 
851
                     value++;
 
852
                  } else {
 
853
                     SGE_ADD_MSG_ID(sprintf(SGE_EVENT, 
 
854
                                            MSG_ATTR_EQUALSIGNEXPRECTED));
 
855
                     answer_list_add(answer_list, SGE_EVENT,
 
856
                                     STATUS_ERROR1, ANSWER_QUALITY_ERROR);
 
857
                     ret = false;
 
858
                  }
 
859
               } else {
 
860
                  href_name = HOSTREF_DEFAULT;
 
861
                  value = token;
 
862
               }
 
863
            }
 
864
 
 
865
            /*
 
866
             * Parsing the token was successfull. We can create a new 
 
867
             * element.
 
868
             */
 
869
            if (ret) {
 
870
               lListElem *attr_elem = NULL;
 
871
     
 
872
               attr_elem = attr_create(answer_list, href_name, NULL,
 
873
                                       descriptor, href_nm, value_nm);
 
874
               if (attr_elem != NULL) {
 
875
                  ret &= object_parse_field_from_string(attr_elem, 
 
876
                                                        answer_list,
 
877
                                                        value_nm, value);
 
878
                  if (ret) {
 
879
                     ret &= attr_list_add(this_list, answer_list,
 
880
                                          &attr_elem, flags, NULL,
 
881
                                          descriptor, href_nm, value_nm);
 
882
                  } else {
 
883
                     SGE_ADD_MSG_ID(sprintf(SGE_EVENT, 
 
884
                                    MSG_ATTR_PARSINGERROR_S, value));
 
885
                     answer_list_add(answer_list, SGE_EVENT,
 
886
                                     STATUS_ERROR1, ANSWER_QUALITY_ERROR);
 
887
                  }
 
888
                  if (!ret) {
 
889
                     lFreeElem(&attr_elem);
 
890
                  }
 
891
               } else {
 
892
                  ret = false;
 
893
               }
 
894
            }
 
895
         } else {
 
896
            SGE_ADD_MSG_ID(sprintf(SGE_EVENT, MSG_ATTR_NOVALUEGIVEN));
 
897
            answer_list_add(answer_list, SGE_EVENT,
 
898
                            STATUS_ERROR1, ANSWER_QUALITY_ERROR);
 
899
            ret = false;
 
900
         }
 
901
         is_first_token = false;
 
902
      } 
 
903
      sge_free_saved_vars(strtok_context);
 
904
      strtok_context = NULL;
 
905
   } else {
 
906
      SGE_ADD_MSG_ID(sprintf(SGE_EVENT, MSG_INAVLID_PARAMETER_IN_S, SGE_FUNC));
 
907
      answer_list_add(answer_list, SGE_EVENT, 
 
908
                      STATUS_ERROR1, ANSWER_QUALITY_ERROR);
 
909
      ret = false;
 
910
   } 
 
911
 
 
912
   DEXIT;
 
913
   return ret;
 
914
}
 
915
 
 
916
/*
 
917
href_nm           ASTR_href
 
918
*/
 
919
static lListElem *
 
920
attr_list_locate(const lList *this_list, const char *host_or_group, int href_nm)
 
921
{
 
922
   lListElem *ret = NULL;
 
923
 
 
924
   DENTER(HOSTATTR_LAYER, "attr_list_locate");
 
925
   if (this_list != NULL && host_or_group != NULL) {
 
926
      ret = lGetElemHost(this_list, href_nm, host_or_group);
 
927
   }
 
928
   DEXIT;
 
929
   return ret; 
 
930
}
 
931
 
 
932
TEMPLATE_ATTR_IMPL(str_attr, const char *, const char *, ASTR_Type, ASTR_href, ASTR_value) 
 
933
 
 
934
TEMPLATE_ATTR_IMPL(ulng_attr, u_long32, u_long32, AULNG_Type, AULNG_href, AULNG_value) 
 
935
 
 
936
TEMPLATE_ATTR_IMPL(bool_attr, bool, bool, ABOOL_Type, ABOOL_href, ABOOL_value) 
 
937
 
 
938
TEMPLATE_ATTR_IMPL(time_attr, const char *, const char *, ATIME_Type, ATIME_href, ATIME_value) 
 
939
 
 
940
TEMPLATE_ATTR_IMPL(mem_attr, const char *, const char *, AMEM_Type, AMEM_href, AMEM_value) 
 
941
 
 
942
TEMPLATE_ATTR_IMPL(inter_attr, const char *, const char *, AINTER_Type, AINTER_href, AINTER_value) 
 
943
 
 
944
TEMPLATE_ATTR_IMPL(qtlist_attr, u_long32, u_long32, AQTLIST_Type, AQTLIST_href, AQTLIST_value) 
 
945
 
 
946
 
 
947
TEMPLATE_ATTR_IMPL(strlist_attr, const char *, lList *, ASTRLIST_Type, ASTRLIST_href, ASTRLIST_value) 
 
948
 
 
949
TEMPLATE_ATTR_IMPL(usrlist_attr, const char *, lList *, AUSRLIST_Type, AUSRLIST_href, AUSRLIST_value) 
 
950
 
 
951
TEMPLATE_ATTR_IMPL(prjlist_attr, const char *, lList *, APRJLIST_Type, APRJLIST_href, APRJLIST_value) 
 
952
 
 
953
TEMPLATE_ATTR_IMPL(celist_attr, const char *, lList *, ACELIST_Type, ACELIST_href, ACELIST_value) 
 
954
 
 
955
TEMPLATE_ATTR_IMPL(solist_attr, const char *, lList *, ASOLIST_Type, ASOLIST_href, ASOLIST_value) 
 
956
 
 
957