static
int
job_status_with_info_test(void)
{
    int                                 rc;
    char *                              job_contact = NULL;
    struct monitor                      monitor;

    globus_mutex_init(&monitor.mutex, NULL);
    globus_cond_init(&monitor.cond, NULL);
    monitor.done = GLOBUS_FALSE;
    monitor.job_state = GLOBUS_GRAM_PROTOCOL_JOB_STATE_UNSUBMITTED;
    monitor.protocol_error_code = GLOBUS_SUCCESS;

    rc = globus_gram_client_job_request(
            rm_contact,
            "&(executable=/bin/sleep)(arguments=60)",
            0,
            NULL,
            &job_contact);

    test_assert(rc == GLOBUS_SUCCESS,
            ("Failed submitting sleep job because %s (%d)",
                    globus_gram_protocol_error_string(rc),
                    rc));
    rc = globus_gram_client_register_job_status_with_info(
            job_contact,
            NULL,
            info_callback,
            &monitor);
    free(job_contact);

    test_assert(rc == GLOBUS_SUCCESS,
            ("Failed registering job_status because %s (%d)",
                    globus_gram_protocol_error_string(rc),
                    rc));

    globus_mutex_lock(&monitor.mutex);
    while (!monitor.done)
    {
        globus_cond_wait(&monitor.cond, &monitor.mutex);
    }
    globus_mutex_unlock(&monitor.mutex);

    test_assert(monitor.protocol_error_code == GLOBUS_SUCCESS,
            ("Failed to determine job status because %s (%d)",
                    globus_gram_protocol_error_string(
                            monitor.protocol_error_code),
                    monitor.protocol_error_code));

    test_assert(monitor.job_state != 0,
            ("Failed to determine job status"));

                    
    rc = GLOBUS_SUCCESS;

    return rc;
}
/* submit a job without a callback contact, register a callback
 * contact, wait for job to terminate
 */
int
test1()
{
    char *				callback_contact;
    char *				job_contact;
    int					rc;
    monitor_t				monitor;

    rc = globus_module_activate(GLOBUS_GRAM_CLIENT_MODULE);

    if(rc)
    {
	goto out;
    }

    globus_mutex_init(&monitor.mutex ,GLOBUS_NULL);
    globus_cond_init(&monitor.cond, GLOBUS_NULL);
    monitor.state = GLOBUS_GRAM_PROTOCOL_JOB_STATE_PENDING;

    rc = globus_gram_client_callback_allow(gram_state_callback,
	                                   &monitor,
					   &callback_contact);
    if(rc != GLOBUS_SUCCESS)
    {
	fprintf(stderr,
		"Error creating callback contact %s.\n",
		globus_gram_client_error_string(rc));

	goto error_exit;
    }

    globus_mutex_lock(&monitor.mutex);
    rc = globus_gram_client_job_request(
	    resource_manager_contact,
	    "&(executable=/bin/sleep)(arguments=10)",
	    GLOBUS_GRAM_PROTOCOL_JOB_STATE_ALL,
	    GLOBUS_NULL,
	    &job_contact);

    if(rc != GLOBUS_SUCCESS)
    {
	fprintf(stderr,
		"Failed submitting job request because %s.\n",
		globus_gram_client_error_string(rc));

	goto destroy_callback_contact;
    }
    
    rc = globus_gram_client_job_callback_register(
	    job_contact,
	    GLOBUS_GRAM_PROTOCOL_JOB_STATE_FAILED|
	    GLOBUS_GRAM_PROTOCOL_JOB_STATE_DONE,
	    callback_contact,
	    &monitor.state,
	    &monitor.errorcode);

    if(rc != GLOBUS_SUCCESS)
    {
	fprintf(stderr,
		"Error registering callback contact because %s.\n",
		globus_gram_client_error_string(rc));

	goto destroy_callback_contact;
    }

    while(monitor.state != GLOBUS_GRAM_PROTOCOL_JOB_STATE_FAILED &&
	  monitor.state != GLOBUS_GRAM_PROTOCOL_JOB_STATE_DONE)
    {
	globus_cond_wait(&monitor.cond, &monitor.mutex);
    }

    rc = monitor.errorcode;

destroy_callback_contact:
    globus_gram_client_callback_disallow(callback_contact);
    globus_libc_free(callback_contact);
    globus_libc_free(job_contact);
    globus_mutex_unlock(&monitor.mutex);
error_exit:
    globus_mutex_destroy(&monitor.mutex);
    globus_cond_destroy(&monitor.cond);
    globus_module_deactivate(GLOBUS_GRAM_CLIENT_MODULE);

out:
    return rc;
}
int main(int argc, char *argv[])
{
    char *                              callback_contact;
    char *                              job_contact;
    char *                              rm_contact;
    monitor_t                           monitor;
    int                                 rc = 0;

    LTDL_SET_PRELOADED_SYMBOLS();

    printf("1..1\n");
    rm_contact = getenv("CONTACT_STRING");

    if (argc == 2)
    {
        rm_contact = argv[1];
    }

    if (rm_contact == NULL)
    {
        fprintf(stderr, "Usage: %s resource-manager-contact\n", argv[0]);
        exit(1);
    }

    rc = globus_module_activate(GLOBUS_COMMON_MODULE);
    if(rc)
    {
        goto end;
    }
    rc = globus_module_activate(GLOBUS_GRAM_CLIENT_MODULE);
    if(rc)
    {
        goto disable_modules;
    }

    globus_mutex_init(&monitor.mutex ,GLOBUS_NULL);
    globus_cond_init(&monitor.cond, GLOBUS_NULL);
    monitor.state = GLOBUS_GRAM_PROTOCOL_JOB_STATE_PENDING;

    rc = globus_gram_client_callback_allow(gram_state_callback,
                                           &monitor,
                                           &callback_contact);
    if(rc != GLOBUS_SUCCESS)
    {
        fprintf(stderr,
                "Error creating callback contact %s.\n",
                globus_gram_client_error_string(rc));

        goto error_exit;
    }

    globus_mutex_lock(&monitor.mutex);
    rc = globus_gram_client_job_request(
            rm_contact,
            "&(executable=/bin/sleep)(arguments=300)",
            GLOBUS_GRAM_PROTOCOL_JOB_STATE_ALL,
            callback_contact,
            &job_contact);

    if(rc != GLOBUS_SUCCESS)
    {
        fprintf(stderr,
                "Error submitting job request %s.\n",
                globus_gram_client_error_string(rc));

        goto destroy_callback_contact;
    }

    while(monitor.state != GLOBUS_GRAM_PROTOCOL_JOB_STATE_ACTIVE &&
          monitor.state != GLOBUS_GRAM_PROTOCOL_JOB_STATE_FAILED &&
          monitor.state != GLOBUS_GRAM_PROTOCOL_JOB_STATE_DONE)
    {
        globus_cond_wait(&monitor.cond, &monitor.mutex);
    }

    if(monitor.state == GLOBUS_GRAM_PROTOCOL_JOB_STATE_ACTIVE)
    {
        rc = globus_gram_client_job_cancel(job_contact);
        if(rc != GLOBUS_SUCCESS)
        {
            fprintf(stderr,
                    "Error cancelling job %s.\n",
                    globus_gram_client_error_string(rc));

            goto destroy_callback_contact;
        }
    }

    while(monitor.state != GLOBUS_GRAM_PROTOCOL_JOB_STATE_DONE &&
          monitor.state != GLOBUS_GRAM_PROTOCOL_JOB_STATE_FAILED)
    {
        globus_cond_wait(&monitor.cond, &monitor.mutex);
    }
    rc = monitor.errorcode;
    if(rc == GLOBUS_GRAM_PROTOCOL_ERROR_USER_CANCELLED)
    {
        rc = GLOBUS_SUCCESS;
    }
destroy_callback_contact:
    globus_mutex_unlock(&monitor.mutex);
    globus_gram_client_callback_disallow(callback_contact);
    free(callback_contact);
    free(job_contact);
error_exit:
    globus_mutex_destroy(&monitor.mutex);
    globus_cond_destroy(&monitor.cond);
disable_modules:
    globus_module_deactivate_all();
end:
    printf("%s - cancel-test\n", rc == 0 ? "ok" : "not ok");
    return rc;
}
/* 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;
}