Beispiel #1
0
int flom_handle_clean(flom_handle_t *handle)
{
    enum Exception { FLOM_HANDLE_UNLOCK_ERROR
                     , API_INVALID_SEQUENCE
                     , NONE } excp;
    int ret_cod = FLOM_RC_INTERNAL_ERROR;
    
    /* check flom library is initialized */
    if (FLOM_RC_OK != (ret_cod = flom_init_check()))
        return ret_cod;
    
    FLOM_TRACE(("flom_handle_clean\n"));
    TRY {
        /* is the handle locked? we must unlock it before going on... */
        if (FLOM_HANDLE_STATE_LOCKED == handle->state) {
            if (FLOM_RC_OK != (ret_cod = flom_handle_unlock(handle)))
                THROW(FLOM_HANDLE_UNLOCK_ERROR);
        }
        /* check handle state */
        if (FLOM_HANDLE_STATE_INIT != handle->state &&
            FLOM_HANDLE_STATE_DISCONNECTED != handle->state) {
            FLOM_TRACE(("flom_handle_clean: handle->state=%d\n",
                        handle->state));
            THROW(API_INVALID_SEQUENCE);
        }
        /* release memory allocated for configuration object */
        flom_config_free(handle->config);
        g_free(handle->config);
        handle->config = NULL;
        /* release memory of connection data structure */
        g_free(handle->conn);
        handle->conn = NULL;
        /* release memory of locked element */
        g_free(handle->locked_element);
        handle->locked_element = NULL;
        /* clean handle state */
        handle->state = FLOM_HANDLE_STATE_CLEANED;
        
        THROW(NONE);
    } CATCH {
        switch (excp) {
            case FLOM_HANDLE_UNLOCK_ERROR:
                break;
            case API_INVALID_SEQUENCE:
                ret_cod = FLOM_RC_API_INVALID_SEQUENCE;
                break;
            case NONE:
                ret_cod = FLOM_RC_OK;
                break;
            default:
                ret_cod = FLOM_RC_INTERNAL_ERROR;
        } /* switch (excp) */
    } /* TRY-CATCH */
    FLOM_TRACE(("flom_handle_clean/excp=%d/"
                "ret_cod=%d/errno=%d\n", excp, ret_cod, errno));
    return ret_cod;
}
Beispiel #2
0
int flom_handle_init(flom_handle_t *handle)
{
    enum Exception { G_TRY_MALLOC_ERROR1
                     , G_TRY_MALLOC_ERROR2
                     , CONFIG_INIT_ERROR
                     , NONE } excp;
    int ret_cod = FLOM_RC_INTERNAL_ERROR;
    
    /* check flom library is initialized */
    if (FLOM_RC_OK != (ret_cod = flom_init_check()))
        return ret_cod;
    
    FLOM_TRACE(("flom_handle_init\n"));
    TRY {
        /* memory reset */
        memset(handle, 0, sizeof(flom_handle_t));
        /* allocate memory for connection data structure */
        if (NULL == (handle->conn = g_try_malloc0(
                         sizeof(flom_conn_t))))
            THROW(G_TRY_MALLOC_ERROR1);
        /* allocate memory for configuration data structure */
        if (NULL == (handle->config = g_try_malloc0(
                         sizeof(flom_config_t))))
            THROW(G_TRY_MALLOC_ERROR2);
        /* initialize config object */
        if (FLOM_RC_OK != (ret_cod = flom_config_clone(handle->config)))
            THROW(CONFIG_INIT_ERROR);
        /* clients can not fork a new flom daemon: this restriction is
         * necessary to avoid the side effects related to daemonization that
         * can affect a general purpose environment... This is a CLIENT!!! */
        flom_config_set_lifespan(handle->config, 0);
        /* state reset */
        handle->state = FLOM_HANDLE_STATE_INIT;
        
        THROW(NONE);
    } CATCH {
        switch (excp) {
            case G_TRY_MALLOC_ERROR1:
            case G_TRY_MALLOC_ERROR2:
                ret_cod = FLOM_RC_G_TRY_MALLOC_ERROR;
                break;
            case CONFIG_INIT_ERROR:
                break;
            case NONE:
                ret_cod = FLOM_RC_OK;
                break;
            default:
                ret_cod = FLOM_RC_INTERNAL_ERROR;
        } /* switch (excp) */
    } /* TRY-CATCH */
    /* clean memory if an error occurred */
    if (NONE != excp) {
        if (NULL != handle->config) {
            flom_config_free(handle->config);
            g_free(handle->config);
            handle->config = NULL;
        } /* if (NULL != handle->config) */
        if (NULL != handle->conn) {
            g_free(handle->conn);
            handle->conn = NULL;
        } /* if (NULL != handle->conn) */
    } /* if (NONE != excp) */
    FLOM_TRACE(("flom_handle_init/excp=%d/"
                "ret_cod=%d/errno=%d\n", excp, ret_cod, errno));
    return ret_cod;
}
Beispiel #3
0
int main (int argc, char *argv[])
{
    GError *error = NULL;
    GOptionContext *option_context;
    int child_status = 0;
    int ret_cod = FLOM_RC_INTERNAL_ERROR;
    struct flom_conn_data_s cd;
    char locked_element[100];

    option_context = g_option_context_new("[-- command to execute]");
    g_option_context_add_main_entries(option_context, entries, NULL);
    if (!g_option_context_parse(option_context, &argc, &argv, &error)) {
        g_print("option parsing failed: %s\n", error->message);
        exit(FLOM_ES_GENERIC_ERROR);
    }
    g_option_context_free(option_context);

    if (print_version) {
        g_print("FLoM: Free LOck Manager\n"
                "Copyright (c) 2013-2014, Christian Ferrari; "
                "all rights reserved.\n"
                "License: GPL (GNU Public License) version 2\n"
                "Package name: %s; package version: %s; release date: %s\n"
                "Access http://sourceforge.net/projects/flom/ for "
                "project community activities\n",
                FLOM_PACKAGE_NAME, FLOM_PACKAGE_VERSION, FLOM_PACKAGE_DATE);
        exit(FLOM_ES_OK);
    }

    /* initialize trace destination if necessary */
    FLOM_TRACE_INIT;
    
    /* initialize regular expression table */
    if (FLOM_RC_OK != (ret_cod = global_res_name_preg_init())) {
        g_print("global_res_name_preg_init: ret_cod=%d\n", ret_cod);
        exit(FLOM_ES_GENERIC_ERROR);
    }

    /* reset global configuration */
    flom_config_reset(NULL);
    /* initialize configuration with standard system, standard user and
       user customized config files */
    if (FLOM_RC_OK != (ret_cod = flom_config_init(NULL, config_file))) {
        g_print("flom_config_init: ret_cod=%d\n", ret_cod);
        exit(FLOM_ES_GENERIC_ERROR);
    }
    /* overrides configuration with command line passed arguments */
    if (NULL != daemon_trace_file)
        flom_config_set_daemon_trace_file(NULL, daemon_trace_file);
    if (NULL != command_trace_file)
        flom_config_set_command_trace_file(NULL, command_trace_file);
    if (verbose)
        flom_config_set_verbose(NULL, verbose);
    if (NULL != resource_name)
        if (FLOM_RC_OK != (ret_cod = flom_config_set_resource_name(
                               NULL, resource_name))) {
            g_print("flom_config_set_resource_name: ret_cod=%d\n", ret_cod);
            exit(FLOM_ES_GENERIC_ERROR);
        }
    if (0 > resource_quantity)
        g_warning("Resource quantity ignored because negative values (%d) "
                  "are meaningless\n", resource_quantity);
    else if (0 < resource_quantity)
        flom_config_set_resource_quantity(NULL, resource_quantity);

    if (NULL != resource_wait) {
        flom_bool_value_t fbv;
        if (FLOM_BOOL_INVALID == (
                fbv = flom_bool_value_retrieve(resource_wait))) {
            g_print("resource-wait: '%s' is an invalid value\n",
                    resource_wait);
            exit(FLOM_ES_GENERIC_ERROR);
        }
        flom_config_set_resource_wait(NULL, fbv);
    }
    if (FLOM_NETWORK_WAIT_TIMEOUT != resource_timeout) {
        /* timeout is useless if no wait was specified */
        if (FLOM_BOOL_NO == flom_config_get_resource_wait(NULL))
            g_warning("Timeout ignored because 'no wait' behavior was "
                      "specified\n");
        else
            flom_config_set_resource_timeout(NULL, resource_timeout);
    }
    if (NULL != lock_mode) {
        flom_lock_mode_t flm;
        if (FLOM_LOCK_MODE_INVALID == (
                flm = flom_lock_mode_retrieve(lock_mode))) {
            g_print("lock-mode: '%s' is an invalid value\n", lock_mode);
            exit(FLOM_ES_GENERIC_ERROR);
        }
        flom_config_set_lock_mode(NULL, flm);
    }
    if (NULL != resource_create) {
        flom_bool_value_t fbv;
        if (FLOM_BOOL_INVALID == (
                fbv = flom_bool_value_retrieve(resource_create))) {
            g_print("resource-create: '%s' is an invalid value\n",
                    resource_create);
            exit(FLOM_ES_GENERIC_ERROR);
        }
        flom_config_set_resource_create(NULL, fbv);
    }
    flom_config_set_resource_idle_lifespan(NULL, resource_idle_lifespan);
    if (NULL != socket_name) {
        if (FLOM_RC_OK != (ret_cod = flom_config_set_socket_name(
                               NULL, socket_name))) {
            g_print("socket-name: '%s' is an invalid value\n", socket_name);
            g_print("flom_client_connect: ret_cod=%d (%s)\n",
                    ret_cod, flom_strerror(ret_cod));
            exit(FLOM_ES_GENERIC_ERROR);
        }
    }
    if (_DEFAULT_DAEMON_LIFESPAN != daemon_lifespan) {
        flom_config_set_lifespan(NULL, daemon_lifespan);
    }
    if (NULL != unicast_address) {
        flom_config_set_unicast_address(NULL, unicast_address);
    }
    if (_DEFAULT_DAEMON_PORT != unicast_port) {
        flom_config_set_unicast_port(NULL, unicast_port);
    }
    if (NULL != multicast_address) {
        flom_config_set_multicast_address(NULL, multicast_address);
    }
    if (_DEFAULT_DAEMON_PORT != multicast_port) {
        flom_config_set_multicast_port(NULL, multicast_port);
    }
    if (_DEFAULT_DISCOVERY_ATTEMPTS != discovery_attempts) {
        flom_config_set_discovery_attempts(NULL, discovery_attempts);
    }
    if (_DEFAULT_DISCOVERY_TIMEOUT != discovery_timeout) {
        flom_config_set_discovery_timeout(NULL, discovery_timeout);
    }
    if (_DEFAULT_DISCOVERY_TTL != discovery_ttl) {
        flom_config_set_discovery_ttl(NULL, discovery_ttl);
    }
    if (_DEFAULT_TCP_KEEPALIVE_TIME != tcp_keepalive_time) {
        flom_config_set_tcp_keepalive_time(NULL, tcp_keepalive_time);
    }
    if (_DEFAULT_TCP_KEEPALIVE_INTVL != tcp_keepalive_intvl) {
        flom_config_set_tcp_keepalive_intvl(NULL, tcp_keepalive_intvl);
    }
    if (_DEFAULT_TCP_KEEPALIVE_PROBES != tcp_keepalive_probes) {
        flom_config_set_tcp_keepalive_probes(NULL, tcp_keepalive_probes);
    }
    if (NULL != flom_config_get_command_trace_file(NULL))
        /* change trace destination if necessary */
        FLOM_TRACE_REOPEN(flom_config_get_command_trace_file(NULL));

    /* print configuration */
    if (flom_config_get_verbose(NULL))
        flom_config_print(NULL);

    /* check configuration */
    if (FLOM_RC_OK != (ret_cod = flom_config_check(NULL))) {
        g_warning("Configuration is not valid, cannot go on!\n");
        exit(FLOM_ES_GENERIC_ERROR);        
    }

    /* check if the command is asking daemon termination */
    if (quiesce_exit || immediate_exit) {
        g_print("Starting FLoM daemon %s shutdown...\n",
                immediate_exit ? "immediate" : "quiesce");
        flom_client_shutdown(NULL, immediate_exit);
        exit(0);
    }
    
    /* check the command is not null */
    if (NULL == command_argv) {
        g_warning("No command to execute!\n");
        exit(FLOM_ES_UNABLE_TO_EXECUTE_COMMAND);        
    }

    /* open connection to a valid flom lock manager... */
    if (FLOM_RC_OK != (ret_cod = flom_client_connect(NULL, &cd, TRUE))) {
        g_print("flom_client_connect: ret_cod=%d (%s)\n",
                ret_cod, flom_strerror(ret_cod));
        exit(FLOM_ES_GENERIC_ERROR);
    }

    /* sending lock command */
    ret_cod = flom_client_lock(NULL, &cd,
                               flom_config_get_resource_timeout(NULL),
                               locked_element, sizeof(locked_element));
    switch (ret_cod) {
        case FLOM_RC_OK: /* OK, go on */
            if (flom_config_get_verbose(NULL) && '\0' != locked_element[0])
                g_print("Locked element is '%s'\n", locked_element);
            break;
        case FLOM_RC_LOCK_BUSY: /* busy */
            g_print("Resource already locked, the lock cannot be obtained\n");
            /* gracefully disconnect from daemon */
            if (FLOM_RC_OK != (ret_cod = flom_client_disconnect(&cd))) {
                g_print("flom_client_unlock: ret_cod=%d (%s)\n",
                        ret_cod, flom_strerror(ret_cod));
            }
            exit(FLOM_ES_RESOURCE_BUSY);
            break;
        case FLOM_RC_LOCK_CANT_WAIT: /* can't wait, leaving... */
            g_print("The resource could be available in the future, but the "
                    "requester can't wait\n");
            /* gracefully disconnect from daemon */
            if (FLOM_RC_OK != (ret_cod = flom_client_disconnect(&cd))) {
                g_print("flom_client_unlock: ret_cod=%d (%s)\n",
                        ret_cod, flom_strerror(ret_cod));
            }
            exit(FLOM_ES_REQUESTER_CANT_WAIT);
            break;
        case FLOM_RC_LOCK_IMPOSSIBLE: /* impossible */
            g_print("Resource will never satisfy the request, the lock "
                    "cannot be obtained\n");
            /* gracefully disconnect from daemon */
            if (FLOM_RC_OK != (ret_cod = flom_client_disconnect(&cd))) {
                g_print("flom_client_unlock: ret_cod=%d (%s)\n",
                        ret_cod, flom_strerror(ret_cod));
            }
            exit(FLOM_ES_GENERIC_ERROR);
            break;
        case FLOM_RC_NETWORK_TIMEOUT: /* timeout expired, busy resource */
            g_print("The lock was not obtained because timeout "
                    "(%d milliseconds) expired\n",
                    flom_config_get_resource_timeout(NULL));
            /* gracefully disconnect from daemon */
            if (FLOM_RC_OK != (ret_cod = flom_client_disconnect(&cd))) {
                g_print("flom_client_unlock: ret_cod=%d (%s)\n",
                        ret_cod, flom_strerror(ret_cod));
            }
            exit(FLOM_ES_RESOURCE_BUSY);
            break;            
        default:
            g_print("flom_client_lock: ret_cod=%d (%s)\n",
                    ret_cod, flom_strerror(ret_cod));
            exit(FLOM_ES_GENERIC_ERROR);
    } /* switch (ret_cod) */

    /* execute the command */
    if (FLOM_RC_OK != (ret_cod = flom_exec(command_argv, locked_element,
                                           &child_status))) {
        guint i, num;
        g_print("Unable to execute command: '");
        num = g_strv_length(command_argv);
        for (i=0; i<num; ++i)
            g_print("%s", command_argv[i]);
        g_print("'\n");
        exit(FLOM_ES_UNABLE_TO_EXECUTE_COMMAND);
    }
    
    /* sending unlock command */
    if (FLOM_RC_OK != (ret_cod = flom_client_unlock(NULL, &cd))) {
        g_print("flom_client_unlock: ret_cod=%d (%s)\n",
                ret_cod, flom_strerror(ret_cod));
        exit(FLOM_ES_GENERIC_ERROR);
    }

    /* gracefully disconnect from daemon */
    if (FLOM_RC_OK != (ret_cod = flom_client_disconnect(&cd))) {
        g_print("flom_client_unlock: ret_cod=%d (%s)\n",
                ret_cod, flom_strerror(ret_cod));
    }

    g_strfreev (command_argv);
    command_argv = NULL;

    /* release config data */
    flom_config_free(NULL);
    /* release regular expression data */
    global_res_name_preg_free();
    
	return child_status;
}