1 | /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- */ |
---|
2 | /* |
---|
3 | * oafd: OAF CORBA dameon. |
---|
4 | * |
---|
5 | * Copyright (C) 1999, 2000 Red Hat, Inc. |
---|
6 | * Copyright (C) 1999, 2000 Eazel, Inc. |
---|
7 | * |
---|
8 | * This library is free software; you can redistribute it and/or |
---|
9 | * modify it under the terms of the GNU General Public License as |
---|
10 | * published by the Free Software Foundation; either version 2 of the |
---|
11 | * License, or (at your option) any later version. |
---|
12 | * |
---|
13 | * This library is distributed in the hope that it will be useful, |
---|
14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
---|
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
---|
16 | * General Public License for more details. |
---|
17 | * |
---|
18 | * You should have received a copy of the GNU General Public License |
---|
19 | * along with this library; if not, write to the Free Software |
---|
20 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. |
---|
21 | * |
---|
22 | * Authors: Elliot Lee <sopwith@redhat.com>, |
---|
23 | * |
---|
24 | */ |
---|
25 | |
---|
26 | #ifdef HAVE_CONFIG_H |
---|
27 | #include <config.h> |
---|
28 | #endif |
---|
29 | |
---|
30 | #include <stdio.h> |
---|
31 | #include <time.h> |
---|
32 | #include <string.h> |
---|
33 | |
---|
34 | #include "server.h" |
---|
35 | |
---|
36 | #include "bonobo-activation/bonobo-activation-i18n.h" |
---|
37 | #include "activation-context-query.h" |
---|
38 | #include "activation-server-corba-extensions.h" |
---|
39 | |
---|
40 | #undef LOCALE_DEBUG |
---|
41 | |
---|
42 | #define Bonobo_LINK_TIME_TO_LIVE 256 |
---|
43 | |
---|
44 | typedef struct { |
---|
45 | Bonobo_ObjectDirectory obj; |
---|
46 | |
---|
47 | char *hostname, *username; |
---|
48 | |
---|
49 | Bonobo_ServerInfoList *list; |
---|
50 | Bonobo_CacheTime time_list_pulled; |
---|
51 | GHashTable *by_iid; |
---|
52 | |
---|
53 | GHashTable *active_servers; /* It is assumed that accesses to this |
---|
54 | * hash table are atomic - i.e. a CORBA |
---|
55 | * call cannot come in while |
---|
56 | * checking a value in this table */ |
---|
57 | Bonobo_ServerStateCache *active_server_list; |
---|
58 | Bonobo_CacheTime time_active_pulled; |
---|
59 | |
---|
60 | guchar locked; |
---|
61 | } ChildODInfo; |
---|
62 | |
---|
63 | static ChildODInfo * |
---|
64 | child_od_info_new (Bonobo_ObjectDirectory obj, CORBA_Environment * ev) |
---|
65 | { |
---|
66 | ChildODInfo *retval; |
---|
67 | char *host, *user; |
---|
68 | |
---|
69 | host = Bonobo_ObjectDirectory__get_hostname (obj, ev); |
---|
70 | if (ev->_major != CORBA_NO_EXCEPTION) |
---|
71 | goto errhost; |
---|
72 | |
---|
73 | user = Bonobo_ObjectDirectory__get_username (obj, ev); |
---|
74 | if (ev->_major != CORBA_NO_EXCEPTION) |
---|
75 | goto erruser; |
---|
76 | |
---|
77 | retval = g_new0 (ChildODInfo, 1); |
---|
78 | |
---|
79 | retval->obj = CORBA_Object_duplicate (obj, ev); |
---|
80 | retval->hostname = host; |
---|
81 | retval->username = user; |
---|
82 | |
---|
83 | return retval; |
---|
84 | |
---|
85 | erruser: |
---|
86 | CORBA_free (host); |
---|
87 | errhost: |
---|
88 | return NULL; |
---|
89 | } |
---|
90 | |
---|
91 | static void |
---|
92 | child_od_info_free (ChildODInfo *child, CORBA_Environment *ev) |
---|
93 | { |
---|
94 | CORBA_Object_release (child->obj, ev); |
---|
95 | CORBA_free (child->hostname); |
---|
96 | CORBA_free (child->username); |
---|
97 | |
---|
98 | if (child->by_iid) |
---|
99 | g_hash_table_destroy (child->by_iid); |
---|
100 | |
---|
101 | if (child->list) { |
---|
102 | CORBA_sequence_set_release (child->list, CORBA_TRUE); |
---|
103 | CORBA_free (child->list); |
---|
104 | } |
---|
105 | |
---|
106 | if (child->active_servers) |
---|
107 | g_hash_table_destroy (child->active_servers); |
---|
108 | CORBA_free (child->active_server_list); |
---|
109 | |
---|
110 | memset (child, 0xaa, sizeof (ChildODInfo)); |
---|
111 | g_free (child); |
---|
112 | } |
---|
113 | |
---|
114 | static void |
---|
115 | child_od_exception (ChildODInfo * child, CORBA_Environment * ev) |
---|
116 | { |
---|
117 | CORBA_Object_release (child->obj, ev); |
---|
118 | child->obj = CORBA_OBJECT_NIL; |
---|
119 | } |
---|
120 | |
---|
121 | static void |
---|
122 | child_od_update_active (ChildODInfo *child, CORBA_Environment *ev) |
---|
123 | { |
---|
124 | int i; |
---|
125 | Bonobo_ServerStateCache *cache; |
---|
126 | |
---|
127 | cache = Bonobo_ObjectDirectory_get_active_servers ( |
---|
128 | child->obj, child->time_active_pulled, ev); |
---|
129 | |
---|
130 | if (ev->_major != CORBA_NO_EXCEPTION) { |
---|
131 | child_od_exception (child, ev); |
---|
132 | return; |
---|
133 | } |
---|
134 | |
---|
135 | if (cache->_d) { |
---|
136 | if (child->active_servers) { |
---|
137 | g_hash_table_destroy (child->active_servers); |
---|
138 | CORBA_free (child->active_server_list); |
---|
139 | } |
---|
140 | |
---|
141 | child->active_server_list = cache; |
---|
142 | |
---|
143 | child->time_active_pulled = time (NULL); |
---|
144 | child->active_servers = |
---|
145 | g_hash_table_new (g_str_hash, g_str_equal); |
---|
146 | for (i = 0; i < cache->_u.active_servers._length; i++) |
---|
147 | g_hash_table_insert (child->active_servers, |
---|
148 | cache->_u. |
---|
149 | active_servers._buffer[i], |
---|
150 | GINT_TO_POINTER (1)); |
---|
151 | } else |
---|
152 | CORBA_free (cache); |
---|
153 | } |
---|
154 | |
---|
155 | static char * |
---|
156 | ac_CORBA_Context_get_value (CORBA_Context ctx, |
---|
157 | const char *propname, |
---|
158 | CORBA_Environment *ev) |
---|
159 | { |
---|
160 | return activation_server_CORBA_Context_get_value ( |
---|
161 | ctx, propname, |
---|
162 | ex_Bonobo_Activation_IncompleteContext, ev); |
---|
163 | } |
---|
164 | |
---|
165 | /*** App-specific servant structures ***/ |
---|
166 | |
---|
167 | typedef struct { |
---|
168 | POA_Bonobo_ActivationContext servant; |
---|
169 | |
---|
170 | GSList *dirs; |
---|
171 | |
---|
172 | int total_servers; |
---|
173 | |
---|
174 | gint refs; /* This is a use count, so we don't accidentally go |
---|
175 | * updating our server list and invalidating memory */ |
---|
176 | Bonobo_ActivationContext self; |
---|
177 | } impl_POA_Bonobo_ActivationContext; |
---|
178 | |
---|
179 | /*** Stub implementations ***/ |
---|
180 | |
---|
181 | static void |
---|
182 | child_od_update_list (ChildODInfo *child, CORBA_Environment *ev) |
---|
183 | { |
---|
184 | int i; |
---|
185 | Bonobo_ServerInfoListCache *cache; |
---|
186 | |
---|
187 | cache = Bonobo_ObjectDirectory_get_servers ( |
---|
188 | child->obj, child->time_list_pulled, ev); |
---|
189 | |
---|
190 | if (ev->_major != CORBA_NO_EXCEPTION) { |
---|
191 | child->list = NULL; |
---|
192 | child_od_exception (child, ev); |
---|
193 | return; |
---|
194 | } |
---|
195 | |
---|
196 | if (cache->_d) { |
---|
197 | if (child->by_iid) |
---|
198 | g_hash_table_destroy (child->by_iid); |
---|
199 | if (child->list) { |
---|
200 | CORBA_sequence_set_release (child->list, CORBA_TRUE); |
---|
201 | CORBA_free (child->list); |
---|
202 | child->list = NULL; |
---|
203 | } |
---|
204 | |
---|
205 | child->list = Bonobo_ServerInfoList__alloc (); |
---|
206 | *(child->list) = cache->_u.server_list; |
---|
207 | CORBA_sequence_set_release (child->list, CORBA_FALSE); |
---|
208 | CORBA_sequence_set_release (&(cache->_u.server_list), |
---|
209 | CORBA_FALSE); |
---|
210 | |
---|
211 | child->time_list_pulled = time (NULL); |
---|
212 | child->by_iid = g_hash_table_new (g_str_hash, g_str_equal); |
---|
213 | for (i = 0; i < child->list->_length; i++) |
---|
214 | g_hash_table_insert (child->by_iid, |
---|
215 | child->list->_buffer[i].iid, |
---|
216 | &(child->list->_buffer[i])); |
---|
217 | } |
---|
218 | |
---|
219 | CORBA_free (cache); |
---|
220 | } |
---|
221 | |
---|
222 | static void |
---|
223 | free_child_dirs (impl_POA_Bonobo_ActivationContext *servant, |
---|
224 | CORBA_Environment *ev) |
---|
225 | { |
---|
226 | GSList *l; |
---|
227 | |
---|
228 | for (l = servant->dirs; l; l = l->next) |
---|
229 | child_od_info_free (l->data, ev); |
---|
230 | g_slist_free (servant->dirs); |
---|
231 | servant->dirs = NULL; |
---|
232 | } |
---|
233 | |
---|
234 | static void |
---|
235 | ac_update_list (impl_POA_Bonobo_ActivationContext *servant, |
---|
236 | ChildODInfo *child, |
---|
237 | CORBA_Environment *ev) |
---|
238 | { |
---|
239 | int prev, new; |
---|
240 | |
---|
241 | if (servant->refs > 0) |
---|
242 | return; |
---|
243 | |
---|
244 | if (child->list) |
---|
245 | prev = child->list->_length; |
---|
246 | else |
---|
247 | prev = 0; |
---|
248 | |
---|
249 | child_od_update_list (child, ev); |
---|
250 | |
---|
251 | if (child->list) |
---|
252 | new = child->list->_length; |
---|
253 | else |
---|
254 | new = 0; |
---|
255 | |
---|
256 | servant->total_servers += (new - prev); |
---|
257 | } |
---|
258 | |
---|
259 | static ChildODInfo * |
---|
260 | ac_find_child_for_server (impl_POA_Bonobo_ActivationContext *servant, |
---|
261 | Bonobo_ServerInfo *server, |
---|
262 | CORBA_Environment *ev) |
---|
263 | { |
---|
264 | GSList *l; |
---|
265 | |
---|
266 | for (l = servant->dirs; l; l = l->next) { |
---|
267 | ChildODInfo *child = l->data; |
---|
268 | |
---|
269 | if (CORBA_Object_is_nil (child->obj, ev) || !child->list) |
---|
270 | continue; |
---|
271 | |
---|
272 | if ((server >= child->list->_buffer) |
---|
273 | && (server < |
---|
274 | (child->list->_buffer + |
---|
275 | child->list->_length))) return child; |
---|
276 | } |
---|
277 | |
---|
278 | return NULL; |
---|
279 | } |
---|
280 | |
---|
281 | static QueryExprConst |
---|
282 | ac_query_get_var (Bonobo_ServerInfo *si, const char *id, QueryContext *qctx) |
---|
283 | { |
---|
284 | ChildODInfo *child; |
---|
285 | QueryExprConst retval; |
---|
286 | |
---|
287 | retval.value_known = FALSE; |
---|
288 | retval.needs_free = FALSE; |
---|
289 | |
---|
290 | child = ac_find_child_for_server (qctx->user_data, si, NULL); |
---|
291 | if (!child) |
---|
292 | goto out; |
---|
293 | |
---|
294 | if (!strcasecmp (id, "_active")) { |
---|
295 | CORBA_Environment ev; |
---|
296 | |
---|
297 | CORBA_exception_init (&ev); |
---|
298 | child_od_update_active (child, &ev); |
---|
299 | CORBA_exception_free (&ev); |
---|
300 | |
---|
301 | retval.value_known = TRUE; |
---|
302 | retval.type = CONST_BOOLEAN; |
---|
303 | retval.u.v_boolean = |
---|
304 | g_hash_table_lookup (child->active_servers, |
---|
305 | si->iid) ? TRUE : FALSE; |
---|
306 | } |
---|
307 | |
---|
308 | out: |
---|
309 | |
---|
310 | return retval; |
---|
311 | } |
---|
312 | |
---|
313 | /* This function should only be called by |
---|
314 | * impl_Bonobo_ActivationContext_query and |
---|
315 | * impl_Bonobo_ActivationContext_activateMatching - hairy implicit preconditions |
---|
316 | * exist. */ |
---|
317 | static void |
---|
318 | ac_query_run (impl_POA_Bonobo_ActivationContext *servant, |
---|
319 | const CORBA_char *requirements, |
---|
320 | const Bonobo_StringList *selection_order, |
---|
321 | CORBA_Context ctx, |
---|
322 | Bonobo_ServerInfo **items, |
---|
323 | CORBA_Environment *ev) |
---|
324 | { |
---|
325 | int total, i; |
---|
326 | GSList *cur; |
---|
327 | QueryContext qctx; |
---|
328 | |
---|
329 | Bonobo_ServerInfo **orig_items; |
---|
330 | int item_count, orig_item_count; |
---|
331 | char *errstr; |
---|
332 | Bonobo_Activation_ParseFailed *ex; |
---|
333 | |
---|
334 | QueryExpr *qexp_requirements; |
---|
335 | QueryExpr **qexp_sort_items; |
---|
336 | |
---|
337 | /* First, parse the query */ |
---|
338 | errstr = (char *) qexp_parse (requirements, &qexp_requirements); |
---|
339 | if (errstr) { |
---|
340 | puts (errstr); |
---|
341 | |
---|
342 | g_strstrip (errstr); |
---|
343 | ex = Bonobo_Activation_ParseFailed__alloc (); |
---|
344 | ex->description = CORBA_string_dup (errstr); |
---|
345 | CORBA_exception_set (ev, CORBA_USER_EXCEPTION, |
---|
346 | ex_Bonobo_Activation_ParseFailed, |
---|
347 | ex); |
---|
348 | return; |
---|
349 | } |
---|
350 | |
---|
351 | qexp_sort_items = |
---|
352 | g_alloca (selection_order->_length * sizeof (QueryExpr *)); |
---|
353 | for (i = 0; i < selection_order->_length; i++) { |
---|
354 | errstr = |
---|
355 | (char *) qexp_parse (selection_order->_buffer[i], |
---|
356 | &qexp_sort_items[i]); |
---|
357 | |
---|
358 | if (errstr) { |
---|
359 | qexp_free (qexp_requirements); |
---|
360 | for (i--; i >= 0; i--) |
---|
361 | qexp_free (qexp_sort_items[i]); |
---|
362 | |
---|
363 | g_strstrip (errstr); |
---|
364 | ex = Bonobo_Activation_ParseFailed__alloc (); |
---|
365 | ex->description = CORBA_string_dup (errstr); |
---|
366 | |
---|
367 | CORBA_exception_set (ev, CORBA_USER_EXCEPTION, |
---|
368 | ex_Bonobo_Activation_ParseFailed, |
---|
369 | ex); |
---|
370 | return; |
---|
371 | } |
---|
372 | } |
---|
373 | |
---|
374 | total = servant->total_servers; |
---|
375 | orig_items = g_alloca (total * sizeof (Bonobo_ServerInfo *)); |
---|
376 | |
---|
377 | for (item_count = 0, cur = servant->dirs; cur; cur = cur->next) { |
---|
378 | ChildODInfo *child; |
---|
379 | int i; |
---|
380 | |
---|
381 | child = cur->data; |
---|
382 | |
---|
383 | if (child->obj == CORBA_OBJECT_NIL) |
---|
384 | continue; |
---|
385 | |
---|
386 | for (i = 0; i < child->list->_length; i++, item_count++) |
---|
387 | items[item_count] = &child->list->_buffer[i]; |
---|
388 | } |
---|
389 | |
---|
390 | memcpy (orig_items, items, item_count * sizeof (Bonobo_ServerInfo *)); |
---|
391 | orig_item_count = item_count; |
---|
392 | |
---|
393 | qctx.sil = orig_items; |
---|
394 | qctx.nservers = orig_item_count; |
---|
395 | qctx.cctx = ctx; |
---|
396 | qctx.id_evaluator = ac_query_get_var; |
---|
397 | qctx.user_data = servant; |
---|
398 | |
---|
399 | for (i = 0; i < item_count; i++) { |
---|
400 | if (!qexp_matches (items[i], qexp_requirements, &qctx)) |
---|
401 | items[i] = NULL; |
---|
402 | } |
---|
403 | |
---|
404 | qexp_sort (items, item_count, qexp_sort_items, |
---|
405 | selection_order->_length, &qctx); |
---|
406 | |
---|
407 | qexp_free (qexp_requirements); |
---|
408 | for (i = 0; i < selection_order->_length; i++) |
---|
409 | qexp_free (qexp_sort_items[i]); |
---|
410 | } |
---|
411 | |
---|
412 | static void |
---|
413 | ac_update_lists (impl_POA_Bonobo_ActivationContext *servant, |
---|
414 | CORBA_Environment *ev) |
---|
415 | { |
---|
416 | GSList *cur; |
---|
417 | |
---|
418 | if (servant->refs > 0) { |
---|
419 | /* FIXME: what happens on re-enterency here ? |
---|
420 | * looks like this could get seriously out of date */ |
---|
421 | return; |
---|
422 | } |
---|
423 | |
---|
424 | for (cur = servant->dirs; cur; cur = cur->next) |
---|
425 | ac_update_list (servant, cur->data, ev); |
---|
426 | } |
---|
427 | |
---|
428 | #define GET_SERVANT(s) ((impl_POA_Bonobo_ActivationContext *)(s)) |
---|
429 | |
---|
430 | static GList *clients = NULL; |
---|
431 | |
---|
432 | void |
---|
433 | activation_clients_cache_notify (void) |
---|
434 | { |
---|
435 | GList *l; |
---|
436 | GSList *notify = NULL, *l2; |
---|
437 | CORBA_Environment ev; |
---|
438 | |
---|
439 | CORBA_exception_init (&ev); |
---|
440 | |
---|
441 | for (l = clients; l; l = l->next) |
---|
442 | notify = g_slist_prepend (notify, CORBA_Object_duplicate (l->data, &ev)); |
---|
443 | |
---|
444 | for (l2 = notify; l2; l2 = l2->next) { |
---|
445 | Bonobo_ActivationClient_resetCache (l2->data, &ev); |
---|
446 | if (ev._major != CORBA_NO_EXCEPTION) |
---|
447 | clients = g_list_remove (clients, l2->data); |
---|
448 | |
---|
449 | CORBA_Object_release (l2->data, &ev); |
---|
450 | CORBA_exception_free (&ev); |
---|
451 | } |
---|
452 | } |
---|
453 | |
---|
454 | gboolean |
---|
455 | activation_clients_is_empty_scan (void) |
---|
456 | { |
---|
457 | GList *l, *next; |
---|
458 | |
---|
459 | for (l = clients; l; l = next) { |
---|
460 | next = l->next; |
---|
461 | if (ORBit_small_get_connection_status (l->data) == |
---|
462 | ORBIT_CONNECTION_DISCONNECTED) { |
---|
463 | CORBA_Object_release (l->data, NULL); |
---|
464 | clients = g_list_delete_link (clients, l); |
---|
465 | } |
---|
466 | } |
---|
467 | |
---|
468 | return clients == NULL; |
---|
469 | } |
---|
470 | |
---|
471 | static void |
---|
472 | active_client_cnx_broken (ORBitConnection *cnx, |
---|
473 | gpointer dummy) |
---|
474 | { |
---|
475 | if (activation_clients_is_empty_scan ()) { |
---|
476 | #ifdef BONOBO_ACTIVATION_DEBUG |
---|
477 | g_warning ("All clients dead"); |
---|
478 | #endif |
---|
479 | check_quit (); |
---|
480 | } |
---|
481 | |
---|
482 | } |
---|
483 | |
---|
484 | static void |
---|
485 | impl_Bonobo_ActivationContext_addClient (PortableServer_Servant servant, |
---|
486 | const Bonobo_ActivationClient client, |
---|
487 | const CORBA_char *locales, |
---|
488 | CORBA_Environment *ev) |
---|
489 | { |
---|
490 | GList *l; |
---|
491 | gboolean new_locale; |
---|
492 | ORBitConnection *cnx; |
---|
493 | |
---|
494 | new_locale = register_interest_in_locales (locales); |
---|
495 | |
---|
496 | cnx = ORBit_small_get_connection (client); |
---|
497 | for (l = clients; l; l = l->next) |
---|
498 | if (cnx == ORBit_small_get_connection (l->data)) |
---|
499 | break; |
---|
500 | |
---|
501 | clients = g_list_prepend ( |
---|
502 | clients, CORBA_Object_duplicate (client, ev)); |
---|
503 | |
---|
504 | if (!l) { |
---|
505 | g_signal_connect ( |
---|
506 | cnx, "broken", |
---|
507 | G_CALLBACK (active_client_cnx_broken), |
---|
508 | NULL); |
---|
509 | check_quit (); |
---|
510 | } |
---|
511 | |
---|
512 | if (new_locale) |
---|
513 | bonobo_object_directory_reload (); |
---|
514 | } |
---|
515 | |
---|
516 | static Bonobo_ObjectDirectoryList * |
---|
517 | impl_Bonobo_ActivationContext__get_directories (PortableServer_Servant _servant, |
---|
518 | CORBA_Environment *ev) |
---|
519 | { |
---|
520 | impl_POA_Bonobo_ActivationContext *servant = GET_SERVANT (_servant); |
---|
521 | Bonobo_ObjectDirectoryList *retval; |
---|
522 | int i; |
---|
523 | GSList *cur; |
---|
524 | |
---|
525 | retval = Bonobo_ObjectDirectoryList__alloc (); |
---|
526 | retval->_length = g_slist_length (servant->dirs); |
---|
527 | retval->_buffer = |
---|
528 | CORBA_sequence_Bonobo_ObjectDirectory_allocbuf (retval->_length); |
---|
529 | |
---|
530 | for (i = 0, cur = servant->dirs; cur; cur = cur->next, i++) { |
---|
531 | ChildODInfo *child; |
---|
532 | child = cur->data; |
---|
533 | retval->_buffer[i] = CORBA_Object_duplicate (child->obj, ev); |
---|
534 | } |
---|
535 | |
---|
536 | CORBA_sequence_set_release (retval, CORBA_TRUE); |
---|
537 | |
---|
538 | return retval; |
---|
539 | } |
---|
540 | |
---|
541 | static void |
---|
542 | impl_Bonobo_ActivationContext_addDirectory (PortableServer_Servant _servant, |
---|
543 | Bonobo_ObjectDirectory dir, |
---|
544 | CORBA_Environment *ev) |
---|
545 | { |
---|
546 | impl_POA_Bonobo_ActivationContext *servant = GET_SERVANT (_servant); |
---|
547 | GSList *cur; |
---|
548 | ChildODInfo *new_child; |
---|
549 | |
---|
550 | for (cur = servant->dirs; cur; cur = cur->next) { |
---|
551 | ChildODInfo *child; |
---|
552 | child = cur->data; |
---|
553 | if (CORBA_Object_is_equivalent (dir, child->obj, ev)) { |
---|
554 | CORBA_exception_set (ev, CORBA_USER_EXCEPTION, |
---|
555 | ex_Bonobo_Activation_AlreadyListed, |
---|
556 | NULL); |
---|
557 | return; |
---|
558 | } |
---|
559 | } |
---|
560 | |
---|
561 | new_child = child_od_info_new (dir, ev); |
---|
562 | if (new_child) |
---|
563 | servant->dirs = g_slist_append (servant->dirs, new_child); |
---|
564 | } |
---|
565 | |
---|
566 | static void |
---|
567 | impl_Bonobo_ActivationContext_removeDirectory (PortableServer_Servant _servant, |
---|
568 | Bonobo_ObjectDirectory dir, |
---|
569 | CORBA_Environment *ev) |
---|
570 | { |
---|
571 | impl_POA_Bonobo_ActivationContext *servant = GET_SERVANT (_servant); |
---|
572 | GSList *cur; |
---|
573 | |
---|
574 | for (cur = servant->dirs; cur; cur = cur->next) { |
---|
575 | ChildODInfo *child; |
---|
576 | child = cur->data; |
---|
577 | |
---|
578 | if (CORBA_Object_is_equivalent (dir, child->obj, ev)) { |
---|
579 | if (servant->refs) { |
---|
580 | CORBA_Object_release (child->obj, ev); |
---|
581 | child->obj = CORBA_OBJECT_NIL; |
---|
582 | } else { |
---|
583 | servant->dirs = |
---|
584 | g_slist_remove (servant->dirs, child); |
---|
585 | child_od_info_free (child, ev); |
---|
586 | } |
---|
587 | break; |
---|
588 | } |
---|
589 | } |
---|
590 | |
---|
591 | if (!cur) |
---|
592 | CORBA_exception_set (ev, CORBA_USER_EXCEPTION, |
---|
593 | ex_Bonobo_Activation_NotListed, |
---|
594 | NULL); |
---|
595 | } |
---|
596 | |
---|
597 | static void |
---|
598 | ac_do_activation (impl_POA_Bonobo_ActivationContext *servant, |
---|
599 | Bonobo_ServerInfo *server, |
---|
600 | const Bonobo_ActivationEnvironment *environment, |
---|
601 | Bonobo_ActivationResult *out, |
---|
602 | Bonobo_ActivationFlags flags, |
---|
603 | const char *hostname, |
---|
604 | CORBA_Context ctx, |
---|
605 | CORBA_Environment *ev) |
---|
606 | { |
---|
607 | int num_layers; |
---|
608 | ChildODInfo *child; |
---|
609 | Bonobo_ServerInfo *activatable; |
---|
610 | |
---|
611 | /* When doing checks for shlib loadability, we |
---|
612 | * have to find the info on the factory object in case |
---|
613 | * a factory is inside a shlib |
---|
614 | */ |
---|
615 | child = ac_find_child_for_server (servant, server, ev); |
---|
616 | |
---|
617 | if (!child || !child->obj || ev->_major != CORBA_NO_EXCEPTION) { |
---|
618 | Bonobo_GeneralError *errval = Bonobo_GeneralError__alloc (); |
---|
619 | errval->description = |
---|
620 | CORBA_string_dup |
---|
621 | (_("Couldn't find which child the server was listed in")); |
---|
622 | CORBA_exception_set (ev, CORBA_USER_EXCEPTION, |
---|
623 | ex_Bonobo_GeneralError, errval); |
---|
624 | return; |
---|
625 | } |
---|
626 | |
---|
627 | for (num_layers = 0, activatable = server; |
---|
628 | activatable && activatable->server_type && |
---|
629 | !strcmp (activatable->server_type, "factory") && |
---|
630 | num_layers < Bonobo_LINK_TIME_TO_LIVE; num_layers++) { |
---|
631 | |
---|
632 | activatable = g_hash_table_lookup (child->by_iid, activatable->location_info); |
---|
633 | } |
---|
634 | |
---|
635 | if (activatable == NULL) { |
---|
636 | Bonobo_GeneralError *errval = Bonobo_GeneralError__alloc (); |
---|
637 | errval->description = CORBA_string_dup ("Couldn't find the factory server"); |
---|
638 | CORBA_exception_set (ev, CORBA_USER_EXCEPTION, |
---|
639 | ex_Bonobo_GeneralError, errval); |
---|
640 | return; |
---|
641 | } |
---|
642 | else if (num_layers == Bonobo_LINK_TIME_TO_LIVE) { |
---|
643 | Bonobo_GeneralError *errval = Bonobo_GeneralError__alloc (); |
---|
644 | errval->description = CORBA_string_dup ("Location loop"); |
---|
645 | CORBA_exception_set (ev, CORBA_USER_EXCEPTION, |
---|
646 | ex_Bonobo_GeneralError, errval); |
---|
647 | return; |
---|
648 | } |
---|
649 | |
---|
650 | /* A shared library must be on the same host as the activator in |
---|
651 | * order for loading to work properly (no, we're not going to |
---|
652 | * bother with loading a remote shlib into a process - it gets far too complicated |
---|
653 | * far too quickly :-) */ |
---|
654 | |
---|
655 | if (activatable && !strcmp (activatable->server_type, "shlib") |
---|
656 | && !(flags & Bonobo_ACTIVATION_FLAG_NO_LOCAL) |
---|
657 | && (hostname && !strcmp (activatable->hostname, hostname))) { |
---|
658 | int j; |
---|
659 | char tbuf[512]; |
---|
660 | |
---|
661 | out->res._d = Bonobo_ACTIVATION_RESULT_SHLIB; |
---|
662 | |
---|
663 | /* Here is an explanation as to why we add 2 to num_layers. |
---|
664 | * At the end of the string list, after all the factory iids are added |
---|
665 | * to the string list, we then add the iid of the shaed library and the |
---|
666 | * location info. This data is later used in oaf_server_activate_shlib |
---|
667 | * to activate the component |
---|
668 | */ |
---|
669 | out->res._u.res_shlib._length = num_layers + 2; |
---|
670 | out->res._u.res_shlib._buffer = CORBA_sequence_CORBA_string_allocbuf (num_layers + 2); |
---|
671 | |
---|
672 | /* Copy over factory info */ |
---|
673 | for (j = 0, activatable = server; activatable |
---|
674 | && !strcmp (activatable->server_type, "factory"); j++) { |
---|
675 | out->res._u.res_shlib._buffer[j] = CORBA_string_dup (activatable->iid); |
---|
676 | activatable = g_hash_table_lookup (child->by_iid, |
---|
677 | activatable->location_info); |
---|
678 | } |
---|
679 | |
---|
680 | /* Copy shlib iid into buffer */ |
---|
681 | out->res._u.res_shlib._buffer[j] = CORBA_string_dup (activatable->iid); |
---|
682 | |
---|
683 | /* Copy location into last buffer slot for use in later activation */ |
---|
684 | out->res._u.res_shlib._buffer[j+1] = CORBA_string_dup (activatable->location_info); |
---|
685 | |
---|
686 | g_snprintf (tbuf, sizeof (tbuf), "OAFAID:[%s,%s,%s]", |
---|
687 | activatable->iid, |
---|
688 | activatable->username, |
---|
689 | activatable->hostname); |
---|
690 | out->aid = CORBA_string_dup (tbuf); |
---|
691 | } else { |
---|
692 | CORBA_Object retval; |
---|
693 | |
---|
694 | retval = Bonobo_ObjectDirectory_activate ( |
---|
695 | child->obj, server->iid, servant->self, environment, flags, ctx, ev); |
---|
696 | |
---|
697 | if (ev->_major == CORBA_NO_EXCEPTION) { |
---|
698 | char tbuf[512]; |
---|
699 | out->res._d = Bonobo_ACTIVATION_RESULT_OBJECT; |
---|
700 | out->res._u.res_object = retval; |
---|
701 | g_snprintf (tbuf, sizeof (tbuf), |
---|
702 | "OAFAID:[%s,%s,%s]", activatable->iid, |
---|
703 | activatable->username, |
---|
704 | activatable->hostname); |
---|
705 | out->aid = CORBA_string_dup (tbuf); |
---|
706 | } |
---|
707 | #ifdef BONOBO_ACTIVATION_DEBUG |
---|
708 | else |
---|
709 | g_warning ("Activation of '%s' failed with exception '%s'", |
---|
710 | activatable->iid, ev->_id); |
---|
711 | #endif |
---|
712 | } |
---|
713 | } |
---|
714 | |
---|
715 | |
---|
716 | static Bonobo_ActivationResult * |
---|
717 | impl_Bonobo_ActivationContext_activateMatching ( |
---|
718 | PortableServer_Servant _servant, |
---|
719 | const CORBA_char *requirements, |
---|
720 | const Bonobo_StringList *selection_order, |
---|
721 | const Bonobo_ActivationEnvironment *environment, |
---|
722 | const Bonobo_ActivationFlags flags, |
---|
723 | CORBA_Context ctx, |
---|
724 | CORBA_Environment *ev) |
---|
725 | { |
---|
726 | impl_POA_Bonobo_ActivationContext *servant = GET_SERVANT (_servant); |
---|
727 | Bonobo_ActivationResult *retval = NULL; |
---|
728 | Bonobo_ServerInfo **items, *curitem; |
---|
729 | int i; |
---|
730 | char *hostname; |
---|
731 | |
---|
732 | ac_update_lists (servant, ev); |
---|
733 | |
---|
734 | servant->refs++; |
---|
735 | |
---|
736 | items = g_alloca (servant->total_servers * |
---|
737 | sizeof (Bonobo_ServerInfo *)); |
---|
738 | ac_query_run (servant, requirements, selection_order, ctx, items, ev); |
---|
739 | |
---|
740 | if (ev->_major != CORBA_NO_EXCEPTION) |
---|
741 | goto out; |
---|
742 | |
---|
743 | hostname = ac_CORBA_Context_get_value (ctx, "hostname", ev); |
---|
744 | |
---|
745 | retval = Bonobo_ActivationResult__alloc (); |
---|
746 | retval->res._d = Bonobo_ACTIVATION_RESULT_NONE; |
---|
747 | |
---|
748 | for (i = 0; (retval->res._d == Bonobo_ACTIVATION_RESULT_NONE) && items[i] |
---|
749 | && (i < servant->total_servers); i++) { |
---|
750 | curitem = items[i]; |
---|
751 | |
---|
752 | ac_do_activation (servant, curitem, environment, |
---|
753 | retval, flags, hostname, ctx, ev); |
---|
754 | } |
---|
755 | |
---|
756 | if (retval->res._d == Bonobo_ACTIVATION_RESULT_NONE) |
---|
757 | retval->aid = CORBA_string_dup (""); |
---|
758 | |
---|
759 | g_free (hostname); |
---|
760 | |
---|
761 | out: |
---|
762 | if (ev->_major != CORBA_NO_EXCEPTION) { |
---|
763 | CORBA_free (retval); |
---|
764 | retval = NULL; |
---|
765 | } |
---|
766 | |
---|
767 | servant->refs--; |
---|
768 | |
---|
769 | return retval; |
---|
770 | } |
---|
771 | |
---|
772 | |
---|
773 | static Bonobo_ServerInfoList * |
---|
774 | impl_Bonobo_ActivationContext__get_servers (PortableServer_Servant _servant, |
---|
775 | CORBA_Environment *ev) |
---|
776 | { |
---|
777 | impl_POA_Bonobo_ActivationContext *servant = GET_SERVANT (_servant); |
---|
778 | Bonobo_ServerInfoList *retval; |
---|
779 | GSList *cur; |
---|
780 | int i; |
---|
781 | int total; |
---|
782 | |
---|
783 | ac_update_lists (servant, ev); |
---|
784 | |
---|
785 | total = servant->total_servers; |
---|
786 | |
---|
787 | retval = Bonobo_ServerInfoList__alloc (); |
---|
788 | retval->_length = total; |
---|
789 | retval->_buffer = CORBA_sequence_Bonobo_ServerInfo_allocbuf (total); |
---|
790 | CORBA_sequence_set_release (retval, CORBA_TRUE); |
---|
791 | |
---|
792 | for (i = 0; i < total;) { |
---|
793 | for (cur = servant->dirs; cur; cur = cur->next) { |
---|
794 | ChildODInfo *child; |
---|
795 | int j; |
---|
796 | |
---|
797 | child = cur->data; |
---|
798 | |
---|
799 | for (j = 0; j < child->list->_length; j++, i++) |
---|
800 | Bonobo_ServerInfo_copy (&retval->_buffer[i], |
---|
801 | &child-> |
---|
802 | list->_buffer[j]); |
---|
803 | } |
---|
804 | } |
---|
805 | |
---|
806 | return retval; |
---|
807 | } |
---|
808 | |
---|
809 | static Bonobo_ServerInfoList * |
---|
810 | impl_Bonobo_ActivationContext_query (PortableServer_Servant _servant, |
---|
811 | const CORBA_char * requirements, |
---|
812 | const Bonobo_StringList * selection_order, |
---|
813 | CORBA_Context ctx, CORBA_Environment * ev) |
---|
814 | { |
---|
815 | impl_POA_Bonobo_ActivationContext *servant = GET_SERVANT (_servant); |
---|
816 | Bonobo_ServerInfoList *retval; |
---|
817 | Bonobo_ServerInfo **items; |
---|
818 | int item_count; |
---|
819 | int i, j, total; |
---|
820 | |
---|
821 | retval = Bonobo_ServerInfoList__alloc (); |
---|
822 | retval->_length = 0; |
---|
823 | retval->_buffer = NULL; |
---|
824 | CORBA_sequence_set_release (retval, CORBA_TRUE); |
---|
825 | |
---|
826 | /* Pull in new lists from OD servers */ |
---|
827 | ac_update_lists (servant, ev); |
---|
828 | servant->refs++; |
---|
829 | |
---|
830 | items = g_alloca (servant->total_servers * |
---|
831 | sizeof (Bonobo_ServerInfo *)); |
---|
832 | item_count = servant->total_servers; |
---|
833 | |
---|
834 | ac_query_run (servant, requirements, selection_order, ctx, items, ev); |
---|
835 | |
---|
836 | if (ev->_major == CORBA_NO_EXCEPTION) { |
---|
837 | for (total = i = 0; i < item_count; i++) { |
---|
838 | if (items[i]) |
---|
839 | total++; |
---|
840 | } |
---|
841 | |
---|
842 | retval->_length = total; |
---|
843 | retval->_buffer = |
---|
844 | CORBA_sequence_Bonobo_ServerInfo_allocbuf (total); |
---|
845 | |
---|
846 | for (i = j = 0; i < item_count; i++) { |
---|
847 | if (!items[i]) |
---|
848 | continue; |
---|
849 | |
---|
850 | Bonobo_ServerInfo_copy (&retval->_buffer[j], items[i]); |
---|
851 | |
---|
852 | j++; |
---|
853 | } |
---|
854 | } |
---|
855 | |
---|
856 | servant->refs--; |
---|
857 | |
---|
858 | return retval; |
---|
859 | } |
---|
860 | |
---|
861 | static char * |
---|
862 | ac_aid_to_query_string (const CORBA_char *aid) |
---|
863 | { |
---|
864 | char *requirements; |
---|
865 | char *iid_requirement; |
---|
866 | char *username_requirement; |
---|
867 | char *hostname_requirement; |
---|
868 | BonoboActivationInfo *ainfo; |
---|
869 | |
---|
870 | ainfo = bonobo_activation_id_parse (aid); |
---|
871 | if (!ainfo) |
---|
872 | return NULL; |
---|
873 | |
---|
874 | iid_requirement = g_strconcat ("iid == \'", ainfo->iid, "\' ", NULL); |
---|
875 | |
---|
876 | if (ainfo->user) { |
---|
877 | username_requirement = g_strconcat ("AND username == \'", ainfo->user, "\'", NULL); |
---|
878 | } else { |
---|
879 | username_requirement = g_strdup (""); |
---|
880 | } |
---|
881 | |
---|
882 | if (ainfo->host) { |
---|
883 | hostname_requirement = g_strconcat ("AND hostname == \'", ainfo->host, "\'", NULL); |
---|
884 | } else { |
---|
885 | hostname_requirement = g_strdup (""); |
---|
886 | } |
---|
887 | |
---|
888 | requirements = g_strconcat (iid_requirement, username_requirement, |
---|
889 | hostname_requirement, NULL); |
---|
890 | |
---|
891 | g_free (iid_requirement); |
---|
892 | g_free (username_requirement); |
---|
893 | g_free (hostname_requirement); |
---|
894 | bonobo_activation_info_free (ainfo); |
---|
895 | |
---|
896 | return requirements; |
---|
897 | } |
---|
898 | |
---|
899 | static void |
---|
900 | ac_context_to_string_array (CORBA_Context context, char **sort_criteria, |
---|
901 | CORBA_Environment *ev) |
---|
902 | { |
---|
903 | char *context_username; |
---|
904 | char *context_hostname; |
---|
905 | |
---|
906 | context_username = ac_CORBA_Context_get_value (context, "username", ev); |
---|
907 | context_hostname = ac_CORBA_Context_get_value (context, "hostname", ev); |
---|
908 | if (ev->_major != CORBA_NO_EXCEPTION) |
---|
909 | return; |
---|
910 | |
---|
911 | sort_criteria[0] = g_strconcat ("username == \'", context_username, "\'", NULL); |
---|
912 | sort_criteria[1] = g_strconcat ("hostname == \'", context_hostname, "\'", NULL); |
---|
913 | sort_criteria[2] = NULL; |
---|
914 | |
---|
915 | g_free (context_username); |
---|
916 | g_free (context_hostname); |
---|
917 | } |
---|
918 | |
---|
919 | #define PARSE_ERROR_NOT_AN_AID (_("Not a valid Activation ID")) |
---|
920 | |
---|
921 | static Bonobo_ActivationResult * |
---|
922 | impl_Bonobo_ActivationContext_activateFromAid (PortableServer_Servant _servant, |
---|
923 | const CORBA_char *aid, |
---|
924 | Bonobo_ActivationFlags flags, |
---|
925 | CORBA_Context ctx, |
---|
926 | CORBA_Environment *ev) |
---|
927 | { |
---|
928 | impl_POA_Bonobo_ActivationContext *servant = GET_SERVANT (_servant); |
---|
929 | Bonobo_ActivationResult *retval; |
---|
930 | char *requirements; |
---|
931 | char *sort_criteria[3]; |
---|
932 | Bonobo_StringList selection_order; |
---|
933 | Bonobo_ActivationEnvironment environment; |
---|
934 | |
---|
935 | if (strncmp ("OAFAID:", aid, 7) != 0) { |
---|
936 | Bonobo_Activation_ParseFailed *ex; |
---|
937 | |
---|
938 | ex = Bonobo_Activation_ParseFailed__alloc (); |
---|
939 | ex->description = CORBA_string_dup (PARSE_ERROR_NOT_AN_AID); |
---|
940 | |
---|
941 | CORBA_exception_set (ev, CORBA_USER_EXCEPTION, |
---|
942 | ex_Bonobo_Activation_ParseFailed, |
---|
943 | ex); |
---|
944 | return NULL; |
---|
945 | } |
---|
946 | |
---|
947 | ac_update_lists (servant, ev); |
---|
948 | if (ev->_major != CORBA_NO_EXCEPTION) |
---|
949 | return NULL; |
---|
950 | |
---|
951 | servant->refs++; |
---|
952 | |
---|
953 | requirements = ac_aid_to_query_string (aid); |
---|
954 | if (requirements == NULL) { |
---|
955 | servant->refs--; |
---|
956 | return NULL; |
---|
957 | } |
---|
958 | |
---|
959 | ac_context_to_string_array (ctx, sort_criteria, ev); |
---|
960 | if (ev->_major != CORBA_NO_EXCEPTION) { |
---|
961 | servant->refs--; |
---|
962 | g_free (requirements); |
---|
963 | return NULL; |
---|
964 | } |
---|
965 | |
---|
966 | selection_order._length = 2; |
---|
967 | selection_order._buffer = sort_criteria; |
---|
968 | CORBA_sequence_set_release (&selection_order, CORBA_FALSE); |
---|
969 | |
---|
970 | memset (&environment, 0, sizeof (Bonobo_ActivationEnvironment)); |
---|
971 | |
---|
972 | retval = impl_Bonobo_ActivationContext_activateMatching ( |
---|
973 | servant, requirements, &selection_order, &environment, flags, ctx, ev); |
---|
974 | |
---|
975 | g_free (sort_criteria[0]); |
---|
976 | g_free (sort_criteria[1]); |
---|
977 | g_free (requirements); |
---|
978 | |
---|
979 | servant->refs--; |
---|
980 | |
---|
981 | return retval; |
---|
982 | } |
---|
983 | |
---|
984 | /*** epv structures ***/ |
---|
985 | |
---|
986 | static PortableServer_ServantBase__epv impl_Bonobo_ActivationContext_base_epv = { |
---|
987 | NULL, /* _private data */ |
---|
988 | NULL, /* finalize routine */ |
---|
989 | NULL /* default_POA routine */ |
---|
990 | }; |
---|
991 | |
---|
992 | /* FIXME: fill me in / deal with me globaly */ |
---|
993 | static POA_Bonobo_Unknown__epv impl_Bonobo_Unknown_epv = { |
---|
994 | NULL, /* _private data */ |
---|
995 | NULL, |
---|
996 | NULL, |
---|
997 | NULL |
---|
998 | }; |
---|
999 | |
---|
1000 | static POA_Bonobo_ActivationContext__epv impl_Bonobo_ActivationContext_epv = { |
---|
1001 | NULL, /* _private */ |
---|
1002 | impl_Bonobo_ActivationContext__get_directories, |
---|
1003 | impl_Bonobo_ActivationContext__get_servers, |
---|
1004 | impl_Bonobo_ActivationContext_addClient, |
---|
1005 | impl_Bonobo_ActivationContext_addDirectory, |
---|
1006 | impl_Bonobo_ActivationContext_removeDirectory, |
---|
1007 | impl_Bonobo_ActivationContext_query, |
---|
1008 | impl_Bonobo_ActivationContext_activateMatching, |
---|
1009 | impl_Bonobo_ActivationContext_activateFromAid |
---|
1010 | }; |
---|
1011 | |
---|
1012 | /*** vepv structures ***/ |
---|
1013 | |
---|
1014 | static POA_Bonobo_ActivationContext__vepv impl_Bonobo_ActivationContext_vepv = { |
---|
1015 | &impl_Bonobo_ActivationContext_base_epv, |
---|
1016 | &impl_Bonobo_Unknown_epv, |
---|
1017 | &impl_Bonobo_ActivationContext_epv |
---|
1018 | }; |
---|
1019 | |
---|
1020 | static impl_POA_Bonobo_ActivationContext *main_ac = NULL; |
---|
1021 | |
---|
1022 | void |
---|
1023 | activation_context_init (PortableServer_POA poa, |
---|
1024 | Bonobo_ObjectDirectory dir, |
---|
1025 | CORBA_Environment *ev) |
---|
1026 | { |
---|
1027 | PortableServer_ObjectId *objid; |
---|
1028 | impl_POA_Bonobo_ActivationContext *servant; |
---|
1029 | |
---|
1030 | servant = g_new0 (impl_POA_Bonobo_ActivationContext, 1); |
---|
1031 | |
---|
1032 | main_ac = servant; |
---|
1033 | |
---|
1034 | servant->servant.vepv = &impl_Bonobo_ActivationContext_vepv; |
---|
1035 | POA_Bonobo_ActivationContext__init ((PortableServer_Servant) servant, ev); |
---|
1036 | objid = PortableServer_POA_activate_object (poa, servant, ev); |
---|
1037 | CORBA_free (objid); |
---|
1038 | |
---|
1039 | servant->self = PortableServer_POA_servant_to_reference (poa, servant, ev); |
---|
1040 | |
---|
1041 | impl_Bonobo_ActivationContext_addDirectory (servant, dir, ev); |
---|
1042 | } |
---|
1043 | |
---|
1044 | void |
---|
1045 | activation_context_shutdown (PortableServer_POA poa, |
---|
1046 | CORBA_Environment *ev) |
---|
1047 | { |
---|
1048 | PortableServer_ObjectId *oid; |
---|
1049 | impl_POA_Bonobo_ActivationContext *servant = main_ac; |
---|
1050 | |
---|
1051 | oid = PortableServer_POA_servant_to_id (poa, servant, ev); |
---|
1052 | PortableServer_POA_deactivate_object (poa, oid, ev); |
---|
1053 | CORBA_free (oid); |
---|
1054 | |
---|
1055 | main_ac = NULL; |
---|
1056 | |
---|
1057 | free_child_dirs (servant, ev); |
---|
1058 | CORBA_Object_release (servant->self, ev); |
---|
1059 | |
---|
1060 | g_free (servant); |
---|
1061 | } |
---|
1062 | |
---|
1063 | Bonobo_ActivationContext |
---|
1064 | activation_context_get (void) |
---|
1065 | { |
---|
1066 | if (!main_ac) |
---|
1067 | return CORBA_OBJECT_NIL; |
---|
1068 | else |
---|
1069 | return main_ac->self; |
---|
1070 | } |
---|