1 /**************************************************************************/
2 /* ---------------------------------------------------------------------- */
3 /* Copyright (C) 2006 - 2008 FRESCOR consortium partners: */
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 */
12 /* Thales Communication S.A. FRANCE */
13 /* Visual Tools S.A. SPAIN */
14 /* Rapita Systems Ltd UK */
17 /* See http://www.frescor.org for a link to partners' websites */
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. */
25 /* This file is part of FORB (Frescor Object Request Broker) */
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. */
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 /**************************************************************************/
49 * @author Michal Sojka <sojkam1@fel.cvut.cz>
50 * @date Sun Oct 12 16:57:01 2008
52 * @brief Implementation of basic FORB's functions.
58 #define _BSD_SOURCE /* Because of on_exit() */
62 #include <forb/config.h>
63 #include <forb/forb-internal.h>
67 #include <forb/object.h>
68 #include <forb/uuid.h>
72 #include <sys/types.h>
73 #include <ul_gavlcust.h>
75 #include <ul_logreg.h>
77 #include "discovery.h"
78 #ifdef CONFIG_FORB_PROTO_UNIX
79 #include <forb/proto_unix.h>
81 #ifdef CONFIG_FORB_PROTO_INET_DEFAULT
82 #include <forb/proto_inet.h>
86 #include <fcb_contact_info.h>
87 #include <wifi_agent.h>
92 #define UL_LOGL_DEF UL_LOGL_DEB
94 #define UL_LOGL_DEF UL_LOGL_ERR
96 #include "log_domains.inc"
98 extern UL_LOG_CUST(ulogd_forb);
99 static int init_ul_log(void);
101 UL_LOGREG_DOMAINS_INIT_FUNCTION(forb_logreg_domains, forb_logreg_domains_array);
105 destroy_forb_on_exit(int exitcode, void *arg)
113 forb_is_alive(forb_orb _obj, CORBA_Environment *ev)
115 ul_logdeb("%s called\n", __FUNCTION__);
118 static struct forb_forb_orb_impl forb_implementation = {
119 .is_alive = forb_is_alive,
123 * Prepares #FORB_TMP_DIR directory for use by forb
125 * @return Zero on succes, -1 on error and errno is set appropriately.
128 forb_init_tmp_dir(void)
133 ret = stat(FORB_TMP_DIR, &st);
135 if (ret == 0 && !S_ISDIR(st.st_mode)) {
136 ret = unlink(FORB_TMP_DIR);
138 } else if (ret == 0) {
141 return mkdir(FORB_TMP_DIR, 0777);
145 * Thread for execution of remote requests for a FORB object.
152 forb_execution_thread(void *arg)
154 forb_executor_t *executor = arg;
155 forb_executor_run(executor);
160 void hack_register_fcb(forb_orb orb, forb_port_t *port)
162 forb_object fcb = forb_object_new(orb, &FCB_SERVER_ID, 1);
164 ul_logerr("Cannot allocate FCB reference\n");
167 forb_register_reference(fcb, fres_contract_broker_reg_name);
168 forb_object_release(fcb);
172 forb_object wai = forb_object_new(orb, &WAI_SERVER_ID, 1);
174 ul_logerr("Cannot allocate WAI reference\n");
177 forb_register_reference(wai, "net.sourceforge.frsh-forb.wai");
178 forb_object_release(wai);
181 #define hack_register_fcb(orb)
187 forb_init(int *argc, char **argv[], const struct forb_init_attr *attr)
193 forb = forb_malloc(sizeof(*forb));
195 memset(forb, 0, sizeof(*forb));
197 /* Initialize ULUT logging facility */
199 forb_logreg_domains();
204 memset(&forb->attr, 0, sizeof(forb->attr));
207 sem_init(&forb->server_ready, 0, 0);
209 if (forb_server_id_empty(&forb->attr.fixed_server_id)) {
210 forb_server_id_init(&forb->server_id);
212 forb->server_id = forb->attr.fixed_server_id;
214 forb_server_id_to_string(forb->server_id_str, &forb->server_id,
215 sizeof(forb->server_id_str));
216 ul_logdeb("Initializing forb %s\n", forb->server_id_str);
218 if (fosa_mutex_init(&forb->request_id_mutex, 0) != 0) goto err2;
219 if (fosa_mutex_init(&forb->port_mutex, 0) != 0) goto err2;
220 forb_port_init_head(forb);
222 if (fosa_mutex_init(&forb->request_mutex, 0) != 0) goto err2;
223 forb_request_nolock_init_root_field(forb);
225 if (forb_discovery_init(forb) != 0) goto err2;
227 if (fosa_mutex_init(&forb->regref_mutex, 0) != 0) goto err2;
228 forb_regref_nolock_init_root_field(forb);
230 ret = forb_init_tmp_dir();
232 ul_logerr("Cannot prepare " FORB_TMP_DIR "\n");
236 forb_executor_prepare();
238 orb = forb_forb_orb_new(NULL, &forb_implementation, forb);
240 /* Server ID must be assigned manualy */
241 orb->server = forb->server_id;
245 /* Insert our object reference to objects tree, so that we
246 * can accept remote request to our new ORB. */
247 forb_objects_nolock_insert(forb, orb);
249 ret = forb_executor_init(&forb->default_executor);
251 ret = forb_executor_register_object(&forb->default_executor, orb);
254 ret = fosa_thread_create(&forb->execution_thread, NULL,
255 forb_execution_thread, &forb->default_executor);
259 /* FIXME: I do not know how to deregister the exit handler if
260 * forb_destroy() is called manually. */
261 /* on_exit(destroy_forb_on_exit, orb); */
263 #ifdef CONFIG_FORB_PROTO_UNIX
265 forb_port_t *port = forb_malloc(sizeof(*port));
267 memset(port, 0, sizeof(*port));
268 ret = forb_unix_port_init(&port->desc, &forb->server_id);
269 if (ret) goto err_free_unix;
270 ret = forb_register_port(orb, port);
271 if (ret) goto err_free_unix; /* TODO: forb_unix_port_done() */
280 #ifdef CONFIG_FORB_PROTO_INET_DEFAULT
282 forb_port_t *port = forb_malloc(sizeof(*port));
284 struct in_addr listen_on;
286 memset(port, 0, sizeof(*port));
287 listen_on.s_addr = INADDR_ANY;
288 ret = forb_inet_port_init(&port->desc, listen_on,
289 forb->attr.fixed_tcp_port);
290 if (ret) goto err_free_inet;
291 ret = forb_register_port(orb, port);
292 if (ret) goto err_free_inet; /* TODO: forb_inet_port_done() */
299 hack_register_fcb(orb, port);
304 err3: forb_executor_destroy(&forb->default_executor);
305 err2: forb_free(forb);
309 void forb_destroy(forb_orb orb)
311 forb_t *forb = forb_object_to_forb(orb);
313 forb_regref_t *regref;
316 /* Stop ports to prevent remote requests from coming */
317 ul_list_for_each(forb_port, forb, port) {
318 forb_stop_port(port);
321 /* Wait for executors to finish all requests (and thus drop
322 * all references to peers). This is very inefficient for big
323 * number of objects, but we do not care */
324 gavl_cust_for_each(forb_objects_nolock, forb, obj) {
325 forb_executor_t *executor;
326 executor = forb_object_get_executor(obj);
328 forb_executor_synchronize(executor);
331 /* Destroy ports - this should drop all remaining references
332 * to peers and result in closing of all remote
334 ul_list_for_each_cut(forb_port, forb, port) {
335 forb_destroy_port(port);
338 pthread_cancel(forb->execution_thread.pthread_id);
339 pthread_join(forb->execution_thread.pthread_id, NULL);
341 /* Unregister all registered references */
342 while ((regref = forb_regref_first(forb))) {
343 forb_unregister_reference(orb, regref->name.str);
346 forb_object_release(orb);
351 /* forb_register_interface(const struct forb_interface *interface) */
353 /* gavl_insert(&type_registry, &interface->node); */
357 * Initializes server ID variable.
359 * @param server_id Serer ID to initialize.
362 forb_server_id_init(forb_server_id *server_id)
364 forb_uuid_generate((forb_uuid_t*)server_id->uuid);
368 * Checks whether the @a object is stale. Stale object is an object
369 * reference whose server cannot be contacted to handle requests.
371 * @param object Object reference to check.
373 * @return True if the object is stale, false otherwise.
375 bool forb_object_is_stale(forb_object object)
381 remote_orb = forb_get_orb_of(object);
382 if (!remote_orb) { /* This shohuld never happen */
385 /* TODO: Check not only the ORB, but also whether the object
386 * is still registered with the remote orb. */
387 forb_orb_is_alive(remote_orb, &env);
388 if (env.major == FORB_EX_COMM_FAILURE) {
389 /* Orb is not alive */
392 if (forb_exception_occurred(&env)) {
393 ul_logerr("%s: unexpected exception: %s\n", __FUNCTION__, forb_strerror(&env));
398 forb_object_release(remote_orb);
405 * Returns object reference of forb::orb object associated with the
413 forb_get_orb_of(const forb_object obj)
417 if (forb_server_id_cmp(&obj->server, &obj->orb->server) == 0) {
418 orb = forb_object_duplicate(obj->orb);
420 orb = forb_object_new(obj->orb, &obj->server, 0);
426 * Returns server ID of an object reference.
432 forb_get_server_id(const forb_object obj, forb_server_id *dest)
441 * Return instance data registered when the object was created by
444 * @param obj Object reference
446 * @return Pointer to the registered data.
449 forb_instance_data(const forb_object obj)
451 return forb_object_instance_data(obj);
455 * Returns error message correspondings FORB exception.
457 * @param env Environemnt
459 * @return Non-NULL pointer to a string.
462 forb_strerror(CORBA_Environment *env)
465 return "Invalid environemnt";
467 #define ex(e) case FORB_EX_##e: return #e; break;
468 switch (env->major) {
489 ex(OBJECT_NOT_EXIST);
494 return "Invalid error number";
498 * Return server id of the requesting application.
500 * This function should be only called from within interface
503 * @param[in] obj Object being requested
504 * @param[out] req_source Server ID of the requesting application
507 forb_get_req_source(const forb_object obj, forb_server_id *req_source)
510 if (obj && obj->exec_req) {
511 *req_source = obj->exec_req->source;
513 memset(req_source, 0, sizeof(*req_source));
519 * Internal function for allocation of sequence bufers. Used by
520 * forb_sequence_alloc_buf().
526 * @param num_elements
529 * @return CORBA_TRUE if the allocation was sucessfull, CORBA_FALSE if
533 __forb_sequence_alloc_buf_internal(void *seq, size_t seq_size,
534 void **buf_pptr, CORBA_unsigned_long *maximum_ptr,
535 unsigned num_elements, size_t elem_size)
537 memset(seq, 0, seq_size);
538 /*(seq)._length = 0;*/
539 if (num_elements && elem_size) *buf_pptr = forb_malloc(num_elements * elem_size);
540 else *buf_pptr = NULL;
541 *maximum_ptr = *buf_pptr ? num_elements : 0;
542 return (*buf_pptr != NULL) || (num_elements == 0);
545 static FILE *forb_ul_log_file;
546 static char progname[64] = "";
549 forb_ul_log_fnc(ul_log_domain_t *domain, int level,
550 const char *format, va_list ap)
553 if(!(level&UL_LOGL_CONT)) {
555 clock_gettime(CLOCK_MONOTONIC, &now);
556 fprintf(forb_ul_log_file,"%ld.%6ld: ", now.tv_sec, now.tv_nsec/1000);
558 fprintf(forb_ul_log_file,"%s: ", progname);
559 if(domain && domain->name)
560 fprintf(forb_ul_log_file,"%s: ",domain->name);
562 vfprintf(forb_ul_log_file, format, ap);
563 fflush(forb_ul_log_file);
566 static int init_ul_log(void)
574 /* if(ul_log_output != NULL) */
577 fd = open("/proc/self/cmdline", O_RDONLY);
580 ret = read(fd, path, sizeof(path)-1);
583 s = strrchr(path, '/');
586 strncpy(progname, s, sizeof(progname)-1);
591 if((log_fname=getenv("UL_LOG_FILENAME"))!=NULL){
592 forb_ul_log_file=fopen(log_fname,"a");
594 if(forb_ul_log_file==NULL)
595 forb_ul_log_file=stderr;
597 if((s=getenv("UL_DEBUG_FLG")) != NULL){
601 ul_log_redir(forb_ul_log_fnc, flg);
603 if((s = getenv("UL_LOG_LEVELS")) != NULL)
604 ul_log_domain_arg2levels(s);
610 * Wait for the server to be ready. Internal function intended forb
615 * @return Zero on success; on error -1 is returned, and errno is set
616 * to indicate the error.
618 int forb_wait_for_server_ready(forb_orb orb)
620 forb_t *forb = forb_object_to_forb(orb);
621 return sem_wait(&forb->server_ready);
625 * Signal the the FORB core that the server is ready for accepting
628 * This function should be called at the initialization of server
629 * implementation at the time when all objects are registered with
630 * executors. All other servers in the same address space are
631 * initialized after this function is called which allows the other
632 * servers to use the services provided by the calling server.
634 * @param orb ORB object.
636 * @return Zero on success; on error -1 is returned, and errno is set
637 * to indicate the error.
639 int forb_signal_server_ready(forb_orb orb)
641 forb_t *forb = forb_object_to_forb(orb);
642 return sem_post(&forb->server_ready);