Table of Contents
- 1. Loading the job description
- 2. Setting the security attributes
- 3. Creating the factory client handle
- 4. Querying for factory resource properties
- 5. Creating the notification consumer
- 6. Creating the job resource
- 7. Subscribing for job state notifications
- 8. Releasing any state holds (if necessary)
- 9. Destroying resources
- 10. Building a client
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 the APIs used in this example.
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.
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);
ManagedJobFactoryService_client_handle_t factory_handle; result = ManagedJobFactoryService_client_init( &factory_handle, message_attr, NULL);
/* * 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);
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);
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.
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);
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);
/* 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);
In order to build a client application, certain flags must be passed to the compiler and linker to enable them to be able to locate headers and libraries. The easiest way to do so is to generate a makefile header, which is a fragment of a Makefile which includes all of the necessary flags needed to build the application. To do this, issue the command:
%
globus-makefile-header --flavor=gcc32dbg globus_c_gram_client_bindings > Makefile.inc
Then, write your makefile to include this file and use the GLOBUS_CC, GLOBUS_LD, GLOBUS_CFLAGS, GLOBUS_LDFLAGS, and GLOBUS_PKG_LIBS macros. For example:
GLOBUS_FLAVOR_NAME=gcc32dbg include Makefile.inc CC = $(GLOBUS_CC) LD = $(GLOBUS_LD) CFLAGS = $(GLOBUS_CFLAGS) LDFLAGS = $(GLOBUS_LDFLAGS) $(GLOBUS_PKG_LIBS) client: client.c