Software Links
Getting Started
- Doc Structure
- A Globus Primer
- Globus Is Modular!
- Quickstart
- Installing GT
- Platform Notes
- GT Developer's Guide
- GT User's Guide (coming soon)
- Migrating from GT2
- Migrating from GT3
Reference
- Best Practices
- Coding Guidelines
- API docs
- Public Interfaces (coming soon)
- Resource Properties
- Samples
- Glossary
- Performance Studies (coming soon)
Manuals
Common Runtime
Security
- Non-WS (General) Security
- WS Java Security
- Message-level
- Authz Framework
- CAS
- Delegation Service
- MyProxy
- GSI-OpenSSH
- SimpleCA
- SGAS
Data Mgt
MDS4
Execution Mgt
Table of Contents
Here we provide some scenarios for using C WS-Core that aren't described in the tutorials.
Both clients and services may need to create or parse instances of
xsd_any or xsd_anyType
types. This is necessary when the XML schema defines a type that includes the
xsd_any or xsd_anyType
as a type for one of its elements, such as:
<xsd:complexType name="TemporalType"> <xsd:sequence>
<xsd:any minOccurs="1" maxOccurs="1" processContents="lax" />
</xsd:sequence> </xsd:complexType> <xsd:element
name="Temporal" type="tns:TemporalType"/> The content of an instance of TemporalType is not
restricted by the schema definition, and so must be handled specially at runtime. For
serialization and deserialization of wildcard elements, a special global variable of type
globus_xsd_type_info_t is associated with each type
that can be set on the wildcard. For example, if a user wanted an instance of
TemporalType to contain an instance of an
xsd:dateTime, the any
field must be filled in properly. The following bit of C code does this:
time_t current; TemporalType temp; xsd_QName * element; xsd_dateTime * time; /* this
is just a struct tm */ ... result = TemporalType_init_contents(&temp); /* check
result */ temp.any.any_info = &xsd_dateTime_info; result =
xsd_dateTime_init(&time); /* check result */ current = time(NULL); /* get the
current time */ result = xsd_dateTime_copy_contents( time, (xsd_dateTime
*)localtime(¤t)); /* check result */ temp.any.value = (void *)time; result =
xsd_QName_init(&element); /* check result */ element->Namespace =
globus_libc_strdup("http://temporal.com"); element->local = globus_libc_strdup("Time");
temp.any.element = element; /* now we can serialize it */ result = TemporalType_serialize(
&Temporal_qname, temp, handle, 0); /* check result */ This serializes the TemporalType to the contain the
current timestamp. The resulting serialized elements would look like this:
<time:Temporal xmlns:time="http://temporal.com">
<time:Time>Mon Apr 17 10:14:22 CDT 2005</time:Time>
</time:Temporal> If we want to serialize it to a string of the current day of the week, we would do this:
time_t current; TemporalType temp;
xsd_QName * element; xsd_string * day; /* this is just a pointer to char * */ ... result =
TemporalType_init_contents(&temp); /* check result */ temp.any.any_info =
&xsd_string_info; result = xsd_string_init_cstr(&day, "Monday"); /* check
result */ temp.any.value = (void *)day; result = xsd_QName_init(&element); /*
check result */ element->Namespace = globus_libc_strdup("http://temporal.com");
element->local = globus_libc_strdup("Day"); temp.any.element = element; /* now we can
serialize it */ result = TemporalType_serialize( &Temporal_qname, temp, handle,
0); /* check result */
This allows us to serialize the temporal time element as the day of the week. The resulting serialized elements for this code would look like this:
<time:Temporal xmlns:time="http://temporal.com">
<time:Day>Monday</time:Day> </time:Temporal>
So this allows us to inject types into wildcard elements at runtime, and demonstrates how to serialize those wildcards.
For deserialization of wildcard types, a registry is used to lookup the actual type of the element based on QName or the xsi:type attribute. The registry contains key/value pairs of QName to globus_xsd_type_info_t structures. These structures contain the appropriate information about deserializing the type.
A client may wish to perform many invocations of resource property requests to different services (or the same service) at once, without waiting for the response from one request before starting a second request. The asynchronous client stubs generated for each operation allow the client to do this. The example code below shows the implementation of the callback that gets called once the response from a resource property has been received for the CounterService.
typedef struct { globus_cond_t cond; globus_mutex_t mutex; } counter_monitor; void
get_rp_counter_value_callback( CounterService_client_handle_t handle, void * user_args,
globus_result_t result, const wsrp_GetResourcePropertyResponseType *
GetResourcePropertyResponse, CounterPortType_GetResourceProperty_fault_t fault_type, const
xsd_any * fault) { counter_monitor_t * monitor = (user_args); xsd_int * rp_value;
if(GetResourcePropertyResponse->any.elements[0].any_info != (&Value_rp_info)) {
/* error - expected Value as the first (and only) resource * property */ } rp_value =
(xsd_int *)GetResourcePropertyResponse->any.elements[0].value;
globus_mutex_lock(&monitor->mutex); monitor->value = *rp_value;
monitor->done = 1; globus_cond_signal(&monitor->cond);
globus_mutex_unlock(&monitor->mutex); } ... counter_monitor_t * monitor; monitor
= globus_malloc(sizeof(counter_monitor_t)); /* check OOM */
globus_cond_init(&monitor->cond, NULL);
globus_mutex_init(&monitor->mutex, NULL); monitor->done = 0; monitor->value
= 0; result = CounterPortType_GetResourceProperty_epr_register( client_handle,
createCounterResponse->EndpointReference, &Value_rp_qname,
get_rp_counter_value_callback, prop_monitor); if(result != GLOBUS_SUCCESS) { ... } /* do
other processing */ globus_mutex_lock(&monitor->mutex); while(!monitor->done)
{ globus_cond_wait(&monitor->cond, &monitor->mutex); /* do other
processing */ } globus_mutex_unlock(&monitor->mutex); This allows us to do other processing while the GetResourceProperty operation is invoked, and the response is returned. For something as simple as the CounterService, the wait for the callback to be called will most likely be short (unless there is network delay). For more complex services, the delay may be longer, and the client may want to perform other processing instead of just waiting.