1
/*___INFO__MARK_BEGIN__*/
2
/*************************************************************************
4
* The Contents of this file are made available subject to the terms of
5
* the Sun Industry Standards Source License Version 1.2
7
* Sun Microsystems Inc., March, 2001
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
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.
24
* The Initial Developer of the Original Code is: Sun Microsystems, Inc.
26
* Copyright: 2001 by Sun Microsystems, Inc.
28
* All Rights Reserved.
30
************************************************************************/
31
/*___INFO__MARK_END__*/
40
#include "rmon/sgermon.h"
42
#include "comm/commlib.h"
44
#include "uti/sge_profiling.h"
45
#include "uti/setup_path.h"
46
#include "uti/sge_string.h"
47
#include "uti/sge_hostname.h"
48
#include "uti/sge_log.h"
49
#include "uti/sge_unistd.h"
50
#include "uti/sge_stdlib.h"
51
#include "uti/sge_prog.h"
52
#include "uti/sge_bootstrap.h"
53
#include "uti/sge_parse_num_par.h"
55
#include "sched/sort_hosts.h"
56
#include "sched/load_correction.h"
57
#include "sched/sge_complex_schedd.h"
58
#include "sched/sge_select_queue.h"
60
#include "sgeobj/parse.h"
61
#include "sgeobj/sge_schedd_conf.h"
62
#include "sgeobj/cull_parse_util.h"
63
#include "sgeobj/sge_conf.h"
64
#include "sgeobj/sge_range.h"
65
#include "sgeobj/sge_resource_quota.h"
66
#include "sgeobj/sge_hgroup.h"
67
#include "sgeobj/sge_userset.h"
68
#include "sgeobj/sge_host.h"
69
#include "sgeobj/sge_answer.h"
70
#include "sgeobj/sge_qinstance.h"
71
#include "sgeobj/sge_qinstance_state.h"
72
#include "sgeobj/sge_qinstance_type.h"
73
#include "sgeobj/sge_ulong.h"
74
#include "sgeobj/sge_centry.h"
75
#include "sgeobj/sge_feature.h"
76
#include "sgeobj/sge_all_listsL.h"
78
#include "gdi/sge_gdi.h"
79
#include "gdi/sge_gdi_ctx.h"
81
#include "basis_types.h"
82
#include "sig_handlers.h"
83
#include "qstat_printing.h"
84
#include "sge_mt_init.h"
85
#include "sge_qstat.h"
86
#include "sge_qquota.h"
89
#include "msg_common.h"
90
#include "msg_clients_common.h"
92
#define HEAD_FORMAT "%-18s %-20.20s %s\n"
102
static bool get_all_lists(sge_gdi_ctx_class_t *ctx, lList **rqs_l, lList **centry_l, lList **userset_l, lList **hgroup_l, lList **exechost_l, lList *hostref_list, lList **alpp);
104
static char *qquota_get_next_filter(stringT filter, const char *cp);
105
static bool qquota_print_out_rule(lListElem *rule, dstring rule_name, const char *limit_name,
106
const char *usage_value, const char *limit_value, qquota_filter_t filter,
107
lListElem *centry, report_handler_t* report_handler, lList *printed_rules, lList **alpp);
109
static bool qquota_print_out_filter(lListElem *filter, const char *name, const char *value, dstring *buffer, report_handler_t *report_handler, lList **alpp);
111
/****** qquota_output/qquota_output() ********************************************
113
* qquota_output() -- qquota output function
116
* bool qquota_output(void *ctx, lList *host_list, lList *resource_match_list,
117
* lList *user_list, lList *pe_list, lList *project_list, lList
118
* *cqueue_list, lList **alpp, report_handler_t* report_handler)
121
* print resource quota rule and the limit
124
* void *ctx - gdi handler
125
* lList *host_list - selected hosts
126
* lList *resource_match_list - selected resources
127
* lList *user_list - selected users
128
* lList *pe_list - selecte pes
129
* lList *project_list - selected projects
130
* lList *cqueue_list - selected cluster queues
131
* lList **alpp - answer list
132
* report_handler_t* report_handler - report handler for xml output
135
* bool - true on success
139
* MT-NOTE: qquota_output() is MT safe
141
*******************************************************************************/
142
bool qquota_output(sge_gdi_ctx_class_t *ctx, lList *host_list, lList *resource_match_list, lList *user_list,
143
lList *pe_list, lList *project_list, lList *cqueue_list, lList **alpp,
144
report_handler_t* report_handler)
146
lList *rqs_list = NULL;
147
lList *centry_list = NULL;
148
lList *userset_list = NULL;
149
lList *hgroup_list = NULL;
150
lList *exechost_list = NULL;
152
lListElem* global_host = NULL;
153
lListElem* exec_host = NULL;
154
lList* printed_rules = NULL; /* Hash list of already printed resource quota rules (possible with -u user1,user2,user3...) */
159
qquota_filter_t qquota_filter = { "*",
165
dstring rule_name = DSTRING_INIT;
167
DENTER(TOP_LAYER, "qquota_output");
169
/* If no user is requested on command line we set the current user as default */
170
qquota_filter.user = ctx->get_username(ctx);
172
ret = get_all_lists(ctx, &rqs_list, ¢ry_list, &userset_list, &hgroup_list, &exechost_list, host_list, alpp);
175
lListElem *rqs = NULL;
176
printed_rules = lCreateList("rule_hash", ST_Type);
177
global_host = host_list_locate(exechost_list, SGE_GLOBAL_NAME);
179
if (report_handler != NULL) {
180
xml_ret = report_handler->report_started(report_handler, alpp);
181
if (xml_ret != QQUOTA_SUCCESS) {
183
goto qquota_output_error;
187
for_each(rqs, rqs_list) {
188
lListElem *rule = NULL;
191
if (lGetBool(rqs, RQS_enabled) == false) {
195
for_each(rule, lGetList(rqs, RQS_rule)) {
196
lListElem *user_ep = lFirst(user_list);
197
lListElem *project_ep = lFirst(project_list);
198
lListElem *pe_ep = lFirst(pe_list);
199
lListElem *queue_ep = lFirst(cqueue_list);
200
lListElem *host_ep = lFirst(host_list);
202
if (user_ep != NULL) {
203
qquota_filter.user = lGetString(user_ep, ST_name);
206
if (project_ep != NULL) {
207
qquota_filter.project = lGetString(project_ep, ST_name);
211
qquota_filter.pe = lGetString(pe_ep, ST_name);
214
if (queue_ep != NULL) {
215
qquota_filter.queue = lGetString(queue_ep, ST_name);
218
if (host_ep != NULL) {
219
qquota_filter.host = lGetString(host_ep, ST_name);
222
if (rqs_is_matching_rule(rule, qquota_filter.user, NULL, qquota_filter.project,
223
qquota_filter.pe, qquota_filter.host,
224
qquota_filter.queue, userset_list, hgroup_list)) {
225
lListElem *limit = NULL;
227
for_each(limit, lGetList(rule, RQR_limit)) {
228
const char *limit_name = lGetString(limit, RQRL_name);
229
lList *rue_list = lGetList(limit, RQRL_usage);
230
lListElem *raw_centry = centry_list_locate(centry_list, limit_name);
231
lListElem *rue_elem = NULL;
233
if (raw_centry == NULL) {
234
/* undefined centries can be ignored */
235
DPRINTF(("centry %s not defined -> IGNORING\n", limit_name));
239
if ((resource_match_list != NULL) &&
240
((centry_list_locate(resource_match_list, limit_name) == NULL) &&
241
(centry_list_locate(resource_match_list, lGetString(raw_centry, CE_shortcut)) == NULL))) {
242
DPRINTF(("centry %s was not requested on CLI -> IGNORING\n", limit_name));
246
if (lGetString(rule, RQR_name)) {
247
sge_dstring_sprintf(&rule_name, "%s/%s", lGetString(rqs, RQS_name), lGetString(rule, RQR_name));
249
sge_dstring_sprintf(&rule_name, "%s/%d", lGetString(rqs, RQS_name), rule_count);
252
if (lGetBool(raw_centry, CE_consumable)) {
253
/* for consumables we need to walk through the utilization and search for matching values */
254
DPRINTF(("found centry %s - consumable\n", limit_name));
255
for_each(rue_elem, rue_list) {
256
u_long32 dominant = 0;
257
const char *rue_name = lGetString(rue_elem, RUE_name);
259
stringT user, project, pe, queue, host;
260
dstring limit_str = DSTRING_INIT;
261
dstring value_str = DSTRING_INIT;
262
qquota_filter_t qf = { NULL, NULL, NULL, NULL, NULL };
264
/* check user name */
265
cp = qquota_get_next_filter(user, rue_name);
266
/* usergroups have the same beginning character @ as host groups */
267
if (is_hgroup_name(qquota_filter.user)) {
268
lListElem *ugroup = NULL;
270
if ((ugroup = userset_list_locate(userset_list, &qquota_filter.user[1])) != NULL) {
271
if (sge_contained_in_access_list(user, NULL, ugroup, NULL) == 0) {
276
if ((strcmp(user, "-") != 0) && (strcmp(qquota_filter.user, "*") != 0)
277
&& (fnmatch(qquota_filter.user, user, 0) != 0)) {
283
cp = qquota_get_next_filter(project, cp);
284
if ((strcmp(project, "-") != 0) && (strcmp(qquota_filter.project, "*") != 0)
285
&& (fnmatch(qquota_filter.project, project, 0) != 0)) {
288
/* check parallel environment */
289
cp = qquota_get_next_filter(pe, cp);
290
if ((strcmp(pe, "-") != 0) && (strcmp(qquota_filter.pe, "*") != 0) &&
291
(fnmatch(qquota_filter.pe, pe, 0) != 0) ) {
294
/* check cluster queue */
295
cp = qquota_get_next_filter(queue, cp);
296
if ((strcmp(queue, "-") != 0) && (strcmp(qquota_filter.queue, "*") != 0) &&
297
(fnmatch(qquota_filter.queue, queue, 0) != 0)) {
300
/* check host name */
301
cp = qquota_get_next_filter(host, cp);
302
if (is_hgroup_name(qquota_filter.host)) {
303
lListElem *hgroup = NULL;
305
if ((hgroup = hgroup_list_locate(hgroup_list, qquota_filter.host)) != NULL) {
306
lList *host_list = NULL;
307
hgroup_find_all_references(hgroup, NULL, hgroup_list, &host_list, NULL);
308
if (host_list == NULL && lGetElemHost(host_list, HR_name, host) == NULL) {
309
lFreeList(&host_list);
312
lFreeList(&host_list);
315
if ((strcmp(host, "-") != 0) && (strcmp(qquota_filter.host, "*") != 0) &&
316
(fnmatch(qquota_filter.host, host, 0) != 0) ) {
320
if (lGetBool(limit, RQRL_dynamic)) {
321
exec_host = host_list_locate(exechost_list, host);
322
sge_dstring_sprintf(&limit_str, "%d", (int)scaled_mixed_load(lGetString(limit, RQRL_value),
323
global_host, exec_host, centry_list));
326
lSetDouble(raw_centry, CE_pj_doubleval, lGetDouble(limit, RQRL_dvalue));
327
sge_get_dominant_stringval(raw_centry, &dominant, &limit_str);
330
lSetDouble(raw_centry,CE_pj_doubleval, lGetDouble(rue_elem, RUE_utilized_now));
331
sge_get_dominant_stringval(raw_centry, &dominant, &value_str);
334
qf.project = project;
338
ret = qquota_print_out_rule(rule, rule_name, limit_name,
339
sge_dstring_get_string(&value_str), sge_dstring_get_string(&limit_str),
340
qf, raw_centry, report_handler, printed_rules, alpp);
342
sge_dstring_free(&limit_str);
343
sge_dstring_free(&value_str);
347
qquota_filter_t qf = { NULL, NULL, NULL, NULL, NULL };
349
DPRINTF(("found centry %s - static value\n", limit_name));
350
ret = qquota_print_out_rule(rule, rule_name, limit_name,
351
NULL, lGetString(limit, RQRL_value),
352
qf, raw_centry, report_handler, printed_rules, alpp);
357
} while ((host_ep = lNext(host_ep)));
358
} while ((queue_ep = lNext(queue_ep)));
359
} while ((pe_ep = lNext(pe_ep)));
360
} while ((project_ep = lNext(project_ep)));
361
} while ((user_ep = lNext(user_ep)));
366
if (report_handler != NULL) {
367
report_handler->report_finished(report_handler, alpp);
372
sge_dstring_free(&rule_name);
373
lFreeList(&rqs_list);
374
lFreeList(¢ry_list);
375
lFreeList(&userset_list);
376
lFreeList(&hgroup_list);
377
lFreeList(&exechost_list);
378
lFreeList(&printed_rules);
383
/****** qquota_output/get_all_lists() ******************************************
385
* get_all_lists() -- get all lists from qmaster
388
* static bool get_all_lists(sge_gdi_ctx_class_t *ctx, lList **rqs_l, lList
389
* **centry_l, lList **userset_l, lList **hgroup_l, lList **exechost_l,
390
* lList *hostref_l, lList **alpp)
393
* Gets copies of queue-, job-, complex-, exechost-list from qmaster.
394
* The lists are stored in the .._l pointerpointer-parameters.
395
* WARNING: Lists previously stored in this pointers are not destroyed!!
398
* void *context - gdi context
399
* lList **rqs_l - resource quota set list (RQS_Type)
400
* lList **centry_l - consumable resource list (CE_Type)
401
* lList **userset_l - userset list (US_Type)
402
* lList **hgroup_l - host group list (HG_Type)
403
* lList **exechost_l - exechost list (EH_Type)
404
* lList *hostref_l - selected hosts (ST_Type)
405
* lList **alpp - answer list
408
* static bool - true on success
412
* MT-NOTE: get_all_lists() is MT safe
414
*******************************************************************************/
416
get_all_lists(sge_gdi_ctx_class_t *ctx, lList **rqs_l, lList **centry_l, lList **userset_l,
417
lList **hgroup_l, lList **exechost_l, lList *hostref_l, lList **alpp)
419
lListElem *ep = NULL;
420
lEnumeration *what = NULL;
421
lCondition *where = NULL, *nw = NULL;
423
int rqs_id, ce_id, userset_id, hgroup_id, eh_id;
424
state_gdi_multi state = STATE_GDI_MULTI_INIT;
426
DENTER(TOP_LAYER, "get_all_lists");
429
** resource quota sets
431
what = lWhat("%T(ALL)", RQS_Type);
432
rqs_id = ctx->gdi_multi(ctx,
433
alpp, SGE_GDI_RECORD, SGE_RQS_LIST, SGE_GDI_GET,
434
NULL, NULL, what, &state, true);
437
if (answer_list_has_error(alpp)) {
444
what = lWhat("%T(ALL)", CE_Type);
445
ce_id = ctx->gdi_multi(ctx,
446
alpp, SGE_GDI_RECORD, SGE_CENTRY_LIST, SGE_GDI_GET,
447
NULL, NULL, what, &state, true);
450
if (answer_list_has_error(alpp)) {
456
what = lWhat("%T(ALL)", US_Type);
457
userset_id = ctx->gdi_multi(ctx,
458
alpp, SGE_GDI_RECORD, SGE_USERSET_LIST, SGE_GDI_GET,
459
NULL, NULL, what, &state, true);
462
if (answer_list_has_error(alpp)) {
468
what = lWhat("%T(ALL)", HGRP_Type);
469
hgroup_id = ctx->gdi_multi(ctx,
470
alpp, SGE_GDI_RECORD, SGE_HGROUP_LIST, SGE_GDI_GET,
471
NULL, NULL, what, &state, true);
476
for_each(ep, hostref_l) {
477
nw = lWhere("%T(%I h= %s)", EH_Type, EH_name, lGetString(ep, ST_name));
481
where = lOrWhere(where, nw);
483
/* the global host has to be retrieved as well */
485
nw = lWhere("%T(%I == %s)", EH_Type, EH_name, SGE_GLOBAL_NAME);
486
where = lOrWhere(where, nw);
489
nw = lWhere("%T(%I != %s)", EH_Type, EH_name, SGE_TEMPLATE_NAME);
491
where = lAndWhere(where, nw);
495
what = lWhat("%T(%I %I %I %I)", EH_Type, EH_name, EH_load_list, EH_consumable_config_list, EH_resource_utilization);
496
eh_id = ctx->gdi_multi(ctx, alpp, SGE_GDI_SEND, SGE_EXECHOST_LIST, SGE_GDI_GET,
497
NULL, where, what, &state, true);
498
ctx->gdi_wait(ctx, alpp, &mal, &state);
502
if (answer_list_has_error(alpp)) {
506
/* --- resource quota sets */
508
sge_gdi_extract_answer(alpp, SGE_GDI_GET, SGE_RQS_LIST, rqs_id,
510
if (answer_list_has_error(alpp)) {
515
/* --- complex attribute */
517
sge_gdi_extract_answer(alpp, SGE_GDI_GET, SGE_CENTRY_LIST, ce_id,
519
if (answer_list_has_error(alpp)) {
525
sge_gdi_extract_answer(alpp, SGE_GDI_GET, SGE_USERSET_LIST, userset_id,
527
if (answer_list_has_error(alpp)) {
533
sge_gdi_extract_answer(alpp, SGE_GDI_GET, SGE_HGROUP_LIST, hgroup_id,
535
if (answer_list_has_error(alpp)) {
541
sge_gdi_extract_answer(alpp, SGE_GDI_GET, SGE_EXECHOST_LIST, eh_id,
546
if (answer_list_has_error(alpp)) {
553
/****** qquota_output/qquota_get_next_filter() *********************************
555
* qquota_get_next_filter() -- tokenize rue_name of usage
558
* static char* qquota_get_next_filter(char *filter, const char *cp)
561
* The rue_name has the type /user_name/project_name/pe_name/queue_name/host_name.
562
* This function tokenizes the rue_name and gives always one element back
565
* char *filter - store for the token
566
* const char *cp - pointer to rue_name
569
* static char* - pointer for the next token
572
* MT-NOTE: qquota_get_next_filter() is not MT safe
574
*******************************************************************************/
575
static char *qquota_get_next_filter(stringT filter, const char *cp)
579
ret = strchr(cp, '/')+1;
580
if (ret - cp < MAX_STRING_SIZE && ret - cp > 1) {
581
snprintf(filter, ret - cp, "%s", cp);
583
sprintf(filter, "-");
589
/****** qquota_output/qquota_print_out_rule() **********************************
591
* qquota_print_out_rule() -- print out rule
594
* static bool qquota_print_out_rule(lListElem *rule, dstring rule_name,
595
* const char *limit_name, const char *usage_value, const char *limit_value,
596
* qquota_filter_t qfilter, lListElem *centry, report_handler_t*
597
* report_handler, lList **alpp)
603
* lListElem *rule - resouce quota rule (RQR_Type)
604
* dstring rule_name - rule name (eg. ruleset1/rule1)
605
* const char *limit_name - limiation name (eg. slots)
606
* const char *usage_value - debited usage
607
* const char *limit_value - configured limitation
608
* qquota_filter_t qfilter - filter touple
609
* lListElem *centry - limitation centry element
610
* report_handler_t* report_handler - handler for xml output
611
* lList **alpp - answer list
614
* static bool - true on success
618
* MT-NOTE: qquota_print_out_rule() is not MT safe
620
*******************************************************************************/
621
static bool qquota_print_out_rule(lListElem *rule, dstring rule_name, const char *limit_name,
622
const char *usage_value, const char *limit_value, qquota_filter_t qfilter,
623
lListElem *centry, report_handler_t* report_handler, lList *printed_rules, lList **alpp)
625
static bool printheader = true;
627
dstring filter_str = DSTRING_INIT;
628
dstring limitation = DSTRING_INIT;
629
dstring token = DSTRING_INIT;
631
sge_dstring_sprintf(&token, "%s,%s,%s,%s,%s,%s,%s", sge_dstring_get_string(&rule_name),
633
qfilter.user? qfilter.user: "",
634
qfilter.project? qfilter.project: "",
635
qfilter.pe? qfilter.pe: "",
636
qfilter.queue? qfilter.queue: "",
637
qfilter.host? qfilter.host: "");
639
if (lGetElemStr(printed_rules, ST_name, sge_dstring_get_string(&token)) != NULL) {
640
sge_dstring_free(&token);
641
sge_dstring_free(&filter_str);
642
sge_dstring_free(&limitation);
646
lAddElemStr(&printed_rules, ST_name, sge_dstring_get_string(&token), ST_Type);
648
if (report_handler != NULL) {
649
report_handler->report_limit_rule_begin(report_handler, sge_dstring_get_string(&rule_name), alpp);
651
if (printheader == true) {
653
printf(HEAD_FORMAT, MSG_HEADER_RULE, MSG_HEADER_LIMIT, MSG_HEADER_FILTER);
654
printf("--------------------------------------------------------------------------------\n");
658
qquota_print_out_filter(lGetObject(rule, RQR_filter_users), "users", qfilter.user, &filter_str, report_handler, alpp);
659
qquota_print_out_filter(lGetObject(rule, RQR_filter_projects), "projects", qfilter.project, &filter_str, report_handler, alpp);
660
qquota_print_out_filter(lGetObject(rule, RQR_filter_pes), "pes", qfilter.pe, &filter_str, report_handler, alpp);
661
qquota_print_out_filter(lGetObject(rule, RQR_filter_queues), "queues", qfilter.queue, &filter_str, report_handler, alpp);
662
qquota_print_out_filter(lGetObject(rule, RQR_filter_hosts), "hosts", qfilter.host, &filter_str, report_handler, alpp);
664
if (report_handler != NULL) {
665
report_handler->report_resource_value(report_handler, limit_name,
669
report_handler->report_limit_rule_finished(report_handler, sge_dstring_get_string(&rule_name), alpp);
671
if (usage_value == NULL) {
672
sge_dstring_sprintf(&limitation, "%s=%s", limit_name, limit_value);
674
sge_dstring_sprintf(&limitation, "%s=%s/%s", limit_name, usage_value, limit_value);
676
if (sge_dstring_strlen(&filter_str) == 0) {
677
sge_dstring_append(&filter_str, "-");
679
printf(HEAD_FORMAT, sge_dstring_get_string(&rule_name), sge_dstring_get_string(&limitation), sge_dstring_get_string(&filter_str));
682
sge_dstring_free(&token);
683
sge_dstring_free(&filter_str);
684
sge_dstring_free(&limitation);
688
/****** qquota_output/qquota_print_out_filter() ********************************
690
* qquota_print_out_filter() -- prints out filter element
693
* static bool qquota_print_out_filter(lListElem *filter, const char *name,
694
* const char *value, dstring *buffer, report_handler_t *report_handler,
698
* this function prints out the filter configured in the rule
701
* lListElem *filter - filter element (RQRF_Type)
702
* const char *name - filter type name
703
* const char *value - filter value
704
* dstring *buffer - buffer
705
* report_handler_t *report_handler - handler for report handler
706
* lList **alpp - answer list
709
* static bool - true on success
713
* MT-NOTE: qquota_print_out_filter() is MT safe
715
*******************************************************************************/
717
qquota_print_out_filter(lListElem *filter, const char *name, const char *value,
718
dstring *buffer, report_handler_t *report_handler, lList **alpp)
723
if (filter != NULL) {
724
if (!lGetBool(filter, RQRF_expand) || value == NULL) {
725
if (report_handler != NULL) {
726
for_each(scope, lGetList(filter, RQRF_scope)) {
727
report_handler->report_limit_string_value(report_handler, name, lGetString(scope, ST_name), false, alpp);
729
for_each(scope, lGetList(filter, RQRF_xscope)) {
730
report_handler->report_limit_string_value(report_handler, name, lGetString(scope, ST_name), true, alpp);
733
if (sge_dstring_strlen(buffer) != 0) {
734
sge_dstring_append(buffer, " ");
736
sge_dstring_append(buffer, name);
737
sge_dstring_append(buffer, " ");
738
rqs_append_filter_to_dstring(filter, buffer, alpp);
741
if (report_handler != NULL) {
742
report_handler->report_limit_string_value(report_handler, name, value, false, alpp);
744
if (sge_dstring_strlen(buffer) != 0) {
745
sge_dstring_append(buffer, " ");
747
sge_dstring_append(buffer, name);
748
sge_dstring_append(buffer, " ");
749
sge_dstring_append(buffer, value);