1 /*
2  * Copyright 1999-2006 University of Chicago
3  * 
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  * 
8  * http://www.apache.org/licenses/LICENSE-2.0
9  * 
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 #include "globus_i_wsrf_service_group.h"
18
19 #include "globus_xml_buffer.h"
20
21 #include "wssg_EntryType.h"
22 #include "wssg_Entry.h"
23
24 #include "wssg_ServiceGroupEPR.h"
25 #include "wssg_MemberEPR.h"
26 #include "wssg_Content.h"
27
28 #ifndef GLOBUS_DONT_DOCUMENT_INTERNAL
29 /**
30  * Structure containing information about how to access a service group
31  * entry and its containing group.
32  *
33  */
34 typedef struct
35 {
36     wsa_EndpointReferenceType           service_group_epr;
37     wsa_EndpointReferenceType           entry_epr;
38     char *                              service_path;
39 }
40 globus_service_group_entry_info_t;
41
42 static
43 globus_result_t
44 globus_l_service_group_entry_create_epr(
45     const wsa_AttributedURI *           entry_uri,
46     const char *                        resource_id,
47     wsa_EndpointReferenceType **        sge_epr_res);
48
49 static
50 globus_result_t
51 globus_l_service_group_create_entry(
52     globus_wsrf_service_group_entry_t * entry,
53     const char *                        resource_id,
54     const wsa_EndpointReferenceType *   entry_epr,
55     const wsa_EndpointReferenceType *   service_epr,
56     const xsd_anyType *                 content);
57
58 static
59 globus_result_t
60 globus_l_service_group_entry_create_resource(
61     const char *                        resource_id,
62     const wsa_EndpointReferenceType *   group_epr,
63     const wsa_EndpointReferenceType *   member_epr,
64     const wsa_EndpointReferenceType *   entry_epr,
65     const xsd_anyType *                 content,
66     const xsd_dateTime *                initial_termination_time);
67
68 static
69 char *
70 globus_l_epr_to_path(
71     const wsa_EndpointReferenceType *   epr);
72
73 static
74 time_t
75 globus_l_timegm(
76     const struct tm *                   tm);
77
78 static
79 void
80 globus_l_service_group_entry_destructor(
81     void *                              p);
82
83 static
84 globus_result_t
85 globus_l_service_group_check_membership(
86     globus_wsrf_service_group_t         sg,
87     const wsa_EndpointReferenceType *   service_epr,
88     const xsd_anyType *                 content);
89
90 #define WSSG_NAMESPACE \
91     "http://docs.oasis-open.org/wsrf/2004/06/wsrf-WS-ServiceGroup-1.2-draft-01.xsd"
92
93 #endif
94
95 /**
96  * Add a service entry to a service group
97  * @ingroup wssg
98  *
99  * Creates a new entry in a service group. This new entry will be created if the
100  * @a content element matches the membership content rule used to create the
101  * service group. The EPR to contact the new entry will be returned in the
102  * @a new_service_group_entry_epr parameter. The providers associated with the
103  * entry service (selected at service group creation time) will be initialized
104  * when the entry is created.
105  *
106  * @param service_group_epr
107  *     EPR of the service group to add the new entry to.
108  * @param service_epr
109  *     EPR of the service to add to the group.
110  * @param content
111  *     Content value to be associated with @a service_epr in the service group
112  *     entry resource. The element used for the content must match the
113  *     membership content rule of the service.
114  * @param initial_termination_time
115  *     Optional initial termination time of the entry. If this is NULL, then
116  *     the entry will last until either explicitly destroyed or until the group
117  *     is destroyed.
118  * @param new_service_group_entry_epr
119  *     Pointer to be set to contain EPR of the new service group entry. This
120  *     EPR must be freed by the caller by calling
121  *     wsa_EndpointReferenceType_destroy().
122  *
123  * @retval GLOBUS_SUCCESS
124  * @retval #GLOBUS_SERVICE_GROUP_ERROR_TYPE_NULL_PARAMETER
125  * @retval #GLOBUS_SERVICE_GROUP_ERROR_TYPE_OUT_OF_MEMORY
126  * @retval #GLOBUS_SERVICE_GROUP_ERROR_TYPE_UNKNOWN
127  * @retval #GLOBUS_SERVICE_GROUP_ERROR_TYPE_INVALID_CONTENT
128  */
129 globus_result_t
130 globus_service_group_add(
131     const wsa_EndpointReferenceType *   service_group_epr,
132     const wsa_EndpointReferenceType *   service_epr,
133     const xsd_anyType *                 content,
134     const xsd_dateTime *                initial_termination_time,
135     wsa_EndpointReferenceType **        new_service_group_entry_epr)
136 47 {
137 47     globus_wsrf_service_group_t         sg;
138 47     globus_wsrf_service_group_entry_t   sge;
139 47     wsa_EndpointReferenceType *         sge_epr;
140 47     globus_result_t                     result;
141 47     int                                 rc;
142 47     globus_uuid_t                       uuid;
143 47     GlobusFuncName(globus_service_group_add);
144
145 47     GlobusServiceGroupDebugEnter();
146
147 47     if (service_group_epr == NULL ||
148         new_service_group_entry_epr == NULL ||
149         service_epr == NULL)
150     {
151 3         result = GLOBUS_SERVICE_GROUP_NULL_PARAMETER();
152
153 3         goto out;
154     }
155
156 44     *new_service_group_entry_epr = NULL;
157
158     /* If successful, sg is locked */
159 44     result = globus_i_service_group_lookup(
160             service_group_epr,
161             &sg);
162
163 44     if (result != GLOBUS_SUCCESS)
164     {
165 1         goto out;
166     }
167
168 43     result = globus_l_service_group_check_membership(
169             sg,
170             service_epr,
171             content);
172 43     if (result != GLOBUS_SUCCESS)
173     {
174 2         goto unlock_sg_out;
175     }
176
177     /* Create UUID to be used for the Reference Properties of the EPR
178      * and the resource_id used by core
179      */
180 41     rc = globus_uuid_create(&uuid);
181 41     if (rc != GLOBUS_SUCCESS)
182     {
183 0         goto unlock_sg_out;
184     }
185
186     /* Create an EPR to the ServiceGroupEntry resource we will create below */
187 41     result = globus_l_service_group_entry_create_epr(
188             &sg->service_group_entry_uri,
189             &uuid.text[0],
190             &sge_epr);
191
192 41     if (result != GLOBUS_SUCCESS)
193     {
194 0         goto unlock_sg_out;
195     }
196
197     /* Create entry which we will stick into the entries hash for the group
198      * This will contain the information needed for the wssg:Entry property
199      * of the ServiceGroup resource.
200      */
201 41     result = globus_l_service_group_create_entry(
202             &sge,
203             &uuid.text[0],
204             sge_epr,
205             service_epr,
206             content);
207 41     if (result != GLOBUS_SUCCESS)
208     {
209 0         goto destroy_sge_epr_out;
210     }
211
212 41     rc = globus_hashtable_insert(
213             &sg->entries,
214             sge->resource_id,
215             sge);
216
217 41     if (rc != GLOBUS_SUCCESS)
218     {
219 0         result = GLOBUS_SERVICE_GROUP_OUT_OF_MEMORY();
220
221 0         goto destroy_sge_out;
222     }
223
224     /* Now create the resource associated with the ServiceGroupEntry.
225      */
226 41     result = globus_l_service_group_entry_create_resource(
227             &uuid.text[0],
228             &sg->service_group_epr,
229             &sge->entry->MemberServiceEPR,
230             sge_epr,
231             content,
232             initial_termination_time);
233
234 41     if (sge->entry && sg->add_callback != NULL)
235     {
236 3         sg->add_callback(sg->callback_arg, sge->entry);
237     }
238
239 41     if (result == GLOBUS_SUCCESS)
240     {
241 41         *new_service_group_entry_epr = sge_epr;
242     }
243
244     /* cleanup if an error occurred */
245 41     if (result != GLOBUS_SUCCESS)
246     {
247 0         globus_hashtable_remove(
248                 &sg->entries,
249                 sge->resource_id);
250
251 destroy_sge_out:
252 0         free(sge->resource_id);
253 0         wssg_EntryType_destroy(sge->entry);
254 0         free(sge);
255
256 destroy_sge_epr_out:
257 0         wsa_EndpointReferenceType_destroy(sge_epr);
258     }
259
260 unlock_sg_out:
261 43     GlobusServiceGroupUnlock(sg);
262
263 out:
264 47     GlobusServiceGroupDebugExit();
265 47     return result;
266 }
267 /* globus_service_group_add() */
268
269 #ifndef GLOBUS_DONT_DOCUMENT_INTERNAL
270 /**
271  * Create an endpoint reference to a new service group entry.
272  *
273  * @param entry_uri
274  * @param resource_id
275  * @param sge_epr_res
276  */
277 static
278 globus_result_t
279 globus_l_service_group_entry_create_epr(
280     const wsa_AttributedURI *           entry_uri,
281     const char *                        resource_id,
282     wsa_EndpointReferenceType **        sge_epr_res)
283 41 {
284 41     wsa_EndpointReferenceType *         sge_epr = NULL;
285 41     xsd_any *                           refprop = NULL;
286 41     globus_result_t                     result;
287 41     GlobusFuncName(globus_l_service_group_entry_create_epr);
288
289 41     GlobusServiceGroupDebugEnter();
290 41     *sge_epr_res = NULL;
291
292 41     result = wsa_EndpointReferenceType_init(&sge_epr);
293 41     if (result != GLOBUS_SUCCESS)
294     {
295 0         result = GLOBUS_SERVICE_GROUP_OUT_OF_MEMORY();
296
297 0         goto out;
298     }
299 41     sge_epr->Address.base_value = globus_libc_strdup(
300             entry_uri->base_value);
301 41     if (sge_epr->Address.base_value == NULL)
302     {
303 0         result = GLOBUS_SERVICE_GROUP_OUT_OF_MEMORY();
304
305 0         goto destroy_sge_epr_out;
306     }
307
308 41     result = wsa_ReferencePropertiesType_init(
309             &sge_epr->ReferenceProperties);
310 41     if (result != GLOBUS_SUCCESS)
311     {
312 0         result = GLOBUS_SERVICE_GROUP_OUT_OF_MEMORY();
313
314 0         goto destroy_sge_epr_out;
315     }
316
317 41     refprop = xsd_any_array_push(&sge_epr->ReferenceProperties->any);
318
319 41     if (refprop == NULL)
320     {
321 0         result = GLOBUS_SERVICE_GROUP_OUT_OF_MEMORY();
322
323 0         goto destroy_sge_epr_out;
324     }
325 41     refprop->any_info = &xsd_string_info;
326 41     result = xsd_string_init_cstr(
327             (xsd_string **) &refprop->value,
328             globus_libc_strdup(resource_id));
329 41     if (result != GLOBUS_SUCCESS)
330     {
331 0         goto destroy_sge_epr_out;
332     }
333 41     result = xsd_QName_init(&refprop->element);
334     
335 41     if (result != GLOBUS_SUCCESS)
336     {
337 0         result = GLOBUS_SERVICE_GROUP_OUT_OF_MEMORY();
338
339 0         goto destroy_sge_epr_out;
340     }
341 41     refprop->element->Namespace = globus_libc_strdup(WSSG_NAMESPACE);
342 41     if (refprop->element->Namespace == GLOBUS_NULL)
343     {
344 0         result = GLOBUS_SERVICE_GROUP_OUT_OF_MEMORY();
345
346 0         goto destroy_sge_epr_out;
347     }
348 41     refprop->element->local = globus_libc_strdup("EntryID");
349 41     if (refprop->element->local == GLOBUS_NULL)
350     {
351 0         result = GLOBUS_SERVICE_GROUP_OUT_OF_MEMORY();
352
353 0         goto destroy_sge_epr_out;
354     }
355
356 41     *sge_epr_res = sge_epr;
357
358 destroy_sge_epr_out:
359 41     if (result != GLOBUS_SUCCESS)
360     {
361 0         wsa_EndpointReferenceType_destroy(sge_epr);
362     }
363 out:
364
365 41     GlobusServiceGroupDebugExit();
366 41     return result;
367 }
368 /* globus_l_service_group_entry_create_epr() */
369
370
371 static
372 globus_result_t
373 globus_l_service_group_create_entry(
374     globus_wsrf_service_group_entry_t * entry,
375     const char *                        resource_id,
376     const wsa_EndpointReferenceType *   entry_epr,
377     const wsa_EndpointReferenceType *   service_epr,
378     const xsd_anyType *                 content)
379 41 {
380 41     globus_wsrf_service_group_entry_t   sge;
381 41     globus_result_t                     result;
382 41     GlobusFuncName(globus_l_service_group_create_entry);
383
384 41     GlobusServiceGroupDebugEnter();
385 41     *entry = NULL;
386
387     /* Create the entry struct we will put in the hash for the service group */
388 41     sge = malloc(sizeof(globus_i_wsrf_service_group_entry_t));
389
390 41     if (sge == NULL)
391     {
392 0         result = GLOBUS_SERVICE_GROUP_OUT_OF_MEMORY();
393
394 0         goto out;
395     }
396 41     result = wssg_EntryType_init(&sge->entry);
397
398 41     if (result != GLOBUS_SUCCESS)
399     {
400 0         result = GLOBUS_SERVICE_GROUP_OUT_OF_MEMORY();
401
402 0         goto free_sge_out;
403     }
404
405 41     sge->entry->ServiceGroupEntryEPR = NULL;
406 41     result = wsa_EndpointReferenceType_copy(
407             &sge->entry->ServiceGroupEntryEPR,
408             entry_epr);
409
410 41     if (result != GLOBUS_SUCCESS)
411     {
412 0         result = GLOBUS_SERVICE_GROUP_OUT_OF_MEMORY();
413
414 0         goto destroy_entry_out;
415     }
416 41     result = wsa_EndpointReferenceType_copy_contents(
417             &sge->entry->MemberServiceEPR,
418             service_epr);
419 41     if (result != GLOBUS_SUCCESS)
420     {
421 0         result = GLOBUS_SERVICE_GROUP_OUT_OF_MEMORY();
422
423 0         goto destroy_entry_out;
424     }
425
426     /* Instead of copying the Content element here, we'll do it when
427      * the entries list is requested via
428      * globus_wsrf_service_group_get_entries(). The only version of the
429      * data in memory will be in the service group entry's resource list
430      */
431
432 41     sge->resource_id = globus_libc_strdup(resource_id);
433 41     if (sge->resource_id == NULL)
434     {
435 0         goto destroy_entry_out;
436     }
437
438 41     *entry = sge;
439
440 41     if (result != GLOBUS_SUCCESS)
441     {
442 destroy_entry_out:
443 0         wssg_EntryType_destroy((*entry)->entry);
444 free_sge_out:
445 0         free(sge);
446     }
447 out:
448 41     GlobusServiceGroupDebugExit();
449 41     return result;
450 }
451 /* globus_l_service_group_create_entry() */
452
453 static
454 globus_result_t
455 globus_l_service_group_entry_create_resource(
456     const char *                        resource_id,
457     const wsa_EndpointReferenceType *   group_epr,
458     const wsa_EndpointReferenceType *   member_epr,
459     const wsa_EndpointReferenceType *   entry_epr,
460     const xsd_anyType *                 content,
461     const xsd_dateTime *                initial_termination_time)
462 41 {
463 41     globus_resource_t                   resource;
464 41     globus_result_t                     result;
465 41     wsa_EndpointReferenceType *         tmp_epr;
466 41     xsd_anyType *                       tmp_content;
467 41     globus_extension_handle_t           ext;
468 41     globus_service_descriptor_t *       service_desc;
469 41     globus_service_group_entry_info_t * info;
470 41     int                                 rc;
471 41     GlobusFuncName(globus_l_service_group_entry_create_resource);
472
473 41     GlobusServiceGroupDebugEnter();
474 41     result = globus_resource_create(resource_id, &resource);
475 41     if (result != GLOBUS_SUCCESS)
476     {
477 0         result = GLOBUS_SERVICE_GROUP_OUT_OF_MEMORY();
478
479 0         goto out;
480     }
481
482 41     info = calloc(1, sizeof(globus_service_group_entry_info_t));
483 41     if (info == NULL)
484     {
485 0         result = GLOBUS_SERVICE_GROUP_OUT_OF_MEMORY();
486
487 0         goto destroy_resource_out;
488     }
489
490     /* This is a little bit of a hack. What this key is used for is to
491      * have a function called when the SGE resource is destroyed. When that 
492      * occurs, the function will try to remove the entry from the containing
493      * group if possible.
494      */
495 41     result = globus_resource_set_resource_specific_by_key(
496             resource,
497             "wssg:DestructionInfo",
498             info,
499             globus_l_service_group_entry_destructor);
500
501 41     if (result != GLOBUS_SUCCESS)
502     {
503 0         result = GLOBUS_SERVICE_GROUP_OUT_OF_MEMORY();
504
505 0         free(info);
506
507 0         goto destroy_resource_out;
508     }
509
510 41     result = wsa_EndpointReferenceType_copy_contents(
511             &info->entry_epr,
512             entry_epr);
513 41     if (result != GLOBUS_SUCCESS)
514     {
515 0         result = GLOBUS_SERVICE_GROUP_OUT_OF_MEMORY();
516
517 0         goto destroy_resource_out;
518     }
519
520 41     result = wsa_EndpointReferenceType_copy_contents(
521             &info->service_group_epr,
522             group_epr);
523 41     if (result != GLOBUS_SUCCESS)
524     {
525 0         result = GLOBUS_SERVICE_GROUP_OUT_OF_MEMORY();
526
527 0         goto destroy_resource_out;
528     }
529
530     /* InitialTerminationTime maps to resource lifetime. The wsrl provider
531      * will create appropriate RPs when we initialize it below.
532      */
533 41     if (initial_termination_time != NULL)
534     {
535 2         globus_abstime_t                timeout;
536
537 2         timeout.tv_sec = globus_l_timegm(initial_termination_time);
538 2         timeout.tv_nsec = 0;
539
540 2         result = globus_resource_set_destroy_time(
541                 resource,
542                 &timeout);
543
544 2         if (result != GLOBUS_SUCCESS)
545         {
546 0             result = GLOBUS_SERVICE_GROUP_OUT_OF_MEMORY();
547
548 0             goto destroy_resource_out;
549         }
550     }
551
552     /* Initialize ResourceProperties with values passed to us */
553     /* ServiceGroupEPR: Contains a reference to the ServiceGroup this
554      * entry is a member of.
555      */
556 41     result = wsa_EndpointReferenceType_copy(
557             &tmp_epr,
558             group_epr);
559
560 41     if (result != GLOBUS_SUCCESS)
561     {
562 0         result = GLOBUS_SERVICE_GROUP_OUT_OF_MEMORY();
563
564 0         goto destroy_resource_out;
565     }
566
567 41     result = globus_resource_create_property(
568             resource,
569             &wssg_ServiceGroupEPR_qname,
570             &wsa_EndpointReferenceType_info,
571             tmp_epr);
572
573 41     if (result != GLOBUS_SUCCESS)
574     {
575 0         result = GLOBUS_SERVICE_GROUP_OUT_OF_MEMORY();
576
577 0         wsa_EndpointReferenceType_destroy(tmp_epr);
578
579 0         goto destroy_resource_out;
580     }
581
582     /*
583      * MemberEPR: Contains a reference to the member to which this entry
584      * pertains.
585      */
586 41     result = wsa_EndpointReferenceType_copy(
587             &tmp_epr,
588             member_epr);
589
590 41     if (result != GLOBUS_SUCCESS)
591     {
592 0         result = GLOBUS_SERVICE_GROUP_OUT_OF_MEMORY();
593
594 0         goto destroy_resource_out;
595     }
596 41     result = globus_resource_create_property(
597             resource,
598             &wssg_MemberEPR_qname,
599             &wsa_EndpointReferenceType_info,
600             tmp_epr);
601 41     if (result != GLOBUS_SUCCESS)
602     {
603 0         result = GLOBUS_SERVICE_GROUP_OUT_OF_MEMORY();
604
605 0         wsa_EndpointReferenceType_destroy(tmp_epr);
606
607 0         goto destroy_resource_out;
608     }
609
610     /*
611      * Content: information pertaining to the group membership.
612      */
613 41     result = xsd_anyType_copy(
614             &tmp_content,
615             content);
616
617 41     if (result != GLOBUS_SUCCESS)
618     {
619 0         result = GLOBUS_SERVICE_GROUP_OUT_OF_MEMORY();
620
621 0         goto destroy_resource_out;
622     }
623
624 41     result = globus_resource_create_property(
625             resource,
626             &wssg_Content_qname,
627             &xsd_anyType_info,
628             tmp_content);
629 41     if (result != GLOBUS_SUCCESS)
630     {
631 0         result = GLOBUS_SERVICE_GROUP_OUT_OF_MEMORY();
632
633 0         xsd_anyType_destroy(tmp_content);
634     }
635 41     info->service_path = globus_l_epr_to_path(entry_epr);
636
637 41     if (info->service_path == NULL)
638     {
639 0         result = GLOBUS_SERVICE_GROUP_OUT_OF_MEMORY();
640
641 0         goto destroy_resource_out;
642     }
643
644 41     rc = globus_extension_activate(info->service_path);
645 41     if (rc != GLOBUS_SUCCESS)
646     {
647 0         result = GLOBUS_SERVICE_GROUP_OUT_OF_MEMORY();
648
649 0         goto free_service_path_out;
650     }
651
652     /* Initialize resource providers for the service group entry */
653 41     service_desc = globus_extension_lookup(
654             &ext,
655             GLOBUS_SERVICE_REGISTRY,
656             info->service_path);
657
658 41     if (service_desc == NULL)
659     {
660 0         result = GLOBUS_SERVICE_GROUP_OUT_OF_MEMORY();
661
662 0         goto deactivate_extension_out;
663     }
664     
665 41     result = globus_operation_table_init_resource(
666             service_desc->operations,
667             entry_epr);
668
669 41     if (result != GLOBUS_SUCCESS)
670     {
671 41         goto release_service_desc_out;
672     }
673
674 release_service_desc_out:
675 41     globus_extension_release(ext);
676
677 41     if (result != GLOBUS_SUCCESS)
678     {
679 deactivate_extension_out:
680 0         globus_extension_deactivate(info->service_path);
681 free_service_path_out:
682 0         free(info->service_path);
683 0         info->service_path = NULL;
684     }
685
686 destroy_resource_out:
687 41     if (result == GLOBUS_SUCCESS)
688     {
689 41         globus_resource_finish(resource);
690     }
691     else
692     {
693 0         globus_resource_destroy(resource);
694     }
695
696 out:
697 41     GlobusServiceGroupDebugExit();
698 41     return result;
699 }
700 /* globus_l_service_group_entry_create_resource() */
701
702 /**
703  * Determine the path to the local service module from an EPR.
704  *
705  * @param epr
706  *     Endpoint Reference to a service deployed in this container.
707  *
708  * @return
709  *     This function returns the local path to the service module for
710  *     the service named by the EPR. This will be NULL if the EPR does
711  *     not contain a path.
712  *
713  * @note There is no checking that the path is valid.
714  */
715 static
716 char *
717 globus_l_epr_to_path(
718     const wsa_EndpointReferenceType *   epr)
719 41 {
720 41     const char *                        tmp;
721 41     globus_url_t                        url;
722 41     char *                              path;
723 41     int                                 rc;
724 41     GlobusFuncName(globus_l_epr_to_path);
725
726 41     GlobusServiceGroupDebugEnter();
727 41     rc = globus_url_parse(epr->Address.base_value, &url);
728
729 41     if (rc != GLOBUS_SUCCESS)
730     {
731 0         return NULL;
732     }
733
734 41     tmp = url.url_path;
735 82     while(*tmp == '/')
736     {
737 41         tmp++;
738     }
739
740 41     path = globus_common_create_string(
741             "%s/%s",
742             GLOBUS_SERVICE_ENGINE_MODULE_PATH_PREFIX,
743             tmp);
744
745 41     globus_url_destroy(&url);
746
747 41     GlobusServiceGroupDebugExit();
748 41     return path;
749 }
750 /* globus_l_epr_to_path() */
751
752 static
753 time_t
754 globus_l_timegm(
755     const struct tm *                   tm)
756 2 {
757 2     time_t ret;
758 2     char *tz;
759 2     GlobusFuncName(globus_l_timegm);
760
761 2     GlobusServiceGroupDebugEnter();
762 2     tz = getenv("TZ");
763 2     setenv("TZ", "", 1);
764 2     tzset();
765 2     ret = mktime((struct tm *) tm);
766 2     if (tz)
767 2       setenv("TZ", tz, 1);
768     else
769 0       unsetenv("TZ");
770 2     tzset();
771
772 2     GlobusServiceGroupDebugExit();
773 2     return ret;
774 }
775 /* globus_l_timegm() */
776
777 /*
778  * This function is called when the resource associated with the service group
779  * entry is destroyed. This can happen either when the service group is
780  * destroyed, the entry is explicitly removed, the entry dies because of
781  * scheduled termination, or the service group module is destroyed.
782  */
783 static
784 void
785 globus_l_service_group_entry_destructor(
786     void *                              p)
787 38 {
788 38     globus_service_group_entry_info_t * info = p;
789
790 38     GlobusFuncName(globus_l_service_group_entry_destructor);
791
792 38     GlobusServiceGroupDebugEnter();
793 38     GlobusServiceGroupDebugPrintf(GLOBUS_L_SERVICE_GROUP_DEBUG_DEBUG,
794             ("Destroying sge %p\n", p));
795
796 38     if (info->service_group_epr.Address.base_value != NULL &&
797         info->entry_epr.Address.base_value != NULL)
798     {
799 38         globus_service_group_remove(
800                 &info->service_group_epr,
801                 &info->entry_epr);
802     }
803
804 38     GlobusServiceGroupDebugPrintf(GLOBUS_L_SERVICE_GROUP_DEBUG_DEBUG,
805             ("Freeing sge data %p\n", p));
806 38     wsa_EndpointReferenceType_destroy_contents(&info->service_group_epr);
807 38     wsa_EndpointReferenceType_destroy_contents(&info->entry_epr);
808 38     globus_extension_deactivate(info->service_path);
809 38     free(info->service_path);
810 38     free(info);
811
812 38     GlobusServiceGroupDebugExit();
813 }
814 /* globus_l_service_group_entry_destructor() */
815
816 static
817 globus_result_t
818 globus_l_service_group_check_membership(
819     globus_wsrf_service_group_t         sg,
820     const wsa_EndpointReferenceType *   service_epr,
821     const xsd_anyType *                 content)
822 43 {
823 43     int                                 i;
824 43     xsd_QName_array *                   elements;
825 43     xsd_any                             tmp;
826 43     globus_result_t                     result;
827 43     GlobusFuncName(globus_l_service_group_check_membership);
828
829 43     GlobusServiceGroupDebugEnter();
830
831 43     result = xsd_any_init_contents(&tmp);
832
833 43     elements = &sg->membership_content_rule->_ContentElements;
834
835 43     if (result != GLOBUS_SUCCESS)
836     {
837 0         return GLOBUS_SERVICE_GROUP_OUT_OF_MEMORY();
838     }
839
840 43     if (sg->membership_content_rule == NULL)
841     {
842 0         GlobusServiceGroupDebugExit();
843 0         return GLOBUS_SUCCESS;
844     }
845 43     else if (content == NULL)
846     {
847 1         GlobusServiceGroupDebugExit();
848 1         return GLOBUS_SERVICE_GROUP_NULL_PARAMETER();
849     }
850
851 42     if (content->any_info == &globus_xml_buffer_info)
852     {
853 3         globus_xml_buffer *             buffer = content->value;
854 3         globus_soap_message_handle_t    any_handle;
855
856 3         result = globus_soap_message_handle_init_from_memory(
857                 &any_handle,
858                 buffer->buffer,
859                 buffer->length);
860
861 3         if (result != GLOBUS_SUCCESS)
862         {
863 0             GlobusServiceGroupDebugExit();
864 0             return GLOBUS_SERVICE_GROUP_INVALID_CONTENT();
865         }
866
867 3         result = xsd_any_deserialize(
868                 NULL,
869                 &tmp,
870                 any_handle,
871                 0);
872
873 3         globus_soap_message_handle_destroy(any_handle);
874
875 3         if (result != GLOBUS_SUCCESS)
876         {
877 0             GlobusServiceGroupDebugExit();
878 0             return GLOBUS_SERVICE_GROUP_INVALID_CONTENT();
879         }
880
881 3         for (i = 0; i < elements->length; i++)
882         {
883 3             if (xsd_QName_keyeq(&elements->elements[i],
884                         tmp.element))
885             {
886 3                 GlobusServiceGroupDebugExit();
887 3                 return GLOBUS_SUCCESS;
888             }
889         }
890     }
891     else
892     {
893         /* I'm not sure this check is correct */
894 40         for (i = 0; i < elements->length; i++)
895         {
896 39             if (xsd_QName_keyeq(&elements->elements[i],
897                         content->any_info->type))
898             {
899 38                 GlobusServiceGroupDebugExit();
900 38                 return GLOBUS_SUCCESS;
901             }
902         }
903     }
904
905
906 1     xsd_any_destroy_contents(&tmp);
907
908 1     GlobusServiceGroupDebugExit();
909 1     return GLOBUS_SERVICE_GROUP_INVALID_CONTENT();
910 }
911 /* globus_l_service_group_check_membership() */