]> rtime.felk.cvut.cz Git - frescor/forb.git/commitdiff
Added checking for stale registered references
authorMichal Sojka <sojkam1@fel.cvut.cz>
Mon, 13 Oct 2008 12:19:57 +0000 (14:19 +0200)
committerMichal Sojka <sojkam1@fel.cvut.cz>
Mon, 13 Oct 2008 12:19:57 +0000 (14:19 +0200)
If the registered reference already exists and is detected as stale, it
is replaced by the new one.

TODO
src/forb.c

diff --git a/TODO b/TODO
index 8d8a1188be39bb3932b433596a00e3b6e46758b7..bf1e9f9d958b78cb60ab2cfcb731c5ac1ebb4322 100644 (file)
--- a/TODO
+++ b/TODO
@@ -1,5 +1,3 @@
-* Check stale registered object references
-
 * Add forb_init() parameters: argc, argv and orb_id
 
 * More flexible handling of log messages (dynamic registration,
index e881e2371d001f81e79283a6a25919e4ccb190e3..94e77864fca37e09272c8b04f75330563ba6b563 100644 (file)
@@ -257,10 +257,97 @@ forb_server_id_init(forb_server_id *server_id)
        forb_uuid_generate((forb_uuid_t*)server_id->uuid);
 }
 
-void *
-forb_instance_data(const forb_object obj)
+/** 
+ * 
+ * 
+ * @param fd 
+ * @param objref 
+ * 
+ * @return Zero on success, -1 on error.
+ */
+static int
+rewrite_regref(int fd, const char *objref)
 {
-       return forb_object_instance_data(obj);
+       int ret;
+       int len = strlen(objref);
+       lseek(fd, 0, SEEK_SET);
+       ftruncate(fd, 0);
+               
+       while (len > 0) {
+               ret = write(fd, objref, len);
+               if (ret < 0) goto out;
+               len -= ret;
+               objref += ret;
+       }
+       ret = 0;        /* Success */
+out:
+       return ret;
+}
+
+/** 
+ * 
+ * 
+ * @param orb 
+ * @param fn File name
+ * @param objref string form of the object reference
+ * 
+ * @return -1 on error, 0 if reference was replaced and 1 in the
+ * reference is valid.
+ */
+static int
+replace_regref_if_stale(forb_orb orb, const char *fn, const char *objref)
+{
+       int fd, ret = 0; 
+       char str[100];
+       forb_object object;
+       forb_orb remote_orb;
+       CORBA_Environment env;
+       
+       fd = open(fn, O_RDWR);
+       if (fd < 0) {
+               ret = -1;
+               goto out;
+       }
+       ret = lockf(fd, F_LOCK, 0);
+       if (ret < 0) goto close_err;
+       ret = read(fd, str, sizeof(str)-1);
+       if (ret < 0) goto unlock_err;
+       /* TODO: Check that we have read the whole file */
+       
+       str[ret] = '\0';
+       object = forb_string_to_object(orb, str);
+       if (!object) {
+               /* reference is unreadable, so we can replace it */
+               ret = rewrite_regref(fd, objref);
+               /* We are done for now */
+               goto unlock_err;
+       }
+       remote_orb = forb_get_orb_of(object);
+       if (!remote_orb) {      /* This shohuld never happen */
+               ret = -1;
+               goto object_release_err;
+       }
+       forb_orb_is_alive(remote_orb, &env);
+       if (env.major == FORB_EX_COMM_FAILURE) {
+               /* Orb is not alive */
+               rewrite_regref(fd, objref);
+       } else {
+               if (forb_exception_occured(&env)) {
+                       ul_logerr("%s: unexpected exception: %s\n", __FUNCTION__, forb_strerror(&env));
+               }
+               /* Reference's FORB is alive :-( */
+               ret = 1;        
+       }
+
+       forb_object_release(remote_orb);
+object_release_err:
+       forb_object_release(object);
+unlock_err:    
+       lockf(fd, F_ULOCK, 0);
+close_err:
+       close(fd);
+out:
+       return ret;
 }
 
 
@@ -300,27 +387,38 @@ forb_register_reference(forb_object object, const char *name)
        if (!f) goto unalloc_err;
        
        objref = forb_object_to_string(object);
-       if (!objref) goto unalloc_err;
+       if (!objref) goto unlink_err;
 
        ret = fprintf(f, "%s", objref);
-       forb_free(objref);
-       if (ret < 0) goto unalloc_err;
+       if (ret < 0) goto free_objref_err;
 
        ret = fclose(f);
-       if (ret == EOF) goto unalloc_err;
+       if (ret == EOF) goto free_objref_err;
 
        /* Make the atomic registration in filesystem */
        ret = link(fntmp, fn);
-       if (ret < 0) {
-               /* TODO: If the reference exists, try whether it is
-                * still active. */
-               goto unlink_err;
+       
+       if (ret < 0 && errno == EEXIST) {
+               /* The reference exists. Try whether it is still
+                * active. */
+               if (replace_regref_if_stale(object->orb, fn, objref) != 0) {
+                       goto free_objref_err;
+               }
+               ul_logdeb("Stale registration replaced\n");
+       } else if (ret < 0) {
+               goto free_objref_err;
        }
 
+       forb_free(objref);
+
        /* Unlink the temporary filename */
        unlink(fntmp);
        
        return 0;
+free_objref_err:
+       ret = errno;
+       forb_free(objref);
+       errno = ret;
 unlink_err:
        ret = errno;
        unlink(fntmp);
@@ -334,6 +432,15 @@ err:
        return -1;
 }
 
+/** 
+ * Unregister reference previously registered by
+ * forb_register_reference().
+ * 
+ * @param orb forb::orb reference
+ * @param name Name to unregister.
+ * 
+ * @return Zero on success, -1 on error.
+ */
 int
 forb_unregister_reference(forb_orb orb, const char *name)
 {
@@ -376,7 +483,7 @@ forb_resolve_reference(const forb_orb orb, const char *name)
        forb_regref_name_t regname;
        char fn[100];
        char str[100];
-       int fd;
+       int fd, ret;
        forb_object object;
 
        strncpy(regname, name, FORB_REGREF_NAME_LEN-1);
@@ -388,8 +495,9 @@ forb_resolve_reference(const forb_orb orb, const char *name)
        if (fd < 0) {
                return NULL;
        }
-       read(fd, str, sizeof(str)-1);
-       str[sizeof(str)-1] = '\0';
+       ret = read(fd, str, sizeof(str)-1);
+       /* TODO: Check that we have read the whole file */
+       str[ret] = '\0';
        object = forb_string_to_object(orb, str);
        close(fd);