From 3cc1dfa6d4dd36d35b059b9f5e7d33eb45d6450e Mon Sep 17 00:00:00 2001 From: Michal Sojka Date: Mon, 13 Oct 2008 14:19:57 +0200 Subject: [PATCH] Added checking for stale registered references If the registered reference already exists and is detected as stale, it is replaced by the new one. --- TODO | 2 - src/forb.c | 136 +++++++++++++++++++++++++++++++++++++++++++++++------ 2 files changed, 122 insertions(+), 16 deletions(-) diff --git a/TODO b/TODO index 8d8a118..bf1e9f9 100644 --- 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, diff --git a/src/forb.c b/src/forb.c index e881e23..94e7786 100644 --- a/src/forb.c +++ b/src/forb.c @@ -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); -- 2.39.2