/*___INFO__MARK_BEGIN__*/ /************************************************************************* * * The Contents of this file are made available subject to the terms of * the Sun Industry Standards Source License Version 1.2 * * Sun Microsystems Inc., March, 2001 * * * Sun Industry Standards Source License Version 1.2 * ================================================= * The contents of this file are subject to the Sun Industry Standards * Source License Version 1.2 (the "License"); You may not use this file * except in compliance with the License. You may obtain a copy of the * License at http://gridengine.sunsource.net/Gridengine_SISSL_license.html * * Software provided under this License is provided on an "AS IS" basis, * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS, * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING. * See the License for the specific provisions governing your rights and * obligations concerning the Software. * * The Initial Developer of the Original Code is: Sun Microsystems, Inc. * * Copyright: 2001 by Sun Microsystems, Inc. * * All Rights Reserved. * ************************************************************************/ #include #include "rmon/sgermon.h" #include "uti/sge_log.h" #include "uti/sge_hostname.h" #include "uti/sge_edit.h" #include "uti/sge_prog.h" #include "msg_common.h" #include "msg_clients_common.h" #include "spool/flatfile/sge_flatfile.h" #include "spool/flatfile/sge_flatfile_obj.h" #include "sgeobj/sge_conf.h" #include "sgeobj/sge_answer.h" #include "sgeobj/sge_cqueue.h" #include "sgeobj/sge_object.h" #include "sgeobj/sge_qinstance.h" #include "sgeobj/sge_hgroup.h" #include "sgeobj/sge_href.h" #include "sgeobj/sge_qref.h" #include "sgeobj/sge_centry.h" #include "sgeobj/sge_eval_expression.h" #include "gdi/sge_gdi.h" #include "gdi/sge_gdi_ctx.h" #include "sge_cqueue_qconf.h" static void insert_custom_complex_values_writer(spooling_field *fields); static int write_QU_consumable_config_list(const lListElem *ep, int nm, dstring *buffer, lList **alp); static bool cqueue_provide_modify_context(sge_gdi_ctx_class_t *ctx, lListElem **this_elem, lList **answer_list, bool ignore_unchanged_message); bool cqueue_add_del_mod_via_gdi(sge_gdi_ctx_class_t *ctx, lListElem *this_elem, lList **answer_list, u_long32 gdi_command) { bool ret = true; DENTER(TOP_LAYER, "cqueue_add_del_mod_via_gdi"); if (this_elem != NULL) { u_long32 operation = SGE_GDI_GET_OPERATION(gdi_command); bool do_verify = (operation == SGE_GDI_MOD) || (operation == SGE_GDI_ADD) ? true : false; if (do_verify) { ret &= cqueue_verify_attributes(this_elem, answer_list, this_elem, false); } if (ret) { lList *cqueue_list = NULL; lList *gdi_answer_list = NULL; cqueue_list = lCreateList("", CQ_Type); lAppendElem(cqueue_list, this_elem); gdi_answer_list = ctx->gdi(ctx, SGE_CQ_LIST, gdi_command, &cqueue_list, NULL, NULL); answer_list_replace(answer_list, &gdi_answer_list); lDechainElem(cqueue_list, this_elem); lFreeList(&cqueue_list); } } DRETURN(ret); } lListElem * cqueue_get_via_gdi(sge_gdi_ctx_class_t *ctx, lList **answer_list, const char *name) { lListElem *ret = NULL; DENTER(TOP_LAYER, "cqueue_get_via_gdi"); if (name != NULL) { lList *gdi_answer_list = NULL; lEnumeration *what = NULL; lCondition *where = NULL; lList *cqueue_list = NULL; what = lWhat("%T(ALL)", CQ_Type); where = lWhere("%T(%I==%s)", CQ_Type, CQ_name, name); gdi_answer_list = ctx->gdi(ctx, SGE_CQ_LIST, SGE_GDI_GET, &cqueue_list, where, what); lFreeWhat(&what); lFreeWhere(&where); if (!answer_list_has_error(&gdi_answer_list)) { ret = lDechainElem(cqueue_list, lFirst(cqueue_list)); } else { answer_list_replace(answer_list, &gdi_answer_list); } lFreeList(&cqueue_list); lFreeList(&gdi_answer_list); } DRETURN(ret); } static bool cqueue_hgroup_get_via_gdi(sge_gdi_ctx_class_t *ctx, lList **answer_list, const lList *qref_list, lList **hgrp_list, lList **cq_list) { bool ret = true; DENTER(TOP_LAYER, "cqueue_hgroup_get_via_gdi"); if (hgrp_list != NULL && cq_list != NULL) { state_gdi_multi state = STATE_GDI_MULTI_INIT; lList *multi_answer_list = NULL; lCondition *cqueue_where = NULL; lListElem *qref = NULL; bool fetch_all_hgroup = false; bool fetch_all_qi = false; bool fetch_all_nqi = false; int hgrp_id = 0; int cq_id = 0; for_each(qref, qref_list) { dstring cqueue_name = DSTRING_INIT; dstring host_domain = DSTRING_INIT; const char *name = lGetString(qref, QR_name); bool has_hostname, has_domain; lCondition *add_cqueue_where = NULL; const char* cqueue_name_str = NULL; if (!cqueue_name_split(name, &cqueue_name, &host_domain, &has_hostname, &has_domain)) { answer_list_add_sprintf(answer_list, STATUS_ESYNTAX, ANSWER_QUALITY_ERROR, MSG_CQUEUE_NOQMATCHING_S, name); } fetch_all_hgroup = (fetch_all_hgroup || has_domain) ? true : false; fetch_all_qi = (fetch_all_qi || (has_domain || has_hostname)) ? true : false; fetch_all_nqi = (fetch_all_nqi || (!has_domain && !has_hostname)) ? true : false; cqueue_name_str = sge_dstring_get_string(&cqueue_name); if (cqueue_name_str == NULL) { answer_list_add_sprintf(answer_list, STATUS_ESYNTAX, ANSWER_QUALITY_ERROR, MSG_CQUEUE_NAMENOTCORRECT_SS, name, name); ret = false; break; } add_cqueue_where = lWhere("%T(%I p= %s)", CQ_Type, CQ_name, sge_dstring_get_string(&cqueue_name)); if (cqueue_where == NULL) { cqueue_where = add_cqueue_where; } else { cqueue_where = lOrWhere(cqueue_where, add_cqueue_where); } sge_dstring_free(&cqueue_name); sge_dstring_free(&host_domain); } if (ret && fetch_all_hgroup) { lEnumeration *what = lWhat("%T(ALL)", HGRP_Type); hgrp_id = ctx->gdi_multi(ctx, answer_list, SGE_GDI_RECORD, SGE_HGRP_LIST, SGE_GDI_GET, NULL, NULL, what, &state, true); lFreeWhat(&what); } if (ret) { lEnumeration *what; what = enumeration_create_reduced_cq(fetch_all_qi, fetch_all_nqi); cq_id = ctx->gdi_multi(ctx, answer_list, SGE_GDI_SEND, SGE_CQ_LIST, SGE_GDI_GET, NULL, cqueue_where, what, &state, true); ctx->gdi_wait(ctx, answer_list, &multi_answer_list, &state); lFreeWhat(&what); } if (ret && fetch_all_hgroup) { lList *local_answer_list = NULL; sge_gdi_extract_answer(&local_answer_list, SGE_GDI_GET, SGE_HGRP_LIST, hgrp_id, multi_answer_list, hgrp_list); if (local_answer_list != NULL) { lListElem *answer = lFirst(local_answer_list); if (lGetUlong(answer, AN_status) != STATUS_OK) { lDechainElem(local_answer_list, answer); answer_list_add_elem(answer_list, answer); ret = false; } } lFreeList(&local_answer_list); } if (ret) { lList *local_answer_list = NULL; sge_gdi_extract_answer(&local_answer_list, SGE_GDI_GET, SGE_CQ_LIST, cq_id, multi_answer_list, cq_list); if (local_answer_list != NULL) { lListElem *answer = lFirst(local_answer_list); if (lGetUlong(answer, AN_status) != STATUS_OK) { lDechainElem(local_answer_list, answer); answer_list_add_elem(answer_list, answer); ret = false; } } lFreeList(&local_answer_list); } lFreeList(&multi_answer_list); lFreeWhere(&cqueue_where); } DRETURN(ret); } bool cqueue_hgroup_get_all_via_gdi(sge_gdi_ctx_class_t *ctx, lList **answer_list, lList **hgrp_list, lList **cq_list) { bool ret = true; DENTER(TOP_LAYER, "cqueue_hgroup_get_all_via_gdi"); if (hgrp_list != NULL && cq_list != NULL) { state_gdi_multi state = STATE_GDI_MULTI_INIT; lEnumeration *hgrp_what = NULL; lEnumeration *cqueue_what = NULL; int hgrp_id = 0; int cq_id = 0; lList *local_answer_list = NULL; lList *multi_answer_list = NULL; /* HGRP */ hgrp_what = lWhat("%T(ALL)", HGRP_Type); hgrp_id = ctx->gdi_multi(ctx, answer_list, SGE_GDI_RECORD, SGE_HGRP_LIST, SGE_GDI_GET, NULL, NULL, hgrp_what, &state, true); lFreeWhat(&hgrp_what); /* CQ */ cqueue_what = lWhat("%T(ALL)", CQ_Type); cq_id = ctx->gdi_multi(ctx, answer_list, SGE_GDI_SEND, SGE_CQ_LIST, SGE_GDI_GET, NULL, NULL, cqueue_what, &state, true); ctx->gdi_wait(ctx, answer_list, &multi_answer_list, &state); lFreeWhat(&cqueue_what); /* HGRP */ sge_gdi_extract_answer(&local_answer_list, SGE_GDI_GET, SGE_HGRP_LIST, hgrp_id, multi_answer_list, hgrp_list); if (local_answer_list != NULL) { lListElem *answer = lFirst(local_answer_list); if (lGetUlong(answer, AN_status) != STATUS_OK) { lDechainElem(local_answer_list, answer); answer_list_add_elem(answer_list, answer); ret = false; } } lFreeList(&local_answer_list); /* CQ */ sge_gdi_extract_answer(&local_answer_list, SGE_GDI_GET, SGE_CQ_LIST, cq_id, multi_answer_list, cq_list); if (local_answer_list != NULL) { lListElem *answer = lFirst(local_answer_list); if (lGetUlong(answer, AN_status) != STATUS_OK) { lDechainElem(local_answer_list, answer); answer_list_add_elem(answer_list, answer); ret = false; } } lFreeList(&local_answer_list); lFreeList(&multi_answer_list); } DRETURN(ret); } static bool cqueue_provide_modify_context(sge_gdi_ctx_class_t *ctx, lListElem **this_elem, lList **answer_list, bool ignore_unchanged_message) { bool ret = false; int status = 0; int fields_out[MAX_NUM_FIELDS]; int missing_field = NoName; uid_t uid = ctx->get_uid(ctx); gid_t gid = ctx->get_gid(ctx); DENTER(TOP_LAYER, "cqueue_provide_modify_context"); if (this_elem != NULL && *this_elem) { const char *filename = NULL; filename = spool_flatfile_write_object(answer_list, *this_elem, false, CQ_fields, &qconf_sfi, SP_DEST_TMP, SP_FORM_ASCII, filename, false); if (answer_list_output(answer_list)) { if (filename != NULL) { unlink(filename); FREE(filename); } DRETURN(false); } status = sge_edit(filename, uid, gid); if (status >= 0) { lListElem *cqueue; fields_out[0] = NoName; cqueue = spool_flatfile_read_object(answer_list, CQ_Type, NULL, CQ_fields, fields_out, false, &qconf_sfi, SP_FORM_ASCII, NULL, filename); if (answer_list_output(answer_list)) { lFreeElem(&cqueue); } if (cqueue != NULL) { missing_field = spool_get_unprocessed_field(CQ_fields, fields_out, answer_list); } if (missing_field != NoName) { lFreeElem(&cqueue); answer_list_output(answer_list); } if (cqueue != NULL) { if (object_has_differences(*this_elem, answer_list, cqueue, false) || ignore_unchanged_message) { lFreeElem(this_elem); *this_elem = cqueue; ret = true; } else { answer_list_add(answer_list, MSG_FILE_NOTCHANGED, STATUS_ERROR1, ANSWER_QUALITY_ERROR); } } else { answer_list_add(answer_list, MSG_FILE_ERRORREADINGINFILE, STATUS_ERROR1, ANSWER_QUALITY_ERROR); } } else { answer_list_add(answer_list, MSG_PARSE_EDITFAILED, STATUS_ERROR1, ANSWER_QUALITY_ERROR); } unlink(filename); FREE(filename); } DRETURN(ret); } bool cqueue_add(sge_gdi_ctx_class_t *ctx, lList **answer_list, const char *name) { bool ret = true; DENTER(TOP_LAYER, "cqueue_add"); if (name != NULL) { lListElem *cqueue = cqueue_create(answer_list, name); if (cqueue == NULL) { ret = false; } if (ret) { ret &= cqueue_set_template_attributes(cqueue, answer_list); } if (ret) { ret &= cqueue_provide_modify_context(ctx, &cqueue, answer_list, true); } if (ret) { ret &= cqueue_add_del_mod_via_gdi(ctx, cqueue, answer_list, SGE_GDI_ADD | SGE_GDI_SET_ALL); } lFreeElem(&cqueue); } DRETURN(ret); } bool cqueue_add_from_file(sge_gdi_ctx_class_t *ctx, lList **answer_list, const char *filename) { bool ret = true; int fields_out[MAX_NUM_FIELDS]; int missing_field = NoName; DENTER(TOP_LAYER, "cqueue_add_from_file"); if (filename != NULL) { lListElem *cqueue; fields_out[0] = NoName; cqueue = spool_flatfile_read_object(answer_list, CQ_Type, NULL, CQ_fields, fields_out, false, &qconf_sfi, SP_FORM_ASCII, NULL, filename); if (answer_list_output(answer_list)) { lFreeElem(&cqueue); } if (cqueue != NULL) { missing_field = spool_get_unprocessed_field (CQ_fields, fields_out, answer_list); } if (missing_field != NoName) { lFreeElem(&cqueue); answer_list_output(answer_list); } if (cqueue == NULL) { ret = false; } if (ret) { ret &= cqueue_add_del_mod_via_gdi(ctx, cqueue, answer_list, SGE_GDI_ADD | SGE_GDI_SET_ALL); } lFreeElem(&cqueue); } DRETURN(ret); } bool cqueue_modify(sge_gdi_ctx_class_t *ctx, lList **answer_list, const char *name) { bool ret = true; DENTER(TOP_LAYER, "cqueue_modify"); if (name != NULL) { lListElem *cqueue = cqueue_get_via_gdi(ctx, answer_list, name); if (cqueue == NULL) { sprintf(SGE_EVENT, MSG_CQUEUE_DOESNOTEXIST_S, name); answer_list_add(answer_list, SGE_EVENT, STATUS_ERROR1, ANSWER_QUALITY_ERROR); ret = false; } if (ret) { ret &= cqueue_provide_modify_context(ctx, &cqueue, answer_list, false); } if (ret) { ret &= cqueue_add_del_mod_via_gdi(ctx, cqueue, answer_list, SGE_GDI_MOD | SGE_GDI_SET_ALL); } lFreeElem(&cqueue); } DRETURN(ret); } bool cqueue_modify_from_file(sge_gdi_ctx_class_t *ctx, lList **answer_list, const char *filename) { bool ret = true; int fields_out[MAX_NUM_FIELDS]; int missing_field = NoName; DENTER(TOP_LAYER, "cqueue_modify_from_file"); if (filename != NULL) { lListElem *cqueue; fields_out[0] = NoName; cqueue = spool_flatfile_read_object(answer_list, CQ_Type, NULL, CQ_fields, fields_out, false, &qconf_sfi, SP_FORM_ASCII, NULL, filename); if (answer_list_output(answer_list)) { lFreeElem(&cqueue); } if (cqueue != NULL) { missing_field = spool_get_unprocessed_field (CQ_fields, fields_out, answer_list); } if (missing_field != NoName) { lFreeElem(&cqueue); answer_list_output(answer_list); } if (cqueue == NULL) { sprintf(SGE_EVENT, MSG_CQUEUE_FILENOTCORRECT_S, filename); answer_list_add(answer_list, SGE_EVENT, STATUS_ERROR1, ANSWER_QUALITY_ERROR); ret = false; } if (ret) { ret &= cqueue_add_del_mod_via_gdi(ctx, cqueue, answer_list, SGE_GDI_MOD | SGE_GDI_SET_ALL); } if (cqueue != NULL) { lFreeElem(&cqueue); } } DRETURN(ret); } bool cqueue_delete(sge_gdi_ctx_class_t *ctx, lList **answer_list, const char *name) { bool ret = true; DENTER(TOP_LAYER, "cqueue_delete"); if (name != NULL) { lListElem *cqueue = cqueue_create(answer_list, name); if (cqueue != NULL) { ret &= cqueue_add_del_mod_via_gdi(ctx, cqueue, answer_list, SGE_GDI_DEL); } lFreeElem(&cqueue); } DRETURN(ret); } bool cqueue_show(sge_gdi_ctx_class_t *ctx, lList **answer_list, const lList *qref_pattern_list) { bool ret = true; DENTER(TOP_LAYER, "cqueue_show"); if (qref_pattern_list != NULL) { lList *hgroup_list = NULL; lList *cqueue_list = NULL; lListElem *qref_pattern; bool local_ret; local_ret = cqueue_hgroup_get_via_gdi(ctx, answer_list, qref_pattern_list, &hgroup_list, &cqueue_list); if (local_ret) { for_each(qref_pattern, qref_pattern_list) { dstring cqueue_name = DSTRING_INIT; dstring host_domain = DSTRING_INIT; const char *cq_pattern = NULL; const char *name = NULL; bool has_hostname; bool has_domain; lList *qref_list = NULL; lListElem *qref = NULL; bool found_something = false; name = lGetString(qref_pattern, QR_name); if (!cqueue_name_split(name, &cqueue_name, &host_domain, &has_hostname, &has_domain)) { /* splitting was not successful means we have a syntax error */ ret = false; break; } cq_pattern = sge_dstring_get_string(&cqueue_name); cqueue_list_find_all_matching_references(cqueue_list, NULL, cq_pattern, &qref_list); if (has_domain) { const char *d_pattern = sge_dstring_get_string(&host_domain); lList *href_list = NULL; bool is_first = true; hgroup_list_find_matching_and_resolve(hgroup_list, NULL, d_pattern, &href_list); for_each(qref, qref_list) { const char *cqueue_name = lGetString(qref, QR_name); const lListElem *cqueue = NULL; cqueue = lGetElemStr(cqueue_list, CQ_name, cqueue_name); if (cqueue != NULL) { const lList *qinstance_list = NULL; const lListElem *href = NULL; qinstance_list = lGetList(cqueue, CQ_qinstances); for_each(href, href_list) { const char *hostname = lGetHost(href, HR_name); const lListElem *qinstance; qinstance = lGetElemHost(qinstance_list, QU_qhostname, hostname); if (qinstance != NULL) { const char *filename_stdout; spooling_field *fields = sge_build_QU_field_list (true, false); /* Bugfix: Issuezilla #1198 * In order to prevent the slots from being printed * in the complex values list, we have to insert a * custom writer for the complex_values field. We do * that with this function. */ insert_custom_complex_values_writer(fields); if (is_first) { is_first = false; } else { fprintf(stdout, "\n"); } filename_stdout = spool_flatfile_write_object( answer_list, qinstance, false, fields, &qconf_sfi, SP_DEST_STDOUT, SP_FORM_ASCII, NULL, false); FREE(fields); FREE(filename_stdout); if (answer_list_output(answer_list)) { lFreeList(&href_list); lFreeList(&qref_list); DRETURN(false); } found_something = true; } } } } lFreeList(&href_list); lFreeList(&qref_list); } else if (has_hostname) { const char *h_pattern = sge_dstring_get_string(&host_domain); bool is_first = true; for_each(qref, qref_list) { const char *cqueue_name = NULL; const lListElem *cqueue = NULL; cqueue_name = lGetString(qref, QR_name); cqueue = lGetElemStr(cqueue_list, CQ_name, cqueue_name); if (cqueue != NULL) { const lList *qinstance_list = NULL; const lListElem *qinstance = NULL; qinstance_list = lGetList(cqueue, CQ_qinstances); for_each(qinstance, qinstance_list) { const char *hostname = NULL; hostname = lGetHost(qinstance, QU_qhostname); if (!sge_eval_expression(TYPE_HOST, h_pattern, hostname, NULL)) { const char *filename; spooling_field *fields = sge_build_QU_field_list(true, false); /* Bugfix: Issuezilla #1198 * In order to prevent the slots from being printed * in the complex values list, we have to insert a * custom writer for the complex_values field. We do * that with this function. */ insert_custom_complex_values_writer(fields); if (is_first) { is_first = false; } else { fprintf(stdout, "\n"); } filename = spool_flatfile_write_object(answer_list, qinstance, false, fields, &qconf_sfi, SP_DEST_STDOUT, SP_FORM_ASCII, NULL, false); FREE(fields); FREE(filename); if (answer_list_output(answer_list)) { DRETURN(false); } found_something = true; } } } } } else { bool is_first = true; for_each(qref, qref_list) { const char *cqueue_name = lGetString(qref, QR_name); lListElem *cqueue = NULL; cqueue = lGetElemStr(cqueue_list, CQ_name, cqueue_name); if (cqueue != NULL) { const char *outname; if (is_first) { is_first = false; } else { fprintf(stdout, "\n"); } outname = spool_flatfile_write_object(answer_list, cqueue, false, CQ_fields, &qconf_sfi, SP_DEST_STDOUT, SP_FORM_ASCII, NULL, false); FREE(outname); if (answer_list_output(answer_list)) { DRETURN(false); } found_something = true; } } } if (!found_something) { sprintf(SGE_EVENT, MSG_CQUEUE_NOQMATCHING_S, name); answer_list_add(answer_list, SGE_EVENT, STATUS_ERROR1, ANSWER_QUALITY_ERROR); ret = false; } sge_dstring_free(&host_domain); sge_dstring_free(&cqueue_name); lFreeList(&qref_list); } } lFreeList(&hgroup_list); lFreeList(&cqueue_list); } else { const char *filename; lListElem *cqueue = cqueue_create(answer_list, "template"); DTRACE; ret &= cqueue_set_template_attributes(cqueue, answer_list); filename = spool_flatfile_write_object(answer_list, cqueue, false, CQ_fields, &qconf_sfi, SP_DEST_STDOUT, SP_FORM_ASCII, NULL, false); FREE(filename); lFreeElem(&cqueue); if (answer_list_output(answer_list)) { DRETURN(false); } } DRETURN(ret); } bool cqueue_list_sick(sge_gdi_ctx_class_t *ctx, lList **answer_list) { bool ret = true; lList *hgroup_list = NULL; lList *cqueue_list = NULL; bool local_ret; DENTER(TOP_LAYER, "cqueue_sick"); local_ret = cqueue_hgroup_get_all_via_gdi(ctx, answer_list, &hgroup_list, &cqueue_list); if (local_ret) { dstring ds = DSTRING_INIT; lListElem *cqueue = NULL; for_each(cqueue, cqueue_list) { cqueue_sick(cqueue, answer_list, hgroup_list, &ds); } if (sge_dstring_get_string(&ds)) { printf(sge_dstring_get_string(&ds)); ret = false; } sge_dstring_free(&ds); } lFreeList(&hgroup_list); lFreeList(&cqueue_list); DRETURN(ret); } /****** insert_custom_complex_values_writer() ********************************** * NAME * insert_custom_complex_values_writer() -- Inserts a custom writer for the * complex_values field * * SYNOPSIS * static void insert_custom_complex_values_writer (spooling_field *fields) * * FUNCTION * Inserts a custom writer for the complex_values field of a QU field list * which does not write out the "slots" complex value. * * INPUT * spooling_field *fields - The QU fields list to be used for spooling * * NOTES * MT-NOTES: insert_custom_complex_values_writer() is MT safe *******************************************************************************/ static void insert_custom_complex_values_writer(spooling_field *fields) { /* First, find the complex_values field. */ int count = 0; DENTER(TOP_LAYER, "insert_custom_complex_values_writer"); while ((fields[count].nm != NoName) && (fields[count].nm != QU_consumable_config_list)) { count++; } if (fields[count].nm == QU_consumable_config_list) { /* Next, insert the custom writer. */ fields[count].write_func = write_QU_consumable_config_list; } DRETURN_VOID; } /****** write_QU_consumable_config_list() ************************************** * NAME * write_QU_consumable_config_list() -- Writes the complex_values field * without including slots * * SYNOPSIS * static int write_QU_consumable_config_list(const lListElem *ep, int nm, * dstring *buffer, lList **alp) * * FUNCTION * Writes the complex_values field to the buffer, but leaves out the slots * entry. * * INPUT * const lListElem *ep - The QU element containing the complex_values * int nm - The nm of the field := QU_consumable_config_list * dstring *buffer - The dstring into which to print the field * lList **alp - Answer list for errors *******************************************************************************/ static int write_QU_consumable_config_list(const lListElem *ep, int nm, dstring *buffer, lList **alp) { lList *lp = lGetList (ep, nm); lListElem *vep = NULL; bool first = true, has_elems = false; DENTER(TOP_LAYER, "write_QU_consumable_config_list"); /* Look through the complex_values list and print everything but slots */ /* The format we're using to print is intended to replicate what is set forth * in the qconf_sub_name_value_space_sfi spooling instruction. If this * instruction changes, or if the qconf_sfi spooling instruction changes to * use a new sub-instruction, this function will have to be changed to * to reflect this. Otherwise, the complex values will be printed in a * different format from the other attributes. */ for_each(vep, lp) { const char *name = lGetString(vep, CE_name); if (strcmp(name, "slots") != 0) { const char *strval = NULL; /* we want to know if any elements from the list are available or not*/ has_elems = true; /* Print a separating space for all elements after the first */ if (first) { first = false; } else { sge_dstring_append(buffer, " "); } /* Append name=value, where value could be a string of a number */ sge_dstring_append(buffer, name); sge_dstring_append(buffer, "="); strval = lGetString(vep, CE_stringval); if (strval != NULL) { sge_dstring_append(buffer, strval); } else { char tmp[MAX_STRING_SIZE]; snprintf(tmp, MAX_STRING_SIZE, "%f", lGetDouble(ep, CE_doubleval)); sge_dstring_append(buffer, strdup (tmp)); } } } /* for CR 6433628, adding NONE string when there are no complex values */ if (!has_elems){ sge_dstring_append(buffer, NONE_STR); } DRETURN(1); }