/* * api_check_memory - check memory * return: 0 if successful, count of failure otherwise * fp(in): FILE * to print check message * NOTE : this function checks malloc/free pair match and * dump debug debug information of malloc/calloced but not freeed. */ int api_check_memory (FILE * fp) { int res = 0; if (api_malloc_dhook_flag_set == 0) return 0; API_ONCE_FUNC (&once, once_function); API_LOCK (&mutex); if (malloc_count != free_count) { fprintf (fp, "malloc/free count mismatch (%d/%d)\n", malloc_count, free_count); res++; } if (!dlisth_is_empty (&malloc_list)) { dlisth *h; fprintf (fp, "malloc list not empty (memory leak)\n"); for (h = malloc_list.next; h != &malloc_list; h = h->next) { fprintf (fp, "\t"); dump_debug_h ((debug_malloc_h *) h, fp); fprintf (fp, "\n"); } res++; } API_UNLOCK (&mutex); return res; }
static int smrCbClose (void *arg, long long seq, short nid, int sid) { redisClient *c; callbackInfo *cb; dlisth *node; if (nid != smr_get_nid (server.smr_conn) || !(server.smr_init_flags & SMR_INIT_DONE)) return REDIS_OK; /* query from this server. get client from global callback list */ assert (!dlisth_is_empty (&server.global_callbacks)); /* global callback list shouldn't be empty */ node = server.global_callbacks.next; cb = (callbackInfo *) node; dlisth_delete (&cb->global_head); dlisth_delete (&cb->client_head); c = cb->client; zfree (cb); if (c->fd == -1) return REDIS_OK; /* ignore if the client is already freed */ assert (c->fd == sid); addReplyError (c, c->smr.protocol_error_reply); c->flags |= REDIS_CLOSE_AFTER_REPLY; return REDIS_OK; }
void decref_be_job (be_job_t * job) { int need_mutex; int need_free = 0; if (job == NULL) { return; } need_mutex = is_job_need_mutex (job); if (need_mutex) { pthread_mutex_lock (&job->ref_mutex); } job->ref_count--; need_free = (job->ref_count <= 0); if (need_mutex) { pthread_mutex_unlock (&job->ref_mutex); } if (need_free) { assert (dlisth_is_empty (&job->head)); assert (dlisth_is_empty (&job->htwhead)); pthread_mutex_destroy (&job->ref_mutex); if (job->free_func) { job->free_func (job->data); } free (job); } }
/* * li_api_destroy - destroy value indexer * return: void * indexer(in): VALUE_INDEXER * df(in): element destroy function */ static void li_api_destroy (VALUE_INDEXER * indexer, void (*df) (VALUE_AREA * va, API_VALUE * db)) { LIST_INDEXER *li = (LIST_INDEXER *) indexer; assert (li != NULL); while (!dlisth_is_empty (&li->elems)) { LIST_INDEXER_ELEM *e = (LIST_INDEXER_ELEM *) li->elems.next; if (df) df (e->va, e->value); dlisth_delete ((dlisth *) e); API_FREE (e); } API_FREE (li); }
/* sid = |flags(4byte)|client fd(4byte)| */ static int smrCbData (void *arg, long long seq, long long timestamp, short nid, int sid, int hash, smrData * smr_data, int size) { char *data = smr_data_get_data (smr_data); redisClient *c; short cmdflags; dlisth *node; /* Special commands */ if (size == 1 && data[0] == REDIS_SMR_CMD_CATCHUP_CHECK) { if (nid == smr_get_nid (server.smr_conn) && (server.smr_init_flags & SMR_INIT_CATCHUP_PHASE2)) checkSmrCatchup (); goto release_seq; } else if (size == 1 && data[0] == REDIS_SMR_CMD_DELIVER_OOM) { server.smr_oom_until = timestamp + REDIS_OOM_DURATION_MS; goto release_seq; } /* Normal command */ server.smr_mstime = timestamp; cmdflags = (0xFFFF0000 & sid) >> 16; /* Because we fixed the bug that causes timestamp be 0, * this warning log is not necessary and just an assert statement is enough after all. * But currently, there are nbase-arc clusters which have the bug. * So, we don't assert for now. */ if (timestamp == 0) { redisLog (REDIS_WARNING, "Timestamp of SMR callback is 0," "seq:%lld, nid:%d, sid:%d, hash:%d, size:%d", seq, nid, sid, hash, size); } if ((server.smr_init_flags & SMR_INIT_DONE) && nid == smr_get_nid (server.smr_conn)) { callbackInfo *cb; /* query from this server. get client from global callback list */ assert (!dlisth_is_empty (&server.global_callbacks)); /* global callback list shouldn't be empty */ node = server.global_callbacks.next; cb = (callbackInfo *) node; dlisth_delete (&cb->global_head); dlisth_delete (&cb->client_head); c = cb->client; assert (cb->hash == hash); assert (c->fd == -1 || c->fd == (0X0000FFFF & sid)); /* We already parsed querybuf because the query is requested from this * server before smr callback*/ c->argc = cb->argc; c->argv = cb->argv; cb->argc = 0; cb->argv = NULL; zfree (cb); server.current_client = c; /* fake client doesn't need to execute non-write query(read-only or admin) */ if (c->fd != -1 || cmdflags & REDIS_CMD_WRITE) { assert (!(c->flags & REDIS_CLOSE_AFTER_REPLY)); processCommand (c); } } else { /* replicated query from other servers, or catchup query during initialize */ c = server.smrlog_client; server.current_client = c; /* fake client doesn't need to execute non-write query(read-only or admin) */ if (cmdflags & REDIS_CMD_WRITE) { /* We need to parse querybuf because the query is from different server * or we are recovering without client */ sdsclear (c->querybuf); c->querybuf = sdsMakeRoomFor (c->querybuf, size); memcpy (c->querybuf, data, size); sdsIncrLen (c->querybuf, size); if (c->querybuf_peak < size) c->querybuf_peak = size; processInputBuffer (c); } } resetClient (c); zfree (c->argv); c->argv = NULL; server.current_client = NULL; release_seq: if (smr_release_seq_upto (server.smr_conn, seq + size) == -1) { redisLog (REDIS_WARNING, "smr_release_seq_upto error"); redisAssert (0); return REDIS_ERR; } server.smr_seqnum = seq + size; return REDIS_OK; }