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 #include "ServiceGroupEntryService.h"
19
20 static
21 globus_result_t
22 globus_l_service_group_uri_to_service_path(
23 const wsa_AttributedURIType * service_group_entry_uri,
24 char ** service_path);
25
26 /**
27 * Create new service group state for a resource.
28 * @ingroup wssg
29 *
30 * Creates new service group state for a resouce named by the @a
31 * service_group_epr parameter. The service group will initially be empty.
32 * Other calls from this API may be used manage this service group.
33 *
34 * @param service_group_epr
35 * EPR naming the service group. This EPR will be used as the key for
36 * all service group operations.
37 * @param membership_content_rule
38 * A rule for determining what services will be allowed into this service
39 * group. Currently, the content element passed to
40 * globus_service_group_add() must be of the same element type as one of
41 * the values in the membership content rule.
42 * @param service_group_entry_uri
43 * A URI path to be used for the service used to implement the service
44 * group entries. Whenever a service is added to the group, a new resource
45 * will be created and the providers handled by this service will be
46 * initialized for the new resource. If this value is @a NULL, then the
47 * ServiceGroupEntryService included in this package will be used.
48 * @param add_callback
49 * Callback function which will be called when a service is added to the
50 * group. The @a callback_arg parameter to this function will be passed
51 * to the callback.
52 * @param remove_callback
53 * Callback function which will be called when a service is removed from
54 * the group. The @a callback_arg parameter to this function will be passed
55 * to the callback.
56 * @param callback_arg
57 * Application-specific argument to the @a add_callback and @a
58 * remove_callback functions.
59 *
60 * @retval GLOBUS_SUCCESS
61 * @retval #GLOBUS_SERVICE_GROUP_ERROR_TYPE_NULL_PARAMETER
62 * @retval #GLOBUS_SERVICE_GROUP_ERROR_TYPE_OUT_OF_MEMORY
63 */
64 globus_result_t
65 globus_service_group_create(
66 const wsa_EndpointReferenceType * service_group_epr,
67 const wssg_MembershipContentRuleType *
68 membership_content_rule,
69 const wsa_AttributedURIType * service_group_entry_uri,
70 globus_service_group_callback_t add_callback,
71 globus_service_group_callback_t
72 remove_callback,
73 void * callback_arg)
74 63 {
75 63 globus_result_t result = GLOBUS_SUCCESS;
76 int rc;
77 globus_wsrf_service_group_t sg;
78 GlobusFuncName(globus_service_group_create);
79
80 63 GlobusServiceGroupDebugEnter();
81
82 63 if (service_group_epr == NULL || membership_content_rule == NULL)
83 {
84 6 result = GLOBUS_SERVICE_GROUP_NULL_PARAMETER();
85
86 6 goto out;
87 }
88
89 57 sg = malloc(sizeof(globus_i_wsrf_service_group_t));
90
91 57 if (sg == NULL)
92 {
93 0 goto out;
94 }
95
96 57 sg->add_callback = add_callback;
97 57 sg->remove_callback = remove_callback;
98 57 sg->callback_arg = callback_arg;
99
100 57 rc = globus_hashtable_init(
101 &sg->entries,
102 5,
103 globus_hashtable_string_hash,
104 globus_hashtable_string_keyeq);
105 57 if (rc != 0)
106 {
107 0 result = GLOBUS_SERVICE_GROUP_OUT_OF_MEMORY();
108
109 0 goto free_sg_out;
110 }
111
112 57 result = wsa_EndpointReferenceType_copy_contents(
113 &sg->service_group_epr,
114 service_group_epr);
115
116 57 if (result != GLOBUS_SUCCESS)
117 {
118 0 result = GLOBUS_SERVICE_GROUP_OUT_OF_MEMORY();
119
120 0 goto destroy_entries_out;
121 }
122
123 /* If the service_group_entry URI is undefined, we will use the
124 * path to the ServiceGroupEntry service (from this source package)
125 */
126 57 if (service_group_entry_uri == NULL)
127 {
128 char * tmp;
129
130 57 result = wsa_AttributedURIType_copy_contents(
131 &sg->service_group_entry_uri,
132 &service_group_epr->Address);
133
134 57 if (result != GLOBUS_SUCCESS)
135 {
136 0 result = GLOBUS_SERVICE_GROUP_OUT_OF_MEMORY();
137
138 0 goto destroy_service_group_epr_out;
139 }
140
141 57 tmp = realloc(
142 sg->service_group_entry_uri.base_value,
143 strlen(sg->service_group_entry_uri.base_value) +
144 strlen(SERVICEGROUPENTRYSERVICE_BASE_PATH) + 2);
145
146 57 if (tmp == NULL)
147 {
148 0 result = GLOBUS_SERVICE_GROUP_OUT_OF_MEMORY();
149
150 0 goto destroy_service_group_entry_uri_out;
151 }
152
153 57 sg->service_group_entry_uri.base_value = tmp;
154
155 57 tmp = strstr(tmp, "://");
156
157 57 if (tmp == NULL)
158 {
159 0 result = GLOBUS_SERVICE_GROUP_OUT_OF_MEMORY();
160
161 0 goto destroy_service_group_entry_uri_out;
162 }
163
164 57 tmp += 3;
165
166 1008 while (*tmp && *tmp != '/')
167 {
168 894 tmp++;
169 }
170
171 57 if (*tmp == '\0')
172 {
173 0 result = GLOBUS_SERVICE_GROUP_OUT_OF_MEMORY();
174
175 0 goto destroy_service_group_entry_uri_out;
176 }
177
178 57 strcpy(tmp+1, SERVICEGROUPENTRYSERVICE_BASE_PATH);
179 }
180 else
181 {
182 0 result = wsa_AttributedURIType_copy_contents(
183 &sg->service_group_entry_uri,
184 service_group_entry_uri);
185
186 0 if (result != GLOBUS_SUCCESS)
187 {
188 0 result = GLOBUS_SERVICE_GROUP_OUT_OF_MEMORY();
189
190 0 goto destroy_service_group_epr_out;
191 }
192 }
193
194 57 result = globus_wsrf_core_get_resource_id_from_epr(
195 &sg->service_group_epr,
196 &sg->resource_id);
197
198 57 if (result != GLOBUS_SUCCESS)
199 {
200 0 result = GLOBUS_SERVICE_GROUP_OUT_OF_MEMORY();
201
202 0 goto destroy_service_group_entry_uri_out;
203 }
204
205 57 rc = globus_mutex_init(&sg->lock, NULL);
206 57 if (rc != GLOBUS_SUCCESS)
207 {
208 0 result = GLOBUS_SERVICE_GROUP_OUT_OF_MEMORY();
209
210 0 goto destroy_resource_id_out;
211 }
212
213 57 result = wssg_MembershipContentRuleType_copy(
214 &sg->membership_content_rule,
215 membership_content_rule);
216 57 if (result != GLOBUS_SUCCESS)
217 {
218 0 result = GLOBUS_SERVICE_GROUP_OUT_OF_MEMORY();
219
220 0 goto destroy_mutex_out;
221 }
222
223 57 result = globus_l_service_group_uri_to_service_path(
224 &sg->service_group_entry_uri,
225 &sg->service_group_entry_path);
226
227 57 if (result != GLOBUS_SUCCESS)
228 {
229 0 goto destroy_membership_content_rule;
230 }
231
232 57 GlobusServiceGroupGlobalLock();
233 57 rc = globus_hashtable_insert(
234 &globus_i_service_groups,
235 sg->resource_id,
236 sg);
237 57 GlobusServiceGroupGlobalUnlock();
238 57 if (rc != GLOBUS_SUCCESS)
239 {
240 0 result = GLOBUS_SERVICE_GROUP_OUT_OF_MEMORY();
241
242 0 goto destroy_service_group_entry_path_out;
243 }
244
245 57 return result;
246
247 0 destroy_service_group_entry_path_out:
248 0 free(sg->service_group_entry_path);
249 0 destroy_membership_content_rule:
250 0 wssg_MembershipContentRuleType_destroy(sg->membership_content_rule);
251 0 destroy_mutex_out:
252 0 globus_mutex_destroy(&sg->lock);
253 0 destroy_resource_id_out:
254 0 free(sg->resource_id);
255 0 destroy_service_group_entry_uri_out:
256 0 wsa_AttributedURIType_destroy_contents(&sg->service_group_entry_uri);
257 0 destroy_service_group_epr_out:
258 0 wsa_EndpointReferenceType_destroy_contents(&sg->service_group_epr);
259 0 destroy_entries_out:
260 0 globus_hashtable_destroy(&sg->entries);
261 0 free_sg_out:
262 0 free(sg);
263 6 out:
264 6 GlobusServiceGroupDebugExit();
265 6 return result;
266 }
267 /* globus_service_group_create() */
268
269 static
270 globus_result_t
271 globus_l_service_group_uri_to_service_path(
272 const wsa_AttributedURIType * service_group_entry_uri,
273 char ** service_path)
274 57 {
275 const char * tmp;
276 globus_url_t url;
277 char * path;
278 int rc;
279 57 globus_result_t result = GLOBUS_SUCCESS;
280 GlobusFuncName(globus_l_service_group_uri_to_service_path);
281
282 57 GlobusServiceGroupDebugEnter();
283 57 rc = globus_url_parse(service_group_entry_uri->base_value, &url);
284
285 57 if (rc != GLOBUS_SUCCESS)
286 {
287 0 return GLOBUS_SERVICE_GROUP_OUT_OF_MEMORY();
288 }
289
290 57 tmp = url.url_path;
291 171 while(*tmp == '/')
292 {
293 57 tmp++;
294 }
295
296 57 path = globus_common_create_string(
297 "%s/%s",
298 GLOBUS_SERVICE_ENGINE_MODULE_PATH_PREFIX,
299 tmp);
300
301 57 globus_url_destroy(&url);
302
303 57 *service_path = path;
304
305 57 GlobusServiceGroupDebugExit();
306
307 57 return result;
308 }