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;
}
/* 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[])
{
    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;
}