/* Test Case: * Submit a job that generates output after a short time. * Before that output is generated, send a STDIO_UPDATE signal, to * direct the output to a different port. * Verify that the output arrives at the new port */ int test_stdio_update(void) { char *old_listener_url, *new_listener_url; char *old_job_contact; int rc; char *callback_contact; char *old_rsl, *new_rsl; test_monitor_t monitor; const char rsl_spec[] = "&(executable=/bin/sh)" "(arguments=-c 'sleep 30; echo hello;')" "(rsl_substitution = (TEST_GASS_URL %s))" "(stdout = $(TEST_GASS_URL)/out)"; const char stdio_update_rsl_spec[] = "&(stdout = %s/out)"; globus_mutex_init(&monitor.mutex, NULL); globus_cond_init(&monitor.cond, NULL); memset(monitor.old_output, 0, sizeof(monitor.old_output)); memset(monitor.new_output, 0, sizeof(monitor.new_output)); monitor.old_request = GLOBUS_NULL_HANDLE; monitor.new_request = GLOBUS_NULL_HANDLE; monitor.status = GLOBUS_GRAM_PROTOCOL_JOB_STATE_UNSUBMITTED; monitor.failure_code = 0; /* Create a pair of listeners and get their base URLs. The job will be * submitted with stdout directed to the first, then redirected to the * second via a stdio update signal */ rc = globus_gass_transfer_create_listener( &monitor.old_listener, NULL, "https"); test_assert_gram_rc_equals(rc, GLOBUS_SUCCESS); test_assert(monitor.old_listener != GLOBUS_NULL_HANDLE); old_listener_url = globus_gass_transfer_listener_get_base_url( monitor.old_listener); test_assert(old_listener_url != NULL); rc = globus_gass_transfer_register_listen( monitor.old_listener, test_l_old_listener_callback, &monitor); test_assert_gram_rc_equals(rc, GLOBUS_SUCCESS); rc = globus_gass_transfer_create_listener( &monitor.new_listener, NULL, "https"); test_assert_gram_rc_equals(rc, GLOBUS_SUCCESS); test_assert(monitor.new_listener != GLOBUS_NULL_HANDLE); new_listener_url = globus_gass_transfer_listener_get_base_url( monitor.new_listener); test_assert(new_listener_url != NULL); rc = globus_gass_transfer_register_listen( monitor.new_listener, test_l_new_listener_callback, &monitor); test_assert(rc == GLOBUS_SUCCESS); old_rsl = globus_common_create_string(rsl_spec, old_listener_url); test_assert(old_rsl != NULL); /* Submit the job, do the two-phase commit, then submit a restart * request with the new stdout destination */ rc = globus_gram_client_callback_allow( test_l_gram_callback, &monitor, &callback_contact); test_assert_gram_rc_equals(rc, GLOBUS_SUCCESS); test_assert(callback_contact != NULL); rc = globus_gram_client_job_request( contact_string, old_rsl, GLOBUS_GRAM_PROTOCOL_JOB_STATE_UNSUBMITTED| GLOBUS_GRAM_PROTOCOL_JOB_STATE_STAGE_IN| GLOBUS_GRAM_PROTOCOL_JOB_STATE_PENDING| GLOBUS_GRAM_PROTOCOL_JOB_STATE_ACTIVE| GLOBUS_GRAM_PROTOCOL_JOB_STATE_STAGE_OUT| GLOBUS_GRAM_PROTOCOL_JOB_STATE_DONE| GLOBUS_GRAM_PROTOCOL_JOB_STATE_FAILED, callback_contact, &old_job_contact); test_assert_gram_rc_equals(rc, GLOBUS_SUCCESS); test_assert(old_job_contact != NULL); globus_mutex_lock(&monitor.mutex); while (monitor.status == GLOBUS_GRAM_PROTOCOL_JOB_STATE_UNSUBMITTED) { globus_cond_wait(&monitor.cond, &monitor.mutex); } new_rsl = globus_common_create_string( stdio_update_rsl_spec, new_listener_url); test_assert(new_rsl != NULL); rc = globus_gram_client_job_signal( old_job_contact, GLOBUS_GRAM_PROTOCOL_JOB_SIGNAL_STDIO_UPDATE, new_rsl, &monitor.status, &monitor.failure_code); test_assert_gram_rc_equals(rc, GLOBUS_SUCCESS); /* Wait for job to complete. After it's done, check to see which * destination got stdout */ while (monitor.status != GLOBUS_GRAM_PROTOCOL_JOB_STATE_DONE && monitor.status != GLOBUS_GRAM_PROTOCOL_JOB_STATE_FAILED) { globus_cond_wait(&monitor.cond, &monitor.mutex); } if (monitor.old_request) { globus_gass_transfer_fail(monitor.old_request, test_l_gass_fail, NULL); } globus_mutex_unlock(&monitor.mutex); if (monitor.new_output[0] == 0) { fprintf(stderr, "Didn't get expected output to new handle\n"); test_assert(strcmp((char *) monitor.new_output, "hello\n") == 0); } if (monitor.old_output[0] != 0) { fprintf(stderr, "Unexpected output to old handle: %s", monitor.old_output); test_assert(monitor.old_output[0] == 0); } return rc; }
int main(int argc, char *argv[]) { int rc = 1; monitor_t monitor; char * rsl; if (argc < 4 || (!globus_l_get_mode(&monitor, argv[2])) || ((monitor.timeout = atoi(argv[3])) < 0)) { globus_libc_fprintf(stderr, "Usage: %s RM-CONTACT MODE SAVE_STATE TIMEOUT\n" " RM-CONTACT: resource manager contact\n" " MODE: no-commit|no-commit-end|commit|late-commit-end\n" " TIMEOUT: two-phase timeout in seconds\n", argv[0]); goto error_exit; } rc = globus_module_activate(GLOBUS_GRAM_CLIENT_MODULE); if (rc != GLOBUS_SUCCESS) { globus_libc_fprintf(stderr, "failure activating GLOBUS_GRAM_CLIENT_MODULE: %s\n", globus_gram_client_error_string(rc)); goto error_exit; } rsl = globus_common_create_string(format, monitor.timeout); if (rsl == NULL) { globus_libc_fprintf(stderr, "failure allocating rsl string\n"); goto deactivate_exit; } globus_mutex_init(&monitor.mutex, NULL); globus_cond_init(&monitor.cond, NULL); monitor.job_contact = NULL; monitor.callback_contact = NULL; rc = globus_gram_client_callback_allow( globus_l_state_callback, &monitor, &monitor.callback_contact); if (rc != GLOBUS_SUCCESS || monitor.callback_contact == NULL) { globus_libc_fprintf(stderr, "failure allowing callbacks\n"); rc = -1; goto destroy_monitor_exit; } globus_mutex_lock(&monitor.mutex); rc = globus_gram_client_job_request( argv[1], rsl, GLOBUS_GRAM_PROTOCOL_JOB_STATE_ALL, monitor.callback_contact, &monitor.job_contact); if (monitor.job_contact != NULL) { globus_libc_printf("%s\n", monitor.job_contact); } if (rc != GLOBUS_GRAM_PROTOCOL_ERROR_WAITING_FOR_COMMIT) { if (rc == GLOBUS_SUCCESS) { globus_libc_fprintf(stderr, "job manager did not return " "GLOBUS_GRAM_PROTOCOL_ERROR_COMMIT_TIMED_OUT\n"); rc = -1; } else { globus_libc_fprintf(stderr, "failure submitting job request [%d]: %s\n", rc, globus_gram_client_error_string(rc)); } goto disallow_exit; } rc = 0; if (monitor.mode == no_commit) { goto disallow_exit; } rc = globus_gram_client_job_signal( monitor.job_contact, GLOBUS_GRAM_PROTOCOL_JOB_SIGNAL_COMMIT_REQUEST, NULL, &monitor.job_status, &monitor.failure_code); if (rc != GLOBUS_SUCCESS) { globus_libc_fprintf(stderr, "failure sending commit signal: %s\n", globus_gram_client_error_string(rc)); goto disallow_exit; } while (monitor.job_status != GLOBUS_GRAM_PROTOCOL_JOB_STATE_DONE && monitor.job_status != GLOBUS_GRAM_PROTOCOL_JOB_STATE_FAILED) { globus_cond_wait(&monitor.cond, &monitor.mutex); } if (monitor.mode == no_commit_end) { rc = 0; goto disallow_exit; } else if (monitor.mode == late_commit_end) { rc = 0; sleep(monitor.timeout + 1); } rc = globus_gram_client_job_signal( monitor.job_contact, GLOBUS_GRAM_PROTOCOL_JOB_SIGNAL_COMMIT_END, NULL, &monitor.job_status, &monitor.failure_code); if (rc != GLOBUS_SUCCESS) { globus_libc_fprintf(stderr, "failure sending commit end signal: %s\n", globus_gram_client_error_string(rc)); goto disallow_exit; } disallow_exit: if (monitor.job_contact != NULL) { globus_gram_client_job_contact_free(monitor.job_contact); } globus_mutex_unlock(&monitor.mutex); globus_gram_client_callback_disallow(monitor.callback_contact); destroy_monitor_exit: if (monitor.callback_contact != NULL) { free(monitor.callback_contact); } globus_mutex_destroy(&monitor.mutex); globus_cond_destroy(&monitor.cond); free(rsl); deactivate_exit: globus_module_deactivate_all(); error_exit: return rc; }