const char* sge_dstring_append_time(dstring *buffer, time_t time, bool as_xml) { struct tm *tm; #ifdef HAS_LOCALTIME_R struct tm tm_buffer; #endif DENTER(DSTRING_LAYER, "sge_dstring_append_time"); #ifdef HAS_LOCALTIME_R tm = (struct tm *)localtime_r(&time, &tm_buffer); #else tm = localtime(&i); #endif if (as_xml) { sge_dstring_sprintf_append(buffer, "%04d-%02d-%02dT%02d:%02d:%02d", 1900 + tm->tm_year, tm->tm_mon + 1, tm->tm_mday, tm->tm_hour, tm->tm_min, tm->tm_sec); } else { sge_dstring_sprintf_append(buffer, "%02d/%02d/%04d %02d:%02d:%02d", tm->tm_mon + 1, tm->tm_mday, 1900 + tm->tm_year, tm->tm_hour, tm->tm_min, tm->tm_sec); } DRETURN(buffer->s); }
void sge_spoolmsg_append(dstring *ds, const char comment_char, const char *version) { int i = 0; sge_dstring_sprintf_append(ds, "%c Version: %s\n", comment_char, version); while(spoolmsg_message[i]) { sge_dstring_sprintf_append(ds, "%c %s\n", comment_char, spoolmsg_message[i]); i++; } return; }
/****** uti/monitor/sge_monitor_output() *************************************** * NAME * sge_monitor_output() -- outputs the result into the message file * * SYNOPSIS * void sge_monitor_output(monitoring_t *monitor) * * FUNCTION * This function computes the output line from the gathered statistics. * The output is only generated, when the the output flag in the * monitoring structure is set. * * The monitoring line is printed to the message file in the profiling * class and it made available for the qping -f output. For the qping * output, it stores the the generation time, though that qping can * show, when the message was generated. * * If an extension is set, it calls the apropriate output function for * it. * * INPUTS * monitoring_t *monitor - the monitoring info * * NOTES * MT-NOTE: sge_monitor_output() is MT safe * *******************************************************************************/ void sge_monitor_output(monitoring_t *monitor) { DENTER(GDI_LAYER, "sge_monitor_output"); if ((monitor != NULL) && (monitor->output == true)) { struct timeval after; double time; gettimeofday(&after, NULL); time = after.tv_usec - monitor->now.tv_usec; time = after.tv_sec - monitor->now.tv_sec + (time/1000000); sge_dstring_clear(monitor->work_line); sge_dstring_sprintf_append(monitor->work_line, MSG_UTI_MONITOR_DEFLINE_SF, monitor->thread_name, monitor->message_in_count/time); if (monitor->ext_type != NONE_EXT) { sge_dstring_append(monitor->work_line, " ("); monitor->ext_output(monitor->work_line, monitor->ext_data, time); sge_dstring_append(monitor->work_line, ")"); }; sge_dstring_sprintf_append(monitor->work_line, MSG_UTI_MONITOR_DEFLINE_FFFFF, monitor->message_out_count/time, monitor->message_in_count ? (time - monitor->idle)/monitor->message_in_count: 0, monitor->idle/time*100, monitor->wait/time*100, time); /* only log into the message file, if the user wants it */ if (monitor->log_monitor_mes) { sge_log(LOG_PROF, sge_dstring_get_string(monitor->work_line),__FILE__,SGE_FUNC,__LINE__); } if (monitor->pos != -1) { dstring *tmp = NULL; sge_mutex_lock("sge_monitor_init", SGE_FUNC, __LINE__, &(Output[monitor->pos].Output_Mutex)); tmp = Output[monitor->pos].output; Output[monitor->pos].output = monitor->work_line; Output[monitor->pos].update_time = after.tv_sec; sge_mutex_unlock("sge_monitor_init", SGE_FUNC, __LINE__, &(Output[monitor->pos].Output_Mutex)); monitor->work_line = tmp; } sge_monitor_reset(monitor); } DRETURN_VOID; }
/****** uti/sge_log/sge_do_log() *********************************************** * NAME * sge_do_log() -- Write message to log file * * SYNOPSIS * static void sge_do_log(int aLevel, const char *aMessage, const char * * FUNCTION * ??? * * INPUTS * int aLevel - log level * const char *aMessage - log message * * RESULT * void - none * * NOTES * MT-NOTE: sge_do_log() is MT safe. * *******************************************************************************/ static void sge_do_log(u_long32 me, const char* progname, const char* unqualified_hostname, int aLevel, const char *aMessage) { int fd; if (me == QMASTER || me == EXECD || me == SCHEDD || me == SHADOWD) { if ((fd = SGE_OPEN3(log_state_get_log_file(), O_WRONLY | O_APPEND | O_CREAT, 0666)) >= 0) { char msg2log[4*MAX_STRING_SIZE]; dstring msg; int len; sge_dstring_init(&msg, msg2log, sizeof(msg2log)); append_time((time_t)sge_get_gmt(), &msg, false); sge_dstring_sprintf_append(&msg, "|%6.6s|%s|%c|%s\n", progname, unqualified_hostname, aLevel, aMessage); len = strlen(msg2log); if (write(fd, msg2log, len) != len) { /* we are in error logging here - the only chance to log this problem * might be to write it to stderr */ fprintf(stderr, "can't log to file %s: %s\n", log_state_get_log_file(), sge_strerror(errno, &msg)); } close(fd); } } return; } /* sge_do_log() */
/****** uti/sge_log/sge_do_log() *********************************************** * NAME * sge_do_log() -- Write message to log file * * SYNOPSIS * static void sge_do_log(int aLevel, const char *aMessage, const char * * FUNCTION * ??? * * INPUTS * int aLevel - log level * const char *aMessage - log message * * RESULT * void - none * * NOTES * MT-NOTE: sge_do_log() is MT safe. * *******************************************************************************/ static void sge_do_log(u_long32 me, const char* progname, const char* unqualified_hostname, int aLevel, const char *aMessage) { int fd; if (me == QMASTER || me == EXECD || me == SCHEDD || me == SHADOWD) { if ((fd = SGE_OPEN3(log_state_get_log_file(), O_WRONLY | O_APPEND | O_CREAT, 0666)) >= 0) { char msg2log[4*MAX_STRING_SIZE]; dstring msg; sge_dstring_init(&msg, msg2log, sizeof(msg2log)); append_time((time_t)sge_get_gmt(), &msg, false); sge_dstring_sprintf_append(&msg, "|%6.6s|%s|%c|%s\n", progname, unqualified_hostname, aLevel, aMessage); write(fd, msg2log, strlen(msg2log)); close(fd); } } return; } /* sge_do_log() */
static void ext_tet_output(dstring *message, void *monitoring_extension, double time) { m_tet_t *tet_ext = (m_tet_t*) monitoring_extension; sge_dstring_sprintf_append(message, MSG_UTI_MONITOR_TETEXT_FF, ((double)tet_ext->event_count) / tet_ext->count, tet_ext->exec_count / time ); }
/****** uti/monitor/ext_lis_output() ******************************************* * NAME * ext_lis_output() -- generates a string from the listener extension * * SYNOPSIS * static void * ext_lis_output(char *message, int size, void * *monitoring_extension, double time) * * FUNCTION * generates a string from the extension and returns it. * * INPUTS * char *message - initilized string buffer * int size - buffer size * void *monitoring_extension - the extension structure * double time - length of the mesurement interval * * NOTES * MT-NOTE: ext_lis_output() is MT safe *******************************************************************************/ static void ext_lis_output(dstring *message, void *monitoring_extension, double time) { m_lis_t *gdi_ext = (m_lis_t*) monitoring_extension; sge_dstring_sprintf_append(message, MSG_UTI_MONITOR_LISEXT_FFFF, gdi_ext->inc_gdi/time, gdi_ext->inc_ack/time, gdi_ext->inc_ece/time, gdi_ext->inc_rep/time); }
/****** uti/monitor/ext_gdi_output() ******************************************* * NAME * ext_gdi_output() -- generates a string from the GDI extension * * SYNOPSIS * static void ext_gdi_output(char *message, int size, void * *monitoring_extension, double time) * * FUNCTION * generates a string from the extension and returns it. * * INPUTS * char *message - initilized string buffer * int size - buffer size * void *monitoring_extension - the extension structure * double time - length of the mesurement interval * * NOTES * MT-NOTE: ext_gdi_output() is MT safe *******************************************************************************/ static void ext_gdi_output(dstring *message, void *monitoring_extension, double time) { m_gdi_t *gdi_ext = (m_gdi_t*) monitoring_extension; sge_dstring_sprintf_append(message, MSG_UTI_MONITOR_GDIEXT_FFFFFFFFFFFFI, gdi_ext->eload_count/time, gdi_ext->ejob_count/time, gdi_ext->econf_count/time, gdi_ext->eproc_count/time, gdi_ext->eack_count/time, gdi_ext->gdi_add_count/time, gdi_ext->gdi_get_count/time, gdi_ext->gdi_mod_count/time, gdi_ext->gdi_del_count/time, gdi_ext->gdi_cp_count/time, gdi_ext->gdi_trig_count/time, gdi_ext->gdi_perm_count/time, sge_u32c(gdi_ext->queue_length)); }
/****** uti/monitor/ext_edt_output() ******************************************* * NAME * ext_edt_output() -- generates a string from the GDI extension * * SYNOPSIS * static void ext_edt_output(char *message, int size, void * *monitoring_extension, double time) * * FUNCTION * generates a string from the extension and returns it. * * INPUTS * char *message - initilized string buffer * int size - buffer size * void *monitoring_extension - the extension structure * double time - length of the mesurement interval * * NOTES * MT-NOTE: ext_edt_output() is MT safe * *******************************************************************************/ static void ext_edt_output(dstring *message, void *monitoring_extension, double time) { m_edt_t *edt_ext = (m_edt_t*) monitoring_extension; sge_dstring_sprintf_append(message, MSG_UTI_MONITOR_EDTEXT_FFFFFFFF, ((double)edt_ext->client_count) / edt_ext->count, edt_ext->mod_client_count / time, edt_ext->ack_count / time, ((double)edt_ext->blocked_client_count) / edt_ext->count, ((double)edt_ext->busy_client_count) / edt_ext->count, edt_ext->new_event_count / time, edt_ext->added_event_count / time, edt_ext->skip_event_count / time); }
/****** sgeobj/str/str_list_append_to_dstring() ******************************* * NAME * str_list_append_to_dstring() -- append strings to dstring * * SYNOPSIS * const char * * str_list_append_to_dstring(const lList *this_list, * dstring *string, * const char delimiter) * * FUNCTION * Append the strings contained in "this_list" to the dstring * "string". Separate them by the character contained in * "delimiter". * If "this_list" is NULL or conaines no elements, "NONE" will * be added to the dstring. * * INPUTS * const lList *this_list - ST_Type list * dstring *string - dynamic string * const char delimiter - delimiter * * RESULT * const char * - pointer to the given "string"-buffer * * SEE ALSO * sgeobj/str/str_list_parse_from_string() *******************************************************************************/ const char * str_list_append_to_dstring(const lList *this_list, dstring *string, const char delimiter) { const char *ret = NULL; DENTER(STR_LAYER, "str_list_append_to_dstring"); if (string != NULL) { lListElem *elem = NULL; bool printed = false; for_each(elem, this_list) { sge_dstring_append(string, lGetString(elem, ST_name)); if (lNext(elem) != NULL) { sge_dstring_sprintf_append(string, "%c", delimiter); } printed = true; }
/****** sge_binding/binding_print_to_string() ********************************** * NAME * binding_print_to_string() -- Prints the content of a binding list to a string * * SYNOPSIS * bool binding_print_to_string(const lListElem *this_elem, dstring *string) * * FUNCTION * Prints the binding type and binding strategy of a binding list element * into a string. * * INPUTS * const lListElem* this_elem - Binding list element * * OUTPUTS * const dstring *string - Output string which must be initialized. * * RESULT * bool - true in all cases * * NOTES * MT-NOTE: is_starting_point() is MT safe * *******************************************************************************/ bool binding_print_to_string(const lListElem *this_elem, dstring *string) { bool ret = true; DENTER(BINDING_LAYER, "binding_print_to_string"); if (this_elem != NULL && string != NULL) { const char *const strategy = lGetString(this_elem, BN_strategy); binding_type_t type = (binding_type_t)lGetUlong(this_elem, BN_type); switch (type) { case BINDING_TYPE_SET: sge_dstring_append(string, "set "); break; case BINDING_TYPE_PE: sge_dstring_append(string, "pe "); break; case BINDING_TYPE_ENV: sge_dstring_append(string, "env "); break; case BINDING_TYPE_NONE: sge_dstring_append(string, "NONE"); } if (strcmp(strategy, "linear_automatic") == 0) { u_long32 n = sge_u32c(lGetUlong(this_elem, BN_parameter_n)); if (BIND_INFINITY == n) sge_dstring_sprintf_append(string, "linear:slots"); else sge_dstring_sprintf_append(string, "linear:"sge_U32CFormat, n); } else if (strcmp(strategy, "linear") == 0) { sge_dstring_sprintf_append(string, "%s:"sge_U32CFormat":"sge_U32CFormat","sge_U32CFormat, "linear", sge_u32c(lGetUlong(this_elem, BN_parameter_n)), sge_u32c(lGetUlong(this_elem, BN_parameter_socket_offset)), sge_u32c(lGetUlong(this_elem, BN_parameter_core_offset))); } else if (strcmp(strategy, "striding_automatic") == 0) { sge_dstring_sprintf_append(string, "%s:"sge_U32CFormat":"sge_U32CFormat, "striding", sge_u32c(lGetUlong(this_elem, BN_parameter_n)), sge_u32c(lGetUlong(this_elem, BN_parameter_striding_step_size))); } else if (strcmp(strategy, "striding") == 0) { sge_dstring_sprintf_append(string, "%s:"sge_U32CFormat":"sge_U32CFormat":"sge_U32CFormat","sge_U32CFormat, "striding", sge_u32c(lGetUlong(this_elem, BN_parameter_n)), sge_u32c(lGetUlong(this_elem, BN_parameter_striding_step_size)), sge_u32c(lGetUlong(this_elem, BN_parameter_socket_offset)), sge_u32c(lGetUlong(this_elem, BN_parameter_core_offset))); } else if (strcmp(strategy, "explicit") == 0) { sge_dstring_sprintf_append(string, "%s", lGetString(this_elem, BN_parameter_explicit)); } } DRETURN(ret); }
/****** category/sge_build_job_cs_category() *********************************** * NAME * sge_build_job_cs_category() -- generates the category string for the sc * * SYNOPSIS * const char* sge_build_job_cs_category(dstring *category_str, lListElem * *job, lListElem *cat_obj) * * FUNCTION * ??? * * INPUTS * dstring *category_str - storage forthe c string * lListElem *job - job for which to create a category * lListElem *cat_obj - regular category for the job. * * RESULT * const char* - * * EXAMPLE * ??? * * NOTES * MT-NOTE: sge_build_job_cs_category() is MT safe * *******************************************************************************/ const char* sge_build_job_cs_category(dstring *category_str, lListElem *job, lListElem *cat_obj, bool did_project) { const char *p; DENTER(TOP_LAYER, "sge_build_job_cs_category"); /* * deadline */ sge_dstring_sprintf_append(category_str, "-dl "sge_u32, lGetUlong(job, JB_deadline)); /* * priority */ sge_dstring_sprintf_append(category_str, "-p "sge_u32, lGetUlong(job, JB_priority)); sge_dstring_sprintf_append(category_str, "-ot "sge_u32, lGetUlong(job, JB_override_tickets)); sge_dstring_sprintf_append(category_str, "-js "sge_u32, lGetUlong(job, JB_jobshare)); sge_dstring_sprintf_append(category_str, "-u %s", lGetString(job, JB_owner)); /* * ticket assignment can depend on a jobs project. * If the project was not added to the resource categories * it gets added directly to the cs category string */ if ((p=lGetString(job, JB_project)) && !did_project) sge_dstring_sprintf_append(category_str, " -P %s", p); /* * id for the resource category * I use teh address of the resource category as a hash value for its string. */ sge_dstring_sprintf_append(category_str, " %x", cat_obj); DEXIT; return sge_dstring_get_string(category_str); }
/****** uti/monitor/ext_sch_output() ******************************************* * NAME * ext_sch_output() -- generates a string from the scheduler extension * * SYNOPSIS * static void * ext_sch_output(char *message, int size, void * *monitoring_extension, double time) * * FUNCTION * generates a string from the extension and returns it. * * INPUTS * char *message - initilized string buffer * int size - buffer size * void *monitoring_extension - the extension structure * double time - length of the mesurement interval * * NOTES * MT-NOTE: ext_gdi_output() is MT safe *******************************************************************************/ static void ext_sch_output(dstring *message, void *monitoring_extension, double time) { sge_dstring_sprintf_append(message, ""); }
/****** uti/monitor/sge_monitor_status() *************************************** * NAME * sge_monitor_status() -- generates the status for qping / commlib * * SYNOPSIS * u_long32 sge_monitor_status(char **info_message, u_long32 monitor_time) * * FUNCTION * This method creats the health monitoring output and returns the monitoring * info to the commlib. * * INPUTS * char **info_message - info_message pointer, has to point to a NULL string * u_long32 monitor_time - the configured monitoring interval * * RESULT * u_long32 - 0 : everything is okay * 1 : warning * 2 : error * 3 : init problems * * NOTES * MT-NOTE: sge_monitor_status() is MT safe * *******************************************************************************/ u_long32 sge_monitor_status(char **info_message, u_long32 monitor_time) { u_long32 ret = 0; char date[40]; dstring ddate; DENTER(GDI_LAYER, "sge_monitor_status"); if (info_message == NULL) { DEXIT; return 3; } sge_dstring_init(&ddate, date, sizeof(date)); sge_mutex_lock("sge_monitor_status", SGE_FUNC, __LINE__, &global_mutex); sge_dstring_clear(&Info_Line); {/* this is the qping info section, it checks if each thread is still alive */ int i; int error_count = 0; struct timeval now; double time; char state = 'R'; gettimeofday(&now,NULL); for (i = 0; i < MAX_OUTPUT_LINES; i++) { sge_mutex_lock("sge_monitor_status", SGE_FUNC, __LINE__, &(Output[i].Output_Mutex)); if (Output[i].name != NULL) { time = now.tv_usec - Output[i].last_wait_time.tv_usec; time = now.tv_sec - Output[i].last_wait_time.tv_sec + (time /1000000); if (Output[i].warning_timeout != NO_WARNING) { if (Output[i].warning_timeout < time) { if (Output[i].error_timeout < time) { state = 'E'; } else { state = 'W'; } error_count++; } } sge_dstring_sprintf_append(&Info_Line, MSG_UTI_MONITOR_INFO_SCF, Output[i].name, state, time); } sge_mutex_unlock("sge_monitor_status", SGE_FUNC, __LINE__, &(Output[i].Output_Mutex)); } if (error_count == 0) { sge_dstring_append(&Info_Line, MSG_UTI_MONITOR_OK); } else if (error_count == 1) { ret = 1; sge_dstring_append(&Info_Line, MSG_UTI_MONITOR_WARNING); } else { ret = 2; sge_dstring_append(&Info_Line, MSG_UTI_MONITOR_ERROR); } sge_dstring_append(&Info_Line, "\n"); } #if defined(LINUX) || defined(AIX43) || defined(AIX51) || defined(IRIX) || defined(SOLARIS) || defined(HP11) if (mallinfo_func_pointer != NULL) { struct mallinfo mallinfo_data = mallinfo_func_pointer(); sge_dstring_sprintf_append(&Info_Line, MSG_UTI_MONITOR_SCHEXT_UUUUUUUUUU, mallinfo_data.arena, mallinfo_data.ordblks, mallinfo_data.smblks, mallinfo_data.hblks, mallinfo_data.hblkhd, mallinfo_data.usmblks, mallinfo_data.fsmblks, mallinfo_data.uordblks, mallinfo_data.fordblks, mallinfo_data.keepcost); sge_dstring_append(&Info_Line, "\n"); } #endif if (monitor_time != 0) { /* generates the output monitoring output data */ int i; sge_dstring_append(&Info_Line, MSG_UTI_MONITOR_COLON); sge_dstring_append(&Info_Line, "\n"); for (i = 0; i < MAX_OUTPUT_LINES; i++) { sge_mutex_lock("sge_monitor_status", SGE_FUNC, __LINE__, &(Output[i].Output_Mutex)); if (Output[i].name != NULL) { append_time(Output[i].update_time, &Info_Line, false); sge_dstring_append(&Info_Line, " | "); sge_dstring_append_dstring(&Info_Line, Output[i].output); sge_dstring_append(&Info_Line,"\n"); } sge_mutex_unlock("sge_monitor_status", SGE_FUNC, __LINE__, &(Output[i].Output_Mutex)); } } else { sge_dstring_append(&Info_Line, MSG_UTI_MONITOR_DISABLED); sge_dstring_append(&Info_Line, "\n"); } *info_message = strdup(sge_dstring_get_string(&Info_Line)); sge_mutex_unlock("sge_monitor_status", SGE_FUNC, __LINE__, &global_mutex); DEXIT; return ret; }
static bool check_all(dstring *sb) { bool ret = true; int i; /* sge_dstring_append */ printf("\nchecking sge_dstring_append\n"); sge_dstring_append(NULL, NULL); sge_dstring_append(sb, NULL); check_dstring(sb); sge_dstring_append(sb, "blah"); check_dstring(sb); sge_dstring_clear(sb); sge_dstring_append(sb, "too long string to fit into a static string buffer"); check_dstring(sb); sge_dstring_clear(sb); sge_dstring_append(sb, "long string that requires multiple chunks ....... "); check_dstring(sb); for (i = 0; i < 20; i++) { sge_dstring_append(sb, "long string that requires multiple chunks ....... "); } check_dstring(sb); /* sge_dstring_append_dstring */ printf("\nchecking sge_dstring_append_dstring\n"); sge_dstring_clear(sb); sge_dstring_append_dstring(NULL, NULL); { dstring second = DSTRING_INIT; sge_dstring_append(&second, "dstring"); sge_dstring_append_dstring(NULL, &second); sge_dstring_append_dstring(sb, NULL); sge_dstring_append_dstring(sb, &second); check_dstring(sb); sge_dstring_free(&second); } /* sge_dstring_append_char */ printf("\nchecking sge_dstring_append_char\n"); sge_dstring_clear(sb); sge_dstring_append_char(NULL, 'a'); sge_dstring_append_char(sb, '\0'); check_dstring(sb); sge_dstring_append_char(sb, 'a'); check_dstring(sb); sge_dstring_append_char(sb, 'b'); check_dstring(sb); /* sge_dstring_sprintf */ printf("\nchecking sge_dstring_sprintf\n"); sge_dstring_sprintf(NULL, "test %s", "string"); sge_dstring_sprintf(sb, NULL); sge_dstring_sprintf(sb, "test %s", "string"); check_dstring(sb); #if 0 /* does not build on irix */ /* sge_dstring_vsprintf */ printf("\nchecking sge_dstring_vsprintf\n"); { const char *args[] = { "string", NULL }; sge_dstring_clear(sb); sge_dstring_vsprintf(NULL, "test %s", args); sge_dstring_vsprintf(sb, NULL, args); sge_dstring_vsprintf(sb, "test %s", args); check_dstring(sb); } #endif /* sge_dstring_sprintf_append */ printf("\nchecking sge_dstring_sprintf_append\n"); sge_dstring_clear(sb); sge_dstring_sprintf_append(NULL, "test %s", "string"); sge_dstring_sprintf_append(sb, NULL); sge_dstring_sprintf_append(sb, "test %s", "string"); sge_dstring_sprintf_append(sb, " appended test %s", "string"); check_dstring(sb); /* sge_dstring_clear */ printf("\nchecking sge_dstring_clear\n"); sge_dstring_clear(NULL); sge_dstring_clear(sb); check_dstring(sb); /* sge_dstring_free */ printf("\nchecking sge_dstring_free\n"); sge_dstring_free(NULL); sge_dstring_free(sb); check_dstring(sb); /* sge_dstring_get_string */ printf("\nchecking sge_dstring_get_string\n"); sge_dstring_clear(sb); sge_dstring_append(sb, "test string"); { const char *result; result = sge_dstring_get_string(NULL); printf("sge_dstring_get_string(NULL) = %s\n", result == NULL ? "NULL" : result); result = sge_dstring_get_string(sb); printf("sge_dstring_get_string(sb) = %s\n", result == NULL ? "NULL" : result); } /* sge_dstring_copy_string */ printf("\nchecking sge_dstring_copy_string\n"); sge_dstring_copy_string(NULL, NULL); sge_dstring_copy_string(sb, NULL); sge_dstring_copy_string(NULL, "new test string"); sge_dstring_copy_string(sb, "new test string"); check_dstring(sb); /* sge_dstring_copy_dstring * check only NULL pointer behaviour, it just calls sge_dstring_copy_string */ printf("\nchecking sge_dstring_copy_dstring\n"); sge_dstring_copy_dstring(NULL, NULL); sge_dstring_copy_dstring(sb, NULL); check_dstring(sb); /* sge_dstring_strlen */ printf("\nchecking sge_dstring_strlen\n"); { int len; sge_dstring_copy_string(sb, "test string"); len = sge_dstring_strlen(NULL); printf("sge_dstring_strlen(NULL) = %d\n", len); len = sge_dstring_strlen(sb); printf("sge_dstring_strlen(sb) = %d\n", len); } /* sge_dstring_remaining */ printf("\nchecking sge_dstring_remaining\n"); { int len; sge_dstring_copy_string(sb, "test string"); len = sge_dstring_remaining(NULL); printf("sge_dstring_remaining(NULL) = %d\n", len); len = sge_dstring_remaining(sb); printf("sge_dstring_remaining(sb) = %d\n", len); } return ret; }