예제 #1
0
/* Must be called under conn->lock */
int
rpc_clnt_remove_ping_timer_locked (struct rpc_clnt *rpc)
{
        rpc_clnt_connection_t *conn  = &rpc->conn;
        gf_timer_t            *timer = NULL;

        if (conn->ping_timer) {
                timer = conn->ping_timer;
                conn->ping_timer = NULL;
                gf_timer_call_cancel (rpc->ctx, timer);
                conn->ping_started = 0;
                return 1;

        }

        /* This is to account for rpc_clnt_disable that might have set
         *  conn->trans to NULL. */
        if (conn->trans)
                gf_log_callingfn ("", GF_LOG_DEBUG, "%s: ping timer event "
                                  "already removed",
                                   conn->trans->peerinfo.identifier);

        return 0;
}
예제 #2
0
void
rpc_clnt_ping_timer_expired (void *rpc_ptr)
{
        struct rpc_clnt         *rpc                = NULL;
        rpc_transport_t         *trans              = NULL;
        rpc_clnt_connection_t   *conn               = NULL;
        int                      disconnect         = 0;
        int                      transport_activity = 0;
        struct timespec          timeout            = {0, };
        struct timeval           current            = {0, };

        rpc = (struct rpc_clnt*) rpc_ptr;
        conn = &rpc->conn;
        trans = conn->trans;

        if (!trans) {
                gf_log ("ping-timer", GF_LOG_WARNING,
                        "transport not initialized");
                goto out;
        }

        pthread_mutex_lock (&conn->lock);
        {
                if (conn->ping_timer) {
                        gf_timer_call_cancel (rpc->ctx,
                                              conn->ping_timer);
                        conn->ping_timer = NULL;
                        rpc_clnt_unref (rpc);
                }

                gettimeofday (&current, NULL);
                if (((current.tv_sec - conn->last_received.tv_sec) <
                     conn->ping_timeout)
                    || ((current.tv_sec - conn->last_sent.tv_sec) <
                        conn->ping_timeout)) {
                        transport_activity = 1;
                }

                if (transport_activity) {
                        gf_log (trans->name, GF_LOG_TRACE,
                                "ping timer expired but transport activity "
                                "detected - not bailing transport");
                        timeout.tv_sec = conn->ping_timeout;
                        timeout.tv_nsec = 0;

                        rpc_clnt_ref (rpc);
                        conn->ping_timer =
                                gf_timer_call_after (rpc->ctx, timeout,
                                                     rpc_clnt_ping_timer_expired,
                                                     (void *) rpc);
                        if (conn->ping_timer == NULL) {
                                gf_log (trans->name, GF_LOG_WARNING,
                                        "unable to setup ping timer");
                                conn->ping_started = 0;
                                rpc_clnt_unref (rpc);
                        }
                } else {
                        conn->ping_started = 0;
                        disconnect = 1;
                }
        }
        pthread_mutex_unlock (&conn->lock);

        if (disconnect) {
                gf_log (trans->name, GF_LOG_CRITICAL,
                        "server %s has not responded in the last %d "
                        "seconds, disconnecting.",
                        trans->peerinfo.identifier,
                        conn->ping_timeout);

                rpc_transport_disconnect (conn->trans);
        }

out:
        return;
}
예제 #3
0
static void
rpc_clnt_start_ping (void *rpc_ptr)
{
        struct rpc_clnt         *rpc         = NULL;
        rpc_clnt_connection_t   *conn        = NULL;
        struct timespec          timeout     = {0, };
        int                      frame_count = 0;

        rpc = (struct rpc_clnt*) rpc_ptr;
        conn = &rpc->conn;

        if (conn->ping_timeout == 0) {
                gf_log (THIS->name, GF_LOG_DEBUG, "ping timeout is 0,"
                        " returning");
                return;
        }

        pthread_mutex_lock (&conn->lock);
        {
                if (conn->ping_timer) {
                        gf_timer_call_cancel (rpc->ctx, conn->ping_timer);
                        conn->ping_timer = NULL;
                        conn->ping_started = 0;
                        rpc_clnt_unref (rpc);
                }

                if (conn->saved_frames) {
                        GF_ASSERT (conn->saved_frames->count >= 0);
                        /* treat the case where conn->saved_frames is NULL
                           as no pending frames */
                        frame_count = conn->saved_frames->count;
                }

                if ((frame_count == 0) || !conn->connected) {
                        gf_log (THIS->name, GF_LOG_DEBUG,
                                "returning as transport is already disconnected"
                                " OR there are no frames (%d || %d)",
                                !conn->connected, frame_count);

                        pthread_mutex_unlock (&conn->lock);
                        return;
                }

                timeout.tv_sec = conn->ping_timeout;
                timeout.tv_nsec = 0;

                rpc_clnt_ref (rpc);
                conn->ping_timer =
                        gf_timer_call_after (rpc->ctx, timeout,
                                             rpc_clnt_ping_timer_expired,
                                             (void *) rpc);

                if (conn->ping_timer == NULL) {
                        gf_log (THIS->name, GF_LOG_WARNING,
                                "unable to setup ping timer");
                        rpc_clnt_unref (rpc);
                        pthread_mutex_unlock (&conn->lock);
                        return;
                } else {
                        conn->ping_started = 1;
                }
        }
        pthread_mutex_unlock (&conn->lock);

        rpc_clnt_ping(rpc);
}
예제 #4
0
int
rpc_clnt_ping_cbk (struct rpc_req *req, struct iovec *iov, int count,
                   void *myframe)
{
        struct rpc_clnt       *rpc     = NULL;
        xlator_t              *this    = NULL;
        rpc_clnt_connection_t *conn    = NULL;
        call_frame_t          *frame   = NULL;
        struct timespec       timeout  = {0, };

        if (!myframe) {
                gf_log (THIS->name, GF_LOG_WARNING,
                        "frame with the request is NULL");
                goto out;
        }

        frame = myframe;
        this = frame->this;
        rpc  = frame->local;
        frame->local = NULL; /* Prevent STACK_DESTROY from segfaulting */
        conn = &rpc->conn;

        pthread_mutex_lock (&conn->lock);
        {
                if (req->rpc_status == -1) {
                        if (conn->ping_timer != NULL) {
                                gf_log (this->name, GF_LOG_WARNING,
                                        "socket or ib related error");
                                gf_timer_call_cancel (rpc->ctx,
                                                      conn->ping_timer);
                                conn->ping_timer = NULL;
                                rpc_clnt_unref (rpc);

                        } else {
                                /* timer expired and transport bailed out */
                                gf_log (this->name, GF_LOG_WARNING,
                                        "socket disconnected");

                        }
                        conn->ping_started = 0;
                        goto unlock;
                }

                gf_timer_call_cancel (this->ctx,
                                      conn->ping_timer);

                timeout.tv_sec = conn->ping_timeout;
                timeout.tv_nsec = 0;
                rpc_clnt_ref (rpc);
                conn->ping_timer = gf_timer_call_after (this->ctx, timeout,
                                                        rpc_clnt_start_ping,
                                                        (void *)rpc);

                if (conn->ping_timer == NULL) {
                        gf_log (this->name, GF_LOG_WARNING,
                                "failed to set the ping timer");
                        conn->ping_started = 0;
                        rpc_clnt_unref (rpc);
                }

        }
unlock:
        pthread_mutex_unlock (&conn->lock);
out:
        if (frame)
                STACK_DESTROY (frame->root);
        return 0;
}
예제 #5
0
파일: timer.c 프로젝트: lkundrak/glusterfs
void *
gf_timer_proc (void *ctx)
{
        gf_timer_registry_t *reg = NULL;

        if (ctx == NULL)
        {
                gf_log_callingfn ("timer", GF_LOG_ERROR, "invalid argument");
                return NULL;
        }

        reg = gf_timer_registry_init (ctx);
        if (!reg) {
                gf_log ("timer", GF_LOG_ERROR, "!reg");
                return NULL;
        }

        while (!reg->fin) {
                unsigned long long now;
                struct timeval now_tv;
                gf_timer_t *event = NULL;

                gettimeofday (&now_tv, NULL);
                now = TS (now_tv);
                while (1) {
                        unsigned long long at;
                        char need_cbk = 0;

                        pthread_mutex_lock (&reg->lock);
                        {
                                event = reg->active.next;
                                at = TS (event->at);
                                if (event != &reg->active && now >= at) {
                                        need_cbk = 1;
                                        gf_timer_call_stale (reg, event);
                                }
                        }
                        pthread_mutex_unlock (&reg->lock);
                        if (event->xl)
                                THIS = event->xl;
                        if (need_cbk)
                                event->callbk  (event->data);

                        else
                                break;
                }
                usleep (1000000);
        }

        pthread_mutex_lock (&reg->lock);
        {
                while (reg->active.next != &reg->active) {
                        gf_timer_call_cancel (ctx, reg->active.next);
                }

                while (reg->stale.next != &reg->stale) {
                        gf_timer_call_cancel (ctx, reg->stale.next);
                }
        }
        pthread_mutex_unlock (&reg->lock);
        pthread_mutex_destroy (&reg->lock);
        GF_FREE (((glusterfs_ctx_t *)ctx)->timer);

        return NULL;
}
예제 #6
0
//计时器线程
void *
gf_timer_proc (void *ctx)
{
        gf_timer_registry_t *reg = NULL;
        const struct timespec sleepts = {.tv_sec = 1, .tv_nsec = 0, };

        if (ctx == NULL)
        {
                gf_log_callingfn ("timer", GF_LOG_ERROR, "invalid argument");
                return NULL;
        }

        reg = gf_timer_registry_init (ctx);
        if (!reg) {
                gf_log ("timer", GF_LOG_ERROR, "!reg");
                return NULL;
        }

        while (!reg->fin) {
                uint64_t now;
                struct timespec now_ts;
                gf_timer_t *event = NULL;

                timespec_now (&now_ts);
                //现在的时间
                now = TS (now_ts);
                while (1) {
                        uint64_t at;
                        char need_cbk = 0;

                        pthread_mutex_lock (&reg->lock);
                        {
                                event = reg->active.next;
                                at = TS (event->at);
                                if (event != &reg->active && now >= at) {
                                        need_cbk = 1;
                                        gf_timer_call_stale (reg, event);
                                }
                        }
                        pthread_mutex_unlock (&reg->lock);
                        if (event->xl)
                                THIS = event->xl;
                        if (need_cbk)
                                event->callbk  (event->data);

                        else
                            //跳出while(1)
                                break;
                }
                // 睡1秒
                nanosleep (&sleepts, NULL);
        }

        pthread_mutex_lock (&reg->lock);
        {
                while (reg->active.next != &reg->active) {
                        gf_timer_call_cancel (ctx, reg->active.next);
                }

                while (reg->stale.next != &reg->stale) {
                        gf_timer_call_cancel (ctx, reg->stale.next);
                }
        }
        pthread_mutex_unlock (&reg->lock);
        pthread_mutex_destroy (&reg->lock);
        GF_FREE (((glusterfs_ctx_t *)ctx)->timer);

        return NULL;
}

// 计时器注册初始化
gf_timer_registry_t *
gf_timer_registry_init (glusterfs_ctx_t *ctx)
{
        if (ctx == NULL) {
                gf_log_callingfn ("timer", GF_LOG_ERROR, "invalid argument");
                return NULL;
        }
        // 还没初始化过的
        if (!ctx->timer) {
                gf_timer_registry_t *reg = NULL;

                reg = GF_CALLOC (1, sizeof (*reg),
                                 gf_common_mt_gf_timer_registry_t);
                if (!reg)
                        goto out;

                pthread_mutex_init (&reg->lock, NULL);
                reg->active.next = &reg->active;
                reg->active.prev = &reg->active;
                reg->stale.next = &reg->stale;
                reg->stale.prev = &reg->stale;

                ctx->timer = reg;
                gf_thread_create (&reg->th, NULL, gf_timer_proc, ctx);
        }
out:
        return ctx->timer;
}