int32_t gf_timer_call_cancel (glusterfs_ctx_t *ctx, gf_timer_t *event) { gf_timer_registry_t *reg = NULL; if (ctx == NULL || event == NULL) { gf_log_callingfn ("timer", GF_LOG_ERROR, "invalid argument"); return 0; } reg = gf_timer_registry_init (ctx); if (!reg) { gf_log ("timer", GF_LOG_ERROR, "!reg"); GF_FREE (event); return 0; } pthread_mutex_lock (®->lock); { event->next->prev = event->prev; event->prev->next = event->next; } pthread_mutex_unlock (®->lock); GF_FREE (event); return 0; }
int32_t gf_timer_call_cancel (glusterfs_ctx_t *ctx, gf_timer_t *event) { if (!ctx || !event) { gf_log ("timer", GF_LOG_ERROR, "!ctx || !event"); return 0; } gf_timer_registry_t *reg = gf_timer_registry_init (ctx); if (!reg) { gf_log ("timer", GF_LOG_ERROR, "!reg"); return 0; } pthread_mutex_lock (®->lock); { event->next->prev = event->prev; event->prev->next = event->next; } pthread_mutex_unlock (®->lock); freee (event); return 0; }
gf_timer_t * gf_timer_call_after (glusterfs_ctx_t *ctx, struct timeval delta, gf_timer_cbk_t callbk, void *data) { gf_timer_registry_t *reg = NULL; gf_timer_t *event = NULL; gf_timer_t *trav = NULL; unsigned long long at = 0L; if (ctx == NULL) { gf_log_callingfn ("timer", GF_LOG_ERROR, "invalid argument"); return NULL; } reg = gf_timer_registry_init (ctx); if (!reg) { gf_log_callingfn ("timer", GF_LOG_ERROR, "!reg"); return NULL; } event = GF_CALLOC (1, sizeof (*event), gf_common_mt_gf_timer_t); if (!event) { return NULL; } gettimeofday (&event->at, NULL); event->at.tv_usec = ((event->at.tv_usec + delta.tv_usec) % 1000000); event->at.tv_sec += ((event->at.tv_usec + delta.tv_usec) / 1000000); event->at.tv_sec += delta.tv_sec; at = TS (event->at); event->callbk = callbk; event->data = data; event->xl = THIS; pthread_mutex_lock (®->lock); { trav = reg->active.prev; while (trav != ®->active) { if (TS (trav->at) < at) break; trav = trav->prev; } event->prev = trav; event->next = event->prev->next; event->prev->next = event; event->next->prev = event; } pthread_mutex_unlock (®->lock); return event; }
gf_timer_t * gf_timer_call_after (glusterfs_ctx_t *ctx, struct timespec delta, gf_timer_cbk_t callbk, void *data) { gf_timer_registry_t *reg = NULL; gf_timer_t *event = NULL; gf_timer_t *trav = NULL; uint64_t at = 0; if (ctx == NULL) { gf_msg_callingfn ("timer", GF_LOG_ERROR, EINVAL, LG_MSG_INVALID_ARG, "invalid argument"); return NULL; } reg = gf_timer_registry_init (ctx); if (!reg) { gf_msg_callingfn ("timer", GF_LOG_ERROR, 0, LG_MSG_TIMER_REGISTER_ERROR, "!reg"); return NULL; } event = GF_CALLOC (1, sizeof (*event), gf_common_mt_gf_timer_t); if (!event) { return NULL; } timespec_now (&event->at); timespec_adjust_delta (&event->at, delta); at = TS (event->at); event->callbk = callbk; event->data = data; event->xl = THIS; LOCK (®->lock); { trav = reg->active.prev; while (trav != ®->active) { if (TS (trav->at) < at) break; trav = trav->prev; } event->prev = trav; event->next = event->prev->next; event->prev->next = event; event->next->prev = event; } UNLOCK (®->lock); return event; }
// 插入一个事件到定时器链表中 gf_timer_t * gf_timer_call_after (glusterfs_ctx_t *ctx, struct timespec delta, gf_timer_cbk_t callbk, void *data) { gf_timer_registry_t *reg = NULL; gf_timer_t *event = NULL; gf_timer_t *trav = NULL; uint64_t at = 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_callingfn ("timer", GF_LOG_ERROR, "!reg"); return NULL; } event = GF_CALLOC (1, sizeof (*event), gf_common_mt_gf_timer_t); if (!event) { return NULL; } timespec_now (&event->at); timespec_adjust_delta (&event->at, delta); at = TS (event->at); event->callbk = callbk; event->data = data; event->xl = THIS; pthread_mutex_lock (®->lock); { //列表最后一个 trav = reg->active.prev; //找最后一个时间比我早的(链表是按时间排序的) while (trav != ®->active) { if (TS (trav->at) < at) break; trav = trav->prev; } event->prev = trav; event->next = event->prev->next; event->prev->next = event; event->next->prev = event; } pthread_mutex_unlock (®->lock); return event; }
gf_timer_t * gf_timer_call_after (glusterfs_ctx_t *ctx, struct timeval delta, gf_timer_cbk_t cbk, void *data) { if (!ctx) { gf_log ("timer", GF_LOG_ERROR, "!ctx"); return NULL; } gf_timer_registry_t *reg = gf_timer_registry_init (ctx); gf_timer_t *event, *trav; unsigned long long at; if (!reg) { gf_log ("timer", GF_LOG_ERROR, "!reg"); return NULL; } event = calloc (1, sizeof (*event)); if (!event) { gf_log ("timer", GF_LOG_CRITICAL, "Not enough memory"); return NULL; } gettimeofday (&event->at, NULL); event->at.tv_usec = ((event->at.tv_usec + delta.tv_usec) % 1000000); event->at.tv_sec += ((event->at.tv_usec + delta.tv_usec) / 1000000); event->at.tv_sec += delta.tv_sec; at = TS (event->at); event->cbk = cbk; event->data = data; pthread_mutex_lock (®->lock); { trav = reg->active.prev; while (trav != ®->active) { if (TS (trav->at) < at) break; trav = trav->prev; } event->prev = trav; event->next = event->prev->next; event->prev->next = event; event->next->prev = event; } pthread_mutex_unlock (®->lock); return event; }
void * gf_timer_proc (void *ctx) { if (!ctx) { gf_log ("timer", GF_LOG_ERROR, "(!ctx)"); return 0; } gf_timer_registry_t *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; 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 (need_cbk) event->cbk (event->data); else break; } usleep (100000); } return NULL; }
int32_t gf_timer_call_cancel (glusterfs_ctx_t *ctx, gf_timer_t *event) { gf_timer_registry_t *reg = NULL; gf_boolean_t fired = _gf_false; if (ctx == NULL || event == NULL) { gf_msg_callingfn ("timer", GF_LOG_ERROR, EINVAL, LG_MSG_INVALID_ARG, "invalid argument"); return 0; } reg = gf_timer_registry_init (ctx); if (!reg) { gf_msg ("timer", GF_LOG_ERROR, 0, LG_MSG_INIT_TIMER_FAILED, "!reg"); GF_FREE (event); return 0; } pthread_mutex_lock (®->lock); { fired = event->fired; if (fired) goto unlock; event->next->prev = event->prev; event->prev->next = event->next; } unlock: pthread_mutex_unlock (®->lock); if (!fired) { GF_FREE (event); return 0; } return -1; }
gf_timer_t * gf_timer_call_after (glusterfs_ctx_t *ctx, struct timespec delta, gf_timer_cbk_t callbk, void *data) { gf_timer_registry_t *reg = NULL; gf_timer_t *event = NULL; gf_timer_t *trav = NULL; uint64_t at = 0; if (ctx == NULL) { gf_msg_callingfn ("timer", GF_LOG_ERROR, EINVAL, LG_MSG_INVALID_ARG, "invalid argument"); return NULL; } /* ctx and its fields are not accessed inside mutex!? * TODO: Even with this there is a possiblity of race * when cleanup_started is set after checking for it */ if (ctx->cleanup_started) { gf_msg_callingfn ("timer", GF_LOG_INFO, 0, LG_MSG_CTX_CLEANUP_STARTED, "ctx cleanup " "started"); return NULL; } reg = gf_timer_registry_init (ctx); if (!reg) { gf_msg_callingfn ("timer", GF_LOG_ERROR, 0, LG_MSG_TIMER_REGISTER_ERROR, "!reg"); return NULL; } event = GF_CALLOC (1, sizeof (*event), gf_common_mt_gf_timer_t); if (!event) { return NULL; } timespec_now (&event->at); timespec_adjust_delta (&event->at, delta); at = TS (event->at); event->callbk = callbk; event->data = data; event->xl = THIS; pthread_mutex_lock (®->lock); { trav = reg->active.prev; while (trav != ®->active) { if (TS (trav->at) < at) break; trav = trav->prev; } event->prev = trav; event->next = event->prev->next; event->prev->next = event; event->next->prev = event; } pthread_mutex_unlock (®->lock); return event; }
void * gf_timer_proc (void *ctx) { gf_timer_registry_t *reg = NULL; const struct timespec sleepts = {.tv_sec = 1, .tv_nsec = 0, }; gf_timer_t *event = NULL; xlator_t *old_THIS = NULL; if (ctx == NULL) { gf_msg_callingfn ("timer", GF_LOG_ERROR, EINVAL, LG_MSG_INVALID_ARG, "invalid argument"); return NULL; } reg = gf_timer_registry_init (ctx); if (!reg) { gf_msg ("timer", GF_LOG_ERROR, 0, LG_MSG_INIT_TIMER_FAILED, "!reg"); return NULL; } while (!reg->fin) { uint64_t now; struct timespec now_ts; 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; event->next->prev = event->prev; event->prev->next = event->next; event->fired = _gf_true; } } pthread_mutex_unlock (®->lock); if (need_cbk) { old_THIS = NULL; if (event->xl) { old_THIS = THIS; THIS = event->xl; } event->callbk (event->data); GF_FREE (event); if (old_THIS) { THIS = old_THIS; } } else { break; } } nanosleep (&sleepts, NULL); } pthread_mutex_lock (®->lock); { /* Do not call gf_timer_call_cancel(), * it will lead to deadlock */ while (reg->active.next != ®->active) { event = reg->active.next; /* cannot call list_del as the event doesnt have * list_head*/ __delete_entry (event); } } 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_msg_callingfn ("timer", GF_LOG_ERROR, EINVAL, LG_MSG_INVALID_ARG, "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; ctx->timer = reg; gf_thread_create (®->th, NULL, gf_timer_proc, ctx); } out: return ctx->timer; } void gf_timer_registry_destroy (glusterfs_ctx_t *ctx) { pthread_t thr_id; gf_timer_registry_t *reg = NULL; if (ctx == NULL) return; reg = ctx->timer; thr_id = reg->th; reg->fin = 1; pthread_join (thr_id, NULL); }
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; }