Appendix B. Submitting a job in C using WS GRAM

The following is a general scenario for submitting a job using the C stubs and APIs. Please consult the C WS Core API, WS GRAM API documentation for details on package names for classes referenced in the code excerpts.

1. Loading the job description

    const char *                        file = "job.xml";
    globus_soap_message_handle_t        message;
    wsgram_CreateManagedJobInputType    input;

    globus_soap_message_handle_init_from_file(&message, file);

    globus_soap_message_deserialize_element_unknown(message, &element);

    if(strcmp(element.local, "job") == 0)
    {
        wsgram_JobDescriptionType *     jd;

        input.choice_value.type = wsgram_CreateManagedJobInputType_job;
        jd = &input.choice_value.value.job;

        wsgram_JobDescriptionType_deserialize(&element, jd, message, 0);
    }
    else if(strcmp(element.local, "multiJob") == 0)
    {
        wsgram_MultiJobDescriptionType *       mjd;

        input.choice_value.type = wsgram_CreateManagedJobInputType_multiJob;
        mjd = &input.choice_value.value.multiJob;

        wsgram_MultiJobDescriptionType_deserialize(&element, mjd, message, 0);
    }
    xsd_QName_destroy_contents(&element);
    globus_soap_message_handle_destroy(message);

This code sets the choice value of the wsgram_CreateManagedJobInputType to be the appropriate type depending on whether the job description is a job or multijob request.

2. Setting the security attributes

globus_soap_message_attr_t               message_attr;

globus_soap_message_attr_init(&message_attr);

/*
 * Set authentication mode to host authorization: other possibilities are
 * GLOBUS_SOAP_MESSAGE_AUTHZ_HOST_IDENTITY or
 * GLOBUS_SOAP_MESSAGE_AUTHZ_HOST_SELF.
 */
globus_soap_message_attr_set(
    message_attr,
    GLOBUS_SOAP_MESSAGE_AUTHZ_METHOD_KEY,
    NULL,
    NULL,
    (void *) GLOBUS_SOAP_MESSAGE_AUTHZ_HOST);

/*
 * Set message protection level. GLOBUS_SOAP_MESSAGE_AUTH_PROTECTION_PRIVACY
 * for encryption.
 */
globus_soap_message_attr_set(
    message_attr,
    GLOBUS_SOAP_MESSAGE_AUTH_PROTECTION_KEY,
    NULL,
    NULL,
    (void *) GLOBUS_SOAP_MESSAGE_AUTH_PROTECTION_PRIVACY);

3. Creating the factory client handle

ManagedJobFactoryService_client_handle_t    factory_handle;

result = ManagedJobFactoryService_client_init(
    &factory_handle,
    message_attr,
    NULL);

4. Querying for factory resource properties

4.1. One at a time

/*
 * localResourceManager, or other resource property names as defined in the
 * WSDL
 */
xsd_QName                                property_name =
{
    "http://www.globus.org/namespaces/2004/10/gram/job",
    "localResourceManager"
};
wsrp_GetResourcePropertyResponseType *   property_response;
int                                      fault_type;
xsd_any *                                fault;

ManagedJobFactoryPortType_GetResourceProperty(
    factory_handle,
    endpoint,
    &property_name,
    &property_response,
    (ManagedJobFactoryPortType_GetResourceProperty_fault_t *) &fault_type,
    &fault);

If this is successful, then property_response's any field will contain the deserialized data in the value field of the first element in the array.

xsd_string * localResourceManager = property_response->any.elements[0].value;

printf("local resource manager is %s\n", *localResourceManager);

5. Creating the notification consumer

The notification consumer can be either passed in as part of the wsgram_CreateManagedJobInputType or through a separate invocation of ManagedJobPortType_Subscribe_epr().

    globus_service_engine_t             engine;
    wsa_EndpointReferenceType           consumer_reference;
    
    globus_service_engine_init(&engine, NULL, NULL, NULL, NULL, NULL);

    globus_notification_create_consumer(
            &consumer_reference,
            engine,
            notify_callback,
            NULL);

6. Creating the job resource

First, prepare the other parts of the wsgram_CreateManagedJobInputType structure.

/*
 * You can set input.InitialTerminationTime to be a timeout if interested.
 * The xsd_dateTime type is a struct tm pointer.
 */
time_t                                  term_time = time(NULL);
globus_uuid_t                           uuid;
wsa_AttributedURI *                     job_id;
wsa_EndpointReferenceType *             factory_epr;
xsd_any *                               reference_property;
wsgram_CreateManagedJobOutputType *     output = NULL;
xsd_QName                               factory_reference_id_qname =
{
    "http://www.globus.org/namespaces/2004/10/gram/job",
    "ResourceID"
};

term_time += 60 * 60; /* 1 hour later */
xsd_dateTime_copy(&input.InitialTerminationTime, gmtime(&term_time));

/*
 * Set unique JobID. This is used to reliably create jobs and check for status.
 */
globus_uuid_create(&uuid);
wsa_AttributedURI_init(&job_id);
job_id->base_value = globus_common_create_string("uuid:%s", uuid.text);

/* To subscribe to notifications at create time, add the consumer's EPR to
 * the input message. Otherwise, use the EPR created above in a 
 * call to  
 */
wsnt_SubscribeType_init(&input.Subscribe);
wsa_EndpointReferenceType_copy_contents(
        &input.Subscribe.ConsumerReference,
        &consumer_reference);

xsd_any_init(&input.Subscribe->TopicExpression.any);
&input.Subscribe->TopicExpression.any->any_info =
        &xsd_QName_contents_info;
xsd_QName_copy(
    (xsd_QName **) &input.Subscribe->TopicExpression.any->any.value,
    &ManagedJobPortType_state_rp_qname);

xsd_anyURI_copy_cstr(
    &input.Subscribe->TopicExpression._Dialect,
    "http://docs.oasis-open.org/wsn/2004/06/TopicExpression/Simple");
xsd_boolean_init(&input.Subscribe->UseNotify);

*(&input.Subscribe->UseNotify) = GLOBUS_TRUE;

/* Construct the EPR of the job factory */
wsa_EndpointReferenceType_init(&factory_epr);
wsa_AttributedURI_init_contents(&factory_epr->Address);
xsd_anyURI_init_contents_cstr(&factory_epr->Address.base_value,
        globus_common_create_string(
                "https://%s:%hu/wsrf/services/%s",
                factory_host,
                factory_port,
                MANAGEDJOBFACTORYSERVICE_BASE_PATH);
wsa_ReferencePropertiesTypeinit(&factory_epr->ReferenceProperties);
reference_property = xsd_any_array_push(
        &factory_epr->ReferenceProperties.any);
reference_property->any_info = &xsd_string_info;
xsd_QName_copy(
        &reference_property->element,
        &factory_reference_id_qname);

xsd_string_copy_cstr(
        (xsd_string **) &reference_property->value,
        "Fork");
        
/* Submit the request to the service container */
ManagedJobFactoryPortType_createManagedJob_epr(
        factory_handle,
        factory_epr,
        input,
        &output,
        (ManagedJobFactoryPortType_createManagedJob_fault_t *) &fault_type,
        &fault);

If this is successful, then the output structure will be initialized with the results of the operation. Of particular interest is the managedJobEndpoint which contains the reference to the newly-created job resource.

7. Subscribing for job state notifications

In order to subscribe for job state change notifications to an existing job resource, initialize the subscribe_input used below in the same way as input.Subscribe was initialized above.

    ManagedJobService_client_handle_t   job_handle;
    wsnt_SubscribeType                  subscribe_input;
    wsnt_SubscribeResponseType *        subscribe_response;

ManagedJobService_client_init(
    &job_handle,
    message_attr,
    NULL);

ManagedJobPortType_Subscribe_epr(
    job_handle,
    output->managedJobEndpoint,
    subscribe_input,
    &subscribe_response,
    (ManagedJobPortType_Subscribe_fault_t *) &fault_type,
    &fault);

8. Releasing any state holds (if necessary)

    wsgram_ReleaseInputType             release;
    wsgram_ReleaseOutputType *          release_response = NULL;

    wsgram_ReleaseInputType_init_contents(&release);

ManagedJobPortType_release_epr(
    job_handle,
    output->managedJobEndpoint,
    &release,
    &release_response,
    (ManagedJobPortType_release_fault_t *) &fault_type,
    &fault);

9. Destroying resources

/* destroy subscription resource */
    SubscriptionManagerService_client_init    subscription_handle;
    wsnt_DestroyType                          destroy;
    wsnt_DestroyResponseType *                destroy_response = NULL;

    SubscriptionManagerService_client_init(
        &subscription_handle,
        message_attr,
        NULL);
    /* if subscription done at job creation time, use
     * output->subscriptionEndpoint in place of 
     * subscribe_response->SubscriptionReference,
     */
    SubscriptionManager_Destroy_epr(
        subscription_handle,
        subscribe_response->SubscriptionReference,
        &destroy,
        &destroy_response,
        (SubscriptionManager_Destroy_fault_t *) &fault_type,
        &fault);

    /* destroy the job resource */
    jobPort.destroy(new Destroy());
    ManagedJobPortType_Destroy_epr(
        job_handle,
        output->managedJobEndpoint,
        &destroy,
        &destroy_response,
        (ManagedJobPortType_Destroy_fault_t *) &fault_type,
        &fault);