/* 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; }
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 (¤t, 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; }
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); }
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; }
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 (®->lock); { event = reg->active.next; at = TS (event->at); if (event != ®->active && now >= at) { need_cbk = 1; gf_timer_call_stale (reg, event); } } pthread_mutex_unlock (®->lock); if (event->xl) THIS = event->xl; if (need_cbk) event->callbk (event->data); else break; } usleep (1000000); } pthread_mutex_lock (®->lock); { while (reg->active.next != ®->active) { gf_timer_call_cancel (ctx, reg->active.next); } while (reg->stale.next != ®->stale) { gf_timer_call_cancel (ctx, reg->stale.next); } } pthread_mutex_unlock (®->lock); pthread_mutex_destroy (®->lock); GF_FREE (((glusterfs_ctx_t *)ctx)->timer); return NULL; }
//计时器线程 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 (®->lock); { event = reg->active.next; at = TS (event->at); if (event != ®->active && now >= at) { need_cbk = 1; gf_timer_call_stale (reg, event); } } pthread_mutex_unlock (®->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 (®->lock); { while (reg->active.next != ®->active) { gf_timer_call_cancel (ctx, reg->active.next); } while (reg->stale.next != ®->stale) { gf_timer_call_cancel (ctx, reg->stale.next); } } pthread_mutex_unlock (®->lock); pthread_mutex_destroy (®->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 (®->lock, NULL); reg->active.next = ®->active; reg->active.prev = ®->active; reg->stale.next = ®->stale; reg->stale.prev = ®->stale; ctx->timer = reg; gf_thread_create (®->th, NULL, gf_timer_proc, ctx); } out: return ctx->timer; }