]> rtime.felk.cvut.cz Git - frescor/forb.git/blob - src/forb.c
Reference registry disabled when INET proto is default
[frescor/forb.git] / src / forb.c
1 /**************************************************************************/
2 /* ---------------------------------------------------------------------- */
3 /* Copyright (C) 2006 - 2008 FRESCOR consortium partners:                 */
4 /*                                                                        */
5 /*   Universidad de Cantabria,              SPAIN                         */
6 /*   University of York,                    UK                            */
7 /*   Scuola Superiore Sant'Anna,            ITALY                         */
8 /*   Kaiserslautern University,             GERMANY                       */
9 /*   Univ. Politécnica  Valencia,           SPAIN                        */
10 /*   Czech Technical University in Prague,  CZECH REPUBLIC                */
11 /*   ENEA                                   SWEDEN                        */
12 /*   Thales Communication S.A.              FRANCE                        */
13 /*   Visual Tools S.A.                      SPAIN                         */
14 /*   Rapita Systems Ltd                     UK                            */
15 /*   Evidence                               ITALY                         */
16 /*                                                                        */
17 /*   See http://www.frescor.org for a link to partners' websites          */
18 /*                                                                        */
19 /*          FRESCOR project (FP6/2005/IST/5-034026) is funded             */
20 /*       in part by the European Union Sixth Framework Programme          */
21 /*       The European Union is not liable of any use that may be          */
22 /*       made of this code.                                               */
23 /*                                                                        */
24 /*                                                                        */
25 /*  This file is part of FORB (Frescor Object Request Broker)             */
26 /*                                                                        */
27 /* FORB is free software; you can redistribute it and/or modify it        */
28 /* under terms of the GNU General Public License as published by the      */
29 /* Free Software Foundation; either version 2, or (at your option) any    */
30 /* later version.  FORB is distributed in the hope that it will be        */
31 /* useful, but WITHOUT ANY WARRANTY; without even the implied warranty    */
32 /* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU    */
33 /* General Public License for more details. You should have received a    */
34 /* copy of the GNU General Public License along with FORB; see file       */
35 /* COPYING. If not, write to the Free Software Foundation, 675 Mass Ave,  */
36 /* Cambridge, MA 02139, USA.                                              */
37 /*                                                                        */
38 /* As a special exception, including FORB header files in a file,         */
39 /* instantiating FORB generics or templates, or linking other files       */
40 /* with FORB objects to produce an executable application, does not       */
41 /* by itself cause the resulting executable application to be covered     */
42 /* by the GNU General Public License. This exception does not             */
43 /* however invalidate any other reasons why the executable file might be  */
44 /* covered by the GNU Public License.                                     */
45 /**************************************************************************/
46
47 /**
48  * @file   forb.c
49  * @author Michal Sojka <sojkam1@fel.cvut.cz>
50  * @date   Sun Oct 12 16:57:01 2008
51  * 
52  * @brief  Implementation of basic FORB's functions.
53  * 
54  * 
55  */
56
57 #ifndef _BSD_SOURCE
58 #define _BSD_SOURCE             /* Because of on_exit()  */
59 #endif
60 #include "proto.h"
61 #include "regref.h"
62 #include <forb/config.h>
63 #include <forb/forb-internal.h>
64 #include <forb.h>
65 #include "forb-idl.h"
66 #include <forb/iop.h>
67 #include <forb/object.h>
68 #include <forb/uuid.h>
69 #include <stdio.h>
70 #include <string.h>
71 #include <sys/stat.h>
72 #include <sys/types.h>
73 #include <ul_gavlcust.h>
74 #include <ul_log.h>
75 #include <ul_logreg.h>
76 #include <unistd.h>
77 #ifdef CONFIG_FORB_PROTO_UNIX
78 #include <forb/proto_unix.h>
79 #endif
80 #ifdef CONFIG_FORB_PROTO_INET_DEFAULT
81 #include <forb/proto_inet.h>
82 #endif
83
84
85 #ifdef DEBUG
86 #define UL_LOGL_DEF UL_LOGL_DEB
87 #else
88 #define UL_LOGL_DEF UL_LOGL_ERR
89 #endif
90 #include "log_domains.inc"
91
92 extern UL_LOG_CUST(ulogd_forb);
93
94 UL_LOGREG_DOMAINS_INIT_FUNCTION(forb_logreg_domains, forb_logreg_domains_array);
95
96 static void
97 destroy_forb_on_exit(int exitcode, void *arg)
98 {
99         forb_orb orb = arg;
100         forb_destroy(orb);
101 }
102
103 static void
104 forb_is_alive(forb_orb _obj, CORBA_Environment *ev)
105 {
106         ul_logdeb("%s called\n", __FUNCTION__);
107 }
108
109 static struct forb_forb_orb_impl forb_implementation = {
110         .is_alive = forb_is_alive,
111 };
112
113 /**
114  * Prepares #FORB_TMP_DIR directory for use by forb
115  *
116  * @return Zero on succes, -1 on error and errno is set appropriately.
117  */
118 int
119 forb_init_tmp_dir(void)
120 {
121         struct stat st;
122         int ret;
123
124         ret = stat(FORB_TMP_DIR, &st);
125
126         if (ret == 0 && !S_ISDIR(st.st_mode)) {
127                 ret = unlink(FORB_TMP_DIR);
128                 if (ret) return -1;
129         } else if (ret == 0) {
130                 return 0;
131         }
132         return mkdir(FORB_TMP_DIR, 0777);
133 }
134
135 /** 
136  * Thread for execution of remote requests for a FORB object.
137  * 
138  * @param arg 
139  * 
140  * @return 
141  */
142 static void *
143 forb_execution_thread(void *arg)
144 {
145         forb_orb orb = arg;
146
147         forb_execute_object(orb);
148         return NULL;
149 }
150
151 forb_orb
152 forb_init(int *argc, char **argv[], const struct forb_init_attr *attr)
153 {
154         forb_orb orb;
155         forb_t *forb;
156         int ret;
157
158         forb = forb_malloc(sizeof(*forb));
159         if (!forb) goto err;
160         memset(forb, 0, sizeof(*forb));
161
162         /* Initialize ULUT logging facility */
163         forb_logreg_domains();
164
165         if (attr) {
166                 forb->attr = *attr;
167         } else {
168                 memset(&forb->attr, 0, sizeof(forb->attr));
169         }
170
171         if (forb_server_id_empty(&forb->attr.fixed_server_id)) {
172                 forb_server_id_init(&forb->server_id);
173         } else {
174                 forb->server_id = forb->attr.fixed_server_id;
175         }
176         forb_server_id_to_string(forb->server_id_str, &forb->server_id,
177                                  sizeof(forb->server_id_str));
178         ul_logdeb("Initializing forb %s\n", forb->server_id_str);
179
180         if (fosa_mutex_init(&forb->request_id_mutex, 0) != 0) goto err2;
181         if (fosa_mutex_init(&forb->port_mutex, 0) != 0) goto err2;
182         forb_port_init_head(forb);
183         
184         if (fosa_mutex_init(&forb->request_mutex, 0) != 0) goto err2;
185         forb_request_nolock_init_root_field(forb);
186         
187         if (fosa_mutex_init(&forb->peer_mutex, 0) != 0) goto err2;
188         forb_peer_nolock_init_root_field(forb);
189
190         if (fosa_mutex_init(&forb->objkey_mutex, 0) != 0) goto err2;
191         forb_objects_nolock_init_root_field(forb);
192
193         if (fosa_mutex_init(&forb->regref_mutex, 0) != 0) goto err2;
194         forb_regref_nolock_init_root_field(forb);
195
196         ret = forb_init_tmp_dir();
197         if (ret != 0) {
198                 ul_logerr("Cannot prepare " FORB_TMP_DIR "\n");
199                 return NULL;
200         }
201
202         orb = forb_forb_orb_new(NULL, &forb_implementation, forb);
203         if (!orb) goto err2;
204         /* Server ID must be assigned manualy */
205         orb->server = forb->server_id;
206
207         forb->orb = orb;
208
209         /* Insert our object reference to objects tree, so that we
210          * can accept remote request to our new ORB. */
211         forb_objects_nolock_insert(forb, orb);
212
213         ret = fosa_thread_create(&forb->execution_thread, NULL,
214                                  forb_execution_thread, orb);
215         if (ret != 0)
216                 goto err2;
217         
218         on_exit(destroy_forb_on_exit, orb);
219
220 #ifdef CONFIG_FORB_PROTO_UNIX
221         {
222                 forb_port_t *port = forb_malloc(sizeof(*port));
223                 if (port) {
224                         memset(port, 0, sizeof(*port));
225                         ret = forb_unix_port_init(&port->desc, &forb->server_id);
226                         if (ret) goto err_free_unix;
227                         ret = forb_register_port(orb, port);
228                         if (ret) goto err_free_unix; /* TODO: forb_unix_port_done() */
229                         goto unix_ok;
230                 }
231         err_free_unix:
232                 free(port);
233                 goto err2;
234         unix_ok:;
235         }
236 #endif
237 #ifdef CONFIG_FORB_PROTO_INET_DEFAULT
238         {
239                 forb_port_t *port = forb_malloc(sizeof(*port));
240                 if (port) {
241                         struct in_addr listen_on;
242
243                         memset(port, 0, sizeof(*port));
244                         listen_on.s_addr = INADDR_ANY;
245                         ret = forb_inet_port_init(&port->desc, listen_on,
246                                                   forb->attr.fixed_tcp_port);
247                         if (ret) goto err_free_inet;
248                         ret = forb_register_port(orb, port);
249                         if (ret) goto err_free_inet; /* TODO: forb_inet_port_done() */
250                         goto inet_ok;
251                 }
252         err_free_inet:
253                 free(port);
254                 goto err2;
255         inet_ok:;
256         }
257 #endif
258         return orb;
259
260 err2:   forb_free(forb);
261 err:    return NULL;
262 }
263
264 /* FIXME: forb_destroy is now called automatically on exit. Therefore
265  * forb_destroy() should be either static or should deregister on_exit
266  * handler (how???).  */
267 void forb_destroy(forb_orb orb)
268 {
269         forb_t *forb = forb_object_to_forb(orb);
270         forb_port_t *port;
271         forb_regref_t *regref;
272
273         pthread_cancel(forb->execution_thread.pthread_id);
274         pthread_join(forb->execution_thread.pthread_id, NULL);
275         
276         /* Unregister all registered references */
277         while ((regref = forb_regref_first(forb))) {
278                 forb_unregister_reference(orb, regref->name.str);
279         }
280         
281         ul_list_for_each_cut(forb_port, forb, port) {
282                 forb_destroy_port(port);
283         }
284         forb_object_release(orb);
285         forb_free(forb);
286 }
287
288 /* void */
289 /* forb_register_interface(const struct forb_interface *interface) */
290 /* { */
291 /*      gavl_insert(&type_registry, &interface->node); */
292 /* } */
293
294 /** 
295  * Initializes server ID variable.
296  * 
297  * @param server_id Serer ID to initialize.
298  */
299 void
300 forb_server_id_init(forb_server_id *server_id)
301 {
302         forb_uuid_generate((forb_uuid_t*)server_id->uuid);
303 }
304
305 /** 
306  * Checks whether the @a object is stale. Stale object is an object
307  * reference whose server cannot be contacted to handle requests.
308  * 
309  * @param object Object reference to check.
310  * 
311  * @return True if the object is stale, false otherwise.
312  */
313 bool forb_object_is_stale(forb_object object)
314 {
315         forb_orb remote_orb;
316         struct forb_env env;
317         bool stale = true;
318         
319         remote_orb = forb_get_orb_of(object);
320         if (!remote_orb) {      /* This shohuld never happen */
321                 goto err;
322         }
323         /* TODO: Check not only the ORB, but also whether the object
324          * is still registered with the remote orb. */
325         forb_orb_is_alive(remote_orb, &env);
326         if (env.major == FORB_EX_COMM_FAILURE) {
327                 /* Orb is not alive */
328                 stale = true;
329         } else {
330                 if (forb_exception_occurred(&env)) {
331                         ul_logerr("%s: unexpected exception: %s\n", __FUNCTION__, forb_strerror(&env));
332                 }
333                 stale = false;  
334         }
335
336         forb_object_release(remote_orb);
337 err:
338         return stale;
339 }
340
341
342 /** 
343  * Returns object reference of forb::orb object associated with the
344  * given object.
345  * 
346  * @param obj 
347  * 
348  * @return 
349  */
350 forb_orb
351 forb_get_orb_of(const forb_object obj)
352 {
353         forb_orb orb;
354
355         if (forb_server_id_cmp(&obj->server, &obj->orb->server) == 0) {
356                 orb = forb_object_duplicate(obj->orb);
357         } else {
358                 orb = forb_object_new(obj->orb, &obj->server, 0);
359         }
360         return orb;
361 }
362
363 /** 
364  * Returns server ID of an object reference.
365  * 
366  * @param obj 
367  * @param dest 
368  */
369 void
370 forb_get_server_id(const forb_object obj, forb_server_id *dest)
371 {
372         if (obj) {
373                 *dest = obj->server;
374         }
375 }
376
377
378 /** 
379  * Return instance data registered when the object was created by
380  * forb_XXX_new().
381  * 
382  * @param obj Object reference
383  * 
384  * @return Pointer to the registered data.
385  */
386 void *
387 forb_instance_data(const forb_object obj)
388 {
389         return forb_object_instance_data(obj);
390 }
391
392 /** 
393  * Returns error message correspondings FORB exception.
394  * 
395  * @param env Environemnt
396  * 
397  * @return Non-NULL pointer to a string.
398  */
399 const char *
400 forb_strerror(CORBA_Environment *env)
401 {
402         if (!env) {
403                 return "Invalid environemnt";
404         }
405 #define ex(e) case FORB_EX_##e: return #e; break;
406         switch (env->major) {
407         ex(NONE);
408         ex(UNKNOWN);
409         ex(BAD_PARAM);
410         ex(NO_MEMORY);
411         ex(IMP_LIMIT);
412         ex(COMM_FAILURE);
413         ex(INV_OBJREF);
414         ex(NO_PERMISSION);
415         ex(INTERNAL);
416         ex(MARSHAL);
417         ex(INITIALIZE);
418         ex(NO_IMPLEMENT);
419         ex(BAD_OPERATION);
420         ex(NO_RESOURCES);
421         ex(NO_RESPONSE);
422         ex(TRANSIENT);
423         ex(FREE_MEM);
424         ex(INV_IDENT);
425         ex(INV_FLAG);
426         ex(DATA_CONVERSION);
427         ex(OBJECT_NOT_EXIST);
428         ex(TIMEOUT);
429         ex(APPLICATION);
430         }
431 #undef ex
432         return "Invalid error number";
433 }
434
435 /** 
436  * Return server id of the requesting application.
437  *
438  * This function should be only called from within interface
439  * implementation,
440  * 
441  * @param[in] obj Object being requested
442  * @param[out] req_source Server ID of the requesting application
443  */
444 void
445 forb_get_req_source(const forb_object obj, forb_server_id *req_source)
446 {
447         if (req_source) {
448                 if (obj && obj->exec_req) {
449                         *req_source = obj->exec_req->source;
450                 } else {
451                         memset(req_source, 0, sizeof(*req_source));
452                 }
453         }
454 }
455
456 /**
457  * Internal function for allocation of sequence bufers. Used by
458  * forb_sequence_alloc_buf().
459  *
460  * @param seq
461  * @param seq_size
462  * @param buf_pptr
463  * @param maximum_ptr
464  * @param num_elements
465  * @param elem_size
466  *
467  * @return CORBA_TRUE if the allocation was sucessfull, CORBA_FALSE if wasn't.
468  */
469 CORBA_boolean
470 __forb_sequence_alloc_buf_internal(void *seq, size_t seq_size,
471                                    void **buf_pptr, CORBA_unsigned_long *maximum_ptr,
472                                    unsigned num_elements, size_t elem_size)
473 {
474         memset(seq, 0, seq_size);
475         /*(seq)._length = 0;*/
476         if (num_elements && elem_size) *buf_pptr = forb_malloc(num_elements * elem_size);
477         else *buf_pptr = NULL;
478         *maximum_ptr = *buf_pptr ? num_elements : 0;
479         return (*buf_pptr != NULL) || (num_elements == 0);
480 }