]> rtime.felk.cvut.cz Git - frescor/forb.git/blob - src/regref.c
forb_request_send() moved to iop.c
[frescor/forb.git] / src / regref.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 #include "regref.h"
48 #include "object.h"
49 #include <fcntl.h>
50 #include <stdlib.h>
51 #include <stdio.h>
52 #include <ul_log.h>
53 #include <forb/config.h>
54
55 extern UL_LOG_CUST(ulogd_forb_regref);
56
57 static inline int forb_regref_cmp(const forb_regref_name_t *a, const forb_regref_name_t *b)
58 {
59         return strncmp(a->str, b->str, FORB_REGREF_NAME_LEN);
60 }
61
62 GAVL_CUST_NODE_INT_IMP(forb_regref_nolock /* cust_prefix */,
63                        forb_t /* cust_root_t */,
64                        forb_regref_t /* cust_item_t */,
65                        forb_regref_name_t /* cust_key_t */,
66                        regrefs /* cust_root_node */,
67                        node /* cust_item_node */,
68                        name /* cust_item_key */,
69                        forb_regref_cmp/* cust_cmp_fnc */);
70
71 /** 
72  * Allocates a new ::forb_regref_t structure and fills it with data.
73  * 
74  * @param object Object reference to register.
75  * 
76  * @param name Name of the registered object reference, which can be
77  * used by other applications in forb_resolve_reference().
78  * 
79  * @return Pointer to the newly allocated regref of NULL in case of error.
80  */
81 forb_regref_t *
82 forb_regref_new(forb_object object, forb_regref_name_t name)
83 {
84         forb_regref_t *regref;
85
86         regref = forb_malloc(sizeof(*regref));
87         if (regref) {
88                 regref->name = name;
89                 regref->object = forb_object_duplicate(object);
90         }
91         return regref;
92 }
93
94 /** 
95  * Releases ::forb_regref_t previously allocated by forb_regref_new().
96  * 
97  * @param regref Regref to release.
98  */
99 void 
100 forb_regref_release(forb_regref_t *regref)
101 {
102         if (regref) {
103                 forb_object_release(regref->object);
104                 forb_free(regref);
105         }
106 }
107
108
109
110 #ifndef CONFIG_FORB_PROTO_INET_DEFAULT
111 /** 
112  * 
113  * 
114  * @param fd 
115  * @param objref 
116  * 
117  * @return Zero on success, -1 on error.
118  */
119 static int
120 rewrite_regref(int fd, const char *objref)
121 {
122         int ret;
123         int len = strlen(objref);
124         lseek(fd, 0, SEEK_SET);
125         ftruncate(fd, 0);
126                 
127         while (len > 0) {
128                 ret = write(fd, objref, len);
129                 if (ret < 0) goto out;
130                 len -= ret;
131                 objref += ret;
132         }
133         ret = 0;        /* Success */
134 out:
135         return ret;
136 }
137
138 /** 
139  * 
140  * 
141  * @param orb 
142  * @param fn File name
143  * @param objref string form of the object reference
144  * 
145  * @return -1 on error, 0 if reference was replaced and 1 in the
146  * reference is valid.
147  */
148 static int
149 replace_regref_if_stale(forb_orb orb, const char *fn, const char *objref)
150 {
151         int fd, ret = 0; 
152         char str[100];
153         forb_object object;
154         
155         fd = open(fn, O_RDWR);
156         if (fd < 0) {
157                 ret = -1;
158                 goto out;
159         }
160         ret = lockf(fd, F_LOCK, 0);
161         if (ret < 0) goto close_err;
162         ret = read(fd, str, sizeof(str)-1);
163         if (ret < 0) goto unlock_err;
164         /* TODO: Check that we have read the whole file */
165         
166         str[ret] = '\0';
167         object = forb_string_to_object(orb, str);
168         if (!object) {
169                 /* reference is unreadable, so we can replace it */
170                 ret = rewrite_regref(fd, objref);
171                 /* We are done for now */
172                 goto unlock_err;
173         }
174         if (forb_object_is_stale(object)) {
175                 /* Orb is not alive */
176                 ret = rewrite_regref(fd, objref);
177         } else {
178                 /* Reference's FORB is alive :-( */
179                 ret = 1;        
180         }
181
182         forb_object_release(object);
183 unlock_err:     
184         lockf(fd, F_ULOCK, 0);
185 close_err:
186         close(fd);
187 out:
188         return ret;
189 }
190 #endif
191
192 /** 
193  * Registers a given object reference so that other FORBs on the same
194  * node can find it by using forb_resolve_reference().
195  * 
196  * @param object Object reference to register.
197  * @param name Name under which to register the reference.
198  *
199  * @return Zero on success, -1 on error.
200  */
201 int
202 forb_register_reference(forb_object object, const char *name)
203 {
204         forb_regref_t *regref;
205         forb_regref_name_t regname;
206         forb_t *forb = forb_object_to_forb(object);
207
208         strncpy(regname.str, name, FORB_REGREF_NAME_LEN-1);
209         regname.str[FORB_REGREF_NAME_LEN-1]='\0';
210
211         regref = forb_regref_new(object, regname);
212         if (!regref) goto err;
213
214         forb_regref_insert(forb, regref);
215
216 #ifdef CONFIG_FORB_PROTO_INET_DEFAULT
217         return 0;
218 #else
219         char fn[100], fntmp[100];
220         char *objref;
221         FILE *f;
222         int ret;
223         snprintf(fn,    sizeof(fn),    FORB_TMP_DIR "/%s",    regname.str);
224         snprintf(fntmp, sizeof(fntmp), FORB_TMP_DIR "/%s.%s", regname.str,
225                  forb->server_id_str);
226
227         f = fopen(fntmp, "w");
228         if (!f) goto unalloc_err;
229         
230         objref = forb_object_to_string(object);
231         if (!objref) goto unlink_err;
232
233         ret = fprintf(f, "%s", objref);
234         if (ret < 0) goto free_objref_err;
235
236         ret = fclose(f);
237         if (ret == EOF) goto free_objref_err;
238
239         /* Make the atomic registration in filesystem */
240         ret = link(fntmp, fn);
241         
242         if (ret < 0 && errno == EEXIST) {
243                 /* The reference exists. Try whether it is still
244                  * active. */
245                 if (replace_regref_if_stale(object->orb, fn, objref) != 0) {
246                         goto free_objref_err;
247                 }
248                 ul_logdeb("Stale registration replaced\n");
249         } else if (ret < 0) {
250                 goto free_objref_err;
251         }
252
253         forb_free(objref);
254
255         /* Unlink the temporary filename */
256         unlink(fntmp);
257         
258         return 0;
259 free_objref_err:
260         ret = errno;
261         forb_free(objref);
262         errno = ret;
263 unlink_err:
264         ret = errno;
265         unlink(fntmp);
266         errno = ret;
267 unalloc_err:
268         ret = errno;
269         forb_regref_delete(forb, regref);
270         forb_regref_release(regref);
271         errno = ret;
272 #endif
273 err:
274         return -1;
275 }
276
277 /** 
278  * Unregister reference previously registered by
279  * forb_register_reference().
280  * 
281  * @param orb forb::orb reference
282  * @param name Name to unregister.
283  * 
284  * @return Zero on success, -1 on error.
285  */
286 int
287 forb_unregister_reference(forb_orb orb, const char *name)
288 {
289         forb_regref_t *regref;
290         forb_regref_name_t regname;
291         forb_t *forb = forb_object_to_forb(orb);
292
293         strncpy(regname.str, name, FORB_REGREF_NAME_LEN-1);
294         regname.str[FORB_REGREF_NAME_LEN-1]='\0';
295
296         regref = forb_regref_find(forb, &regname);
297         if (!regref) goto err;
298
299         forb_regref_delete(forb, regref);
300         forb_regref_release(regref);
301
302 #ifndef CONFIG_FORB_PROTO_INET_DEFAULT
303         char fn[100];
304         snprintf(fn,    sizeof(fn),    FORB_TMP_DIR "/%s",    regname.str);
305         return unlink(fn);
306 #endif
307
308         return 0;
309 err:
310         return -1;
311 }
312
313 /** 
314  * Returns a named reference previously registered by
315  * forb_register_reference(). This function can be called even if the
316  * reference was registered in a diferent process (but on the same
317  * node).
318  * 
319  * @param orb Local orb object reference
320  * @param name Name under which the reference was registered.
321  * 
322  * @return Object reference on NULL in case of error.
323  */
324 forb_object
325 forb_resolve_reference(const forb_orb orb, const char *name)
326 {
327         forb_regref_name_t regname;
328         forb_object object;
329
330         strncpy(regname.str, name, FORB_REGREF_NAME_LEN-1);
331         regname.str[FORB_REGREF_NAME_LEN-1]='\0';
332
333 #ifdef CONFIG_FORB_PROTO_INET_DEFAULT
334         forb_regref_t *regref;
335         forb_t *forb = forb_object_to_forb(orb);
336
337         regref = forb_regref_find(forb, &regname);
338         if (!regref) return NULL;
339
340         object = forb_object_duplicate(regref->object);
341         return object;
342
343 #else
344         char fn[100];
345         char str[100];
346         int fd, ret;
347
348         snprintf(fn,    sizeof(fn),    FORB_TMP_DIR "/%s",    regname.str);
349
350         fd = open(fn, 0);
351         if (fd < 0) {
352                 return NULL;
353         }
354         ret = read(fd, str, sizeof(str)-1);
355         /* TODO: Check that we have read the whole file */
356         str[ret] = '\0';
357         object = forb_string_to_object(orb, str);
358         close(fd);
359 #endif
360
361         if (forb_object_is_stale(object)) {
362                 forb_object_release(object);
363                 object = NULL;
364         }
365         return object;
366 }