felist *listLast(felist *l) { felist *t, *o; t = l; while ((o = listNext(t)) != NULL) t = o; return t; }
/* Watch for the specified key */ void watchForKey(redisClient *c, robj *key) { list *clients = NULL; listIter li; listNode *ln; watchedKey *wk; /* Check if we are already watching for this key */ listRewind(c->watched_keys,&li); while((ln = listNext(&li))) { wk = listNodeValue(ln); if (wk->db == c->db && equalStringObjects(key,wk->key)) return; /* Key already watched */ } /* This key is not already watched in this DB. Let's add it */ clients = dictFetchValue(c->db->watched_keys,key); if (!clients) { clients = listCreate(); dictAdd(c->db->watched_keys,key,clients); incrRefCount(key); } listAddNodeTail(clients,c); /* Add the new key to the lits of keys watched by this client */ wk = zmalloc(sizeof(*wk)); wk->key = key; wk->db = c->db; incrRefCount(key); listAddNodeTail(c->watched_keys,wk); }
void replicationFeedMonitors(list *monitors, int dictid, robj **argv, int argc) { listNode *ln; listIter li; int j; sds cmdrepr = sdsnew("+"); robj *cmdobj; struct timeval tv; gettimeofday(&tv,NULL); cmdrepr = sdscatprintf(cmdrepr,"%ld.%06ld ",(long)tv.tv_sec,(long)tv.tv_usec); if (dictid != 0) cmdrepr = sdscatprintf(cmdrepr,"(db %d) ", dictid); for (j = 0; j < argc; j++) { if (argv[j]->encoding == REDIS_ENCODING_INT) { cmdrepr = sdscatprintf(cmdrepr, "\"%ld\"", (long)argv[j]->ptr); } else { cmdrepr = sdscatrepr(cmdrepr,(char*)argv[j]->ptr, sdslen(argv[j]->ptr)); } if (j != argc-1) cmdrepr = sdscatlen(cmdrepr," ",1); } cmdrepr = sdscatlen(cmdrepr,"\r\n",2); cmdobj = createObject(REDIS_STRING,cmdrepr); listRewind(monitors,&li); while((ln = listNext(&li))) { redisClient *monitor = ln->value; addReply(monitor,cmdobj); } decrRefCount(cmdobj); }
void replicationFeedSlaves(list *slaves, int dictid, robj **argv, int argc) { listNode *ln; listIter li; int j; listRewind(slaves,&li); while((ln = listNext(&li))) { redisClient *slave = ln->value; /* Don't feed slaves that are still waiting for BGSAVE to start */ if (slave->replstate == REDIS_REPL_WAIT_BGSAVE_START) continue; /* Feed slaves that are waiting for the initial SYNC (so these commands * are queued in the output buffer until the intial SYNC completes), * or are already in sync with the master. */ if (slave->slaveseldb != dictid) { robj *selectcmd; if (dictid >= 0 && dictid < REDIS_SHARED_SELECT_CMDS) { selectcmd = shared.select[dictid]; incrRefCount(selectcmd); } else { selectcmd = createObject(REDIS_STRING, sdscatprintf(sdsempty(),"select %d\r\n",dictid)); } addReply(slave,selectcmd); decrRefCount(selectcmd); slave->slaveseldb = dictid; } addReplyMultiBulkLen(slave,argc); for (j = 0; j < argc; j++) addReplyBulk(slave,argv[j]); } }
uint8_t Calendar::listForDay(uint8_t maxNumber, Event::Occurrence intoArray[], const DateTime & dt) { DateTime startOfDay = dt.startOfDay(); DateTime justBeforeDayStart = startOfDay - Chronos::Span::Seconds(1); // Event::Occurrence * allVals = new Event::Occurrence[maxNumber]; /*if (! allVals) { CHRONOS_DEBUG_OUTLN("listForDay: Couldn't allocate space for list?"); return 0; } */ uint8_t numNext = listNext(maxNumber, intoArray, justBeforeDayStart); uint8_t numFound = 0; for (uint8_t i=0; i< numNext; i++) { if (intoArray[i].start.sameDateAs(startOfDay)) { numFound++; } } return numFound; }
/// 复制整个链表 list *listDup(list *orig) { list *copy; listIter *iter; listNode *node; if ((copy = listCreate()) == NULL) return NULL; copy->dup = orig->dup; copy->free = orig->free; copy->match = orig->match; iter = listGetIterator(orig, AL_START_HEAD); while((node = listNext(iter)) != NULL) { void *value; if (copy->dup) { value = copy->dup(node->value); if (value == NULL) { listRelease(copy); listReleaseIterator(iter); return NULL; } } else value = node->value; if (listAddNodeTail(copy, value) == NULL) { listRelease(copy); listReleaseIterator(iter); return NULL; } } listReleaseIterator(iter); return copy; }
/* 关键字搜索Node结点此时用到了list的match方法了 */ listNode *listSearchKey(list *list, void *key) { listIter *iter; listNode *node; //获取迭代器 iter = listGetIterator(list, AL_START_HEAD); while((node = listNext(iter)) != NULL) { //遍历循环 if (list->match) { //如果定义了list的match方法,则调用match方法 if (list->match(node->value, key)) { //如果方法返回true,则代表找到结点,释放迭代器 listReleaseIterator(iter); return node; } } else { //如果没有定义list 的match方法,则直接比较函数指针 if (key == node->value) { //如果相等,则代表找到结点,释放迭代器 listReleaseIterator(iter); return node; } } } listReleaseIterator(iter); return NULL; }
/* Duplicate the whole list. On out of memory NULL is returned. * On success a copy of the original list is returned. * * The 'Dup' method set with listSetDupMethod() function is used * to copy the node value. Otherwise the same pointer value of * the original node is used as value of the copied node. * * The original list both on success or error is never modified. */ list *listDup(list *orig) { list *copy; listIter iter; listNode *node; if ((copy = listCreate()) == NULL) return NULL; copy->dup = orig->dup; copy->free = orig->free; copy->match = orig->match; listRewind(orig, &iter); while((node = listNext(&iter)) != NULL) { void *value; if (copy->dup) { value = copy->dup(node->value); if (value == NULL) { listRelease(copy); return NULL; } } else value = node->value; if (listAddNodeTail(copy, value) == NULL) { listRelease(copy); return NULL; } } return copy; }
void closeTimedoutClients(void) { redisClient *c; listNode *ln; time_t now = time(NULL); listIter li; listRewind(server.clients,&li); while ((ln = listNext(&li)) != NULL) { c = listNodeValue(ln); if (server.maxidletime && !(c->flags & REDIS_SLAVE) && /* no timeout for slaves */ !(c->flags & REDIS_MASTER) && /* no timeout for masters */ dictSize(c->pubsub_channels) == 0 && /* no timeout for pubsub */ listLength(c->pubsub_patterns) == 0 && (now - c->lastinteraction > server.maxidletime)) { redisLog(REDIS_VERBOSE,"Closing idle client"); freeClient(c); } else if (c->flags & REDIS_BLOCKED) { if (c->blockingto != 0 && c->blockingto < now) { addReply(c,shared.nullmultibulk); unblockClientWaitingData(c); } } } }
list *listSearchKey(list *list, void *key) /*{{{*/ { listIter *iter; listNode *node; iter = listGetIterator(list, AL_START_HEAD); while((node = listNext(iter)) != NULL) { if(list->match) { if(list->match(node->value, key)) { listReleaseIterator(iter); return node; } } else { //如果match函数不存在,理论上讲是比较不了 //这时候只需要看地址就行了 if(key == node->value) { listReleaseIterator(iter); return node; } } } listReleaseIterator(iter); return NULL; }
/* Search the list for a node matching a given key. * The match is performed using the 'match' method * set with listSetMatchMethod(). If no 'match' method * is set, the 'value' pointer of every node is directly * compared with the 'key' pointer. * * On success the first matching node pointer is returned * (search starts from head). If no matching node exists * NULL is returned. */ listNode *listSearchKey(list *pList, void *key) { listIter *iter = listGetIterator(pList, DL_START_HEAD); listNode *node = listNext(iter); while(node != NULL) { if (pList->match) { if (pList->match(node->value, key)) { listReleaseIterator(iter); return node; } } else { if (key == node->value) { listReleaseIterator(iter); return node; } } } listReleaseIterator(iter); return NULL; }
/* * Write a log message out to all output channels. */ static void log_output(Logger *logger) { LOG_Output *out; for (out = listHead(&logger->outputs); out; out = listNext(out)) { pthread_mutex_lock(&out->output); switch(out->type) { case LOG_OT_UDP: case LOG_OT_TCP: case LOG_OT_FD: tcpWrite(out->u.fd, bufGet(&logger->scratch), bufLen(&logger->scratch)); break; case LOG_OT_FILE: case LOG_OT_FP: fwrite(bufGet(&logger->scratch), bufLen(&logger->scratch), 1, out->u.fp); fflush(out->u.fp); break; case LOG_OT_SYSLOG: syslog(out->u.priority, "%s", bufGet(&logger->scratch)); break; } pthread_mutex_unlock(&out->output); } }
void freeClient(vuiClient *c) { listNode *ln; listIter *it; cJSON *json; /* Free the query buffer */ sdsfree(c->querybuf); sdsfree(c->querymsg); sdsfree(c->res.body); sdsfree(c->res.reason); sdsfree(c->res.buf); /* Close socket, unregister events, and remove list of replies and * accumulated arguments. */ if (c->fd != -1) { aeDeleteFileEvent(server.el,c->fd,AE_READABLE); aeDeleteFileEvent(server.el,c->fd,AE_WRITABLE); close(c->fd); } it = listGetIterator(c->jsons, AL_START_HEAD); while((ln = listNext(it))) { json = (cJSON *)ln->value; cJSON_Delete(json); listDelNode(c->jsons, ln); } listRelease(c->jsons); listReleaseIterator(it); zfree(c); server.client = NULL; }
static void calculate_bm25(fts_t *fts, list *indices, dict_t *scores) { listIter *iter; listNode *node; unsigned long doc_size = fts_size(fts); unsigned long list_size = listLength(indices); doc_size = doc_size ? doc_size : 1; double avgdl = (fts->len * 1.0) / doc_size; iter = listGetIterator(indices, AL_START_HEAD); while((node = listNext(iter)) != NULL) { index_item_t *idx = node->value; int dl = idx->doc->len; fts_doc_score_t *fds = dict_get(scores, idx->doc->title->ptr); if (!fds) { fds = rr_malloc(sizeof(*fds)); fds->doc = idx->doc; fds->score = .0f; dict_set(scores, idx->doc->title->ptr, fds); } double idf = log((doc_size - list_size + 0.5) / (list_size + 0.5)); double tf = idx->tf * (BM25_K + 1) / (idx->tf + BM25_K * (1 - BM25_B + BM25_B*dl/avgdl)); fds->score += tf * idf; } listReleaseIterator(iter); }
/* *Function : mlistNext *Description: define 'next'element in the list in mlist *Parameters : hlist - mlist handle * list - list number to get 'next' element * location - location after which to get 'next' element *Return : 'next' element in the list */ int mlistNext (HLIST hlist, int list, int location) { mListDesc *mlist=(mListDesc*)listGetElem(hlist, list); if (!mlist) return RVERROR; if (location==mlist->tail) return RVERROR; return listNext(hlist, location); }
/* Search the list for a node matching a given key. * The match is performed using the 'match' method * set with listSetMatchMethod(). If no 'match' method * is set, the 'value' pointer of every node is directly * compared with the 'key' pointer. * * On success the first matching node pointer is returned * (search starts from head). If no matching node exists * NULL is returned. */ listNode *listSearchKey(list *list, void *key) { listIter *iter; listNode *node; //遍历整个链表 iter = listGetIterator(list, AL_START_HEAD); while((node = listNext(iter)) != NULL) { //如果有比较的回调函数,调用该函数 if (list->match) { if (list->match(node->value, key)) { listReleaseIterator(iter); return node; } } else { //否则比较两个value是否相同 if (key == node->value) { listReleaseIterator(iter); return node; } } } //也就是默认的match函数就是比较两个value是否相等 listReleaseIterator(iter); return NULL; }
// 撤销对这个客户端的所有 WATCH // 清除 EXEC dirty FLAG 的任务由调用者完成 void unwatchAllKeys(redisClient *c) { listIter li; listNode *ln; // 没有 WATCHED KEY ,直接返回 if (listLength(c->watched_keys) == 0) return; listRewind(c->watched_keys,&li); while((ln = listNext(&li))) { list *clients; watchedKey *wk; /* Lookup the watched key -> clients list and remove the client * from the list */ // 将当前客户端从监视 KEY 的链表中移除 wk = listNodeValue(ln); clients = dictFetchValue(wk->db->watched_keys, wk->key); redisAssertWithInfo(c,NULL,clients != NULL); listDelNode(clients,listSearchKey(clients,c)); /* Kill the entry at all if this was the only client */ // 如果监视 KEY 的只有这个客户端 // 那么将链表从字典中删除 if (listLength(clients) == 0) dictDelete(wk->db->watched_keys, wk->key); /* Remove this watched key from the client->watched list */ // 还需要将 KEY 从 client->watched_keys 链表中移除 listDelNode(c->watched_keys,ln); decrRefCount(wk->key); zfree(wk); } }
int luaworkDoDir(lua_State *L,const char *path, char *err) { int ret = UGOK; sds relpath = sdsempty(); list *queue = listCreate(); listNode *node=NULL; listIter *iter = NULL; if (xfilelistdir(path, "*.lua", queue) == UGERR) { luaworkSetError(err, "list files for %s failed", path); ret = UGERR; goto END; } iter = listGetIterator(queue, AL_START_HEAD); while ((node=listNext(iter))!=NULL) { const char *filename = (char *) (node->value); sdsclear(relpath); relpath = sdscatprintf(relpath, "%s/%s", path, filename); ret = luaworkDoFile(L, relpath, err); if (ret != UGOK) break; } listReleaseIterator(iter); END: listRelease(queue); sdsfree(relpath); return ret; }
void aio_submit_queue() { int rv; struct aiocb *cb; if (0 == listLength(aio_queue)) return; listIter *it; listNode *nd; it = listGetIterator(aio_queue, AL_START_HEAD); while ((nd = listNext(it))) { cb = (struct aiocb *)nd->value; cb->retries += 1; rv = aio_submit(cb); if (0 == rv) { listDelNode(aio_queue, nd); } else if (-2 == rv) { break; } } end: zfree(it); }
/* 取消客户端所订阅的所有模式,最后返回退订的模式数量 */ int pubsubUnsubscribeAllPatterns(redisClient *c, int notify) { listNode *ln; listIter li; int count = 0; // 获取c->pubsub_patterns链表迭代器 listRewind(c->pubsub_patterns,&li); // 遍历客户端订阅的模式链表,逐一退订 while ((ln = listNext(&li)) != NULL) { robj *pattern = ln->value; // 统计退订的模式数量 count += pubsubUnsubscribePattern(c,pattern,notify); } // 如果count == 0,说明客户端没有订阅任何模式,回复客户端 if (notify && count == 0) { /* We were subscribed to nothing? Still reply to the client. */ addReply(c,shared.mbulkhdr[3]); addReply(c,shared.punsubscribebulk); addReply(c,shared.nullbulk); addReplyLongLong(c,dictSize(c->pubsub_channels)+ listLength(c->pubsub_patterns)); } return count; }
// 取消客户端对所有的键的监视,清理 EXEC dirty 标识状态由调用者决定 void unwatchAllKeys(client *c) { listIter li; listNode *ln; // 如果客户端没有监视key则直接返回 if (listLength(c->watched_keys) == 0) return; listRewind(c->watched_keys,&li); // 遍历客户端监视的key while((ln = listNext(&li))) { list *clients; watchedKey *wk; /* Lookup the watched key -> clients list and remove the client * from the list */ wk = listNodeValue(ln); // 从数据库中的watched_keys字典中查找出监视key的client clients = dictFetchValue(wk->db->watched_keys, wk->key); serverAssertWithInfo(c,NULL,clients != NULL); // 从client的链表中删除当前client节点 listDelNode(clients,listSearchKey(clients,c)); /* Kill the entry at all if this was the only client */ // 如果client链表为空,标识给key没有被监视 if (listLength(clients) == 0) // 从数据库的watched_keys中删除该key dictDelete(wk->db->watched_keys, wk->key); /* Remove this watched key from the client->watched list */ // 从客户端的watched_keys中删除该节点 listDelNode(c->watched_keys,ln); decrRefCount(wk->key); zfree(wk); } }
void* listRemove(SList* list, int index) { void* res = NULL; if(list) { listHead(list); if(!listEmpty(list)) { if(index == 0) { SListNode* to_delete = list->head; list->head = list->head->next; res = to_delete->data; free(to_delete); } else { int i = 1; while(listNext(list) && i != index-1) ++i; if( i == index-1) { // l'element existe SListNode* to_delete = list->curr->next; list->curr->next = list->curr->next->next; res = to_delete->data; free(to_delete); } } } } return res; }
/* Unsubscribe from all the patterns. Return the number of patterns the * client was subscribed from. * * 退订客户端 c 订阅的所有模式。 * * 返回被退订模式的数量。 */ int pubsubUnsubscribeAllPatterns(redisClient *c, int notify) { listNode *ln; listIter li; int count = 0; // 迭代客户端订阅模式的链表 listRewind(c->pubsub_patterns,&li); while ((ln = listNext(&li)) != NULL) { robj *pattern = ln->value; // 退订,并计算退订数 count += pubsubUnsubscribePattern(c,pattern,notify); } // 如果在执行这个函数时,客户端没有订阅任何模式, // 那么向客户端发送回复 if (notify && count == 0) { /* We were subscribed to nothing? Still reply to the client. */ addReply(c,shared.mbulkhdr[3]); addReply(c,shared.punsubscribebulk); addReply(c,shared.nullbulk); addReplyLongLong(c,dictSize(c->pubsub_channels)+ listLength(c->pubsub_patterns)); } // 退订总数 return count; }
/* Remove the 'key' from the list of blocked keys for a given client. * * The function returns 1 when there are no longer blocking keys after * the current one was removed (and the client can be unblocked). */ int dontWaitForSwappedKey(redisClient *c, robj *key) { list *l; listNode *ln; listIter li; struct dictEntry *de; /* The key object might be destroyed when deleted from the c->io_keys * list (and the "key" argument is physically the same object as the * object inside the list), so we need to protect it. */ incrRefCount(key); /* Remove the key from the list of keys this client is waiting for. */ listRewind(c->io_keys,&li); while ((ln = listNext(&li)) != NULL) { if (equalStringObjects(ln->value,key)) { listDelNode(c->io_keys,ln); break; } } redisAssert(ln != NULL); /* Remove the client form the key => waiting clients map. */ de = dictFind(c->db->io_keys,key); redisAssert(de != NULL); l = dictGetEntryVal(de); ln = listSearchKey(l,c); redisAssert(ln != NULL); listDelNode(l,ln); if (listLength(l) == 0) dictDelete(c->db->io_keys,key); decrRefCount(key); return listLength(c->io_keys) == 0; }
/* compare should return -1 on lesser, 0 on equal and 1 on greater */ List listGetVal(List root, void* val, int (*compare)(const void*, const void*)) { List element = listBegin(root); for (; element && element->v && compare(element->v, val) != 0; element = listNext(element)) ; return element; }
int _msg_check(const char *file, int line, rmtContext *ctx, struct msg *msg, int panic) { struct mbuf *mbuf; listIter *iter; listNode *node; uint32_t total_mbuf_len = 0; int err = 0; if (msg == NULL) { return RMT_ERROR; } //check msg length iter = listGetIterator(msg->data, AL_START_HEAD); while ((node = listNext(iter)) != NULL) { mbuf = listNodeValue(node); total_mbuf_len += mbuf_length(mbuf); if (mbuf->pos < mbuf->start) { _log(file, line, 0, "MSG CHECK Error: mbuf->pos(%p) < mbuf->start(%p)", mbuf->pos, mbuf->start); err = 1; } if (mbuf->pos > mbuf->last) { _log(file, line, 0, "MSG CHECK Error: mbuf->pos(%p) > mbuf->last(%p)", mbuf->pos, mbuf->last); err = 1; } } listReleaseIterator(iter); if (msg->mlen != total_mbuf_len) { _log(file, line, 0, "MSG CHECK Error: msg->mlen(%u) != total_mbuf_len(%u)", msg->mlen, total_mbuf_len); err = 1; } if (msg->request == 1) { if (memcmp(ctx->cmd, RMT_CMD_REDIS_MIGRATE, MIN(sdslen(ctx->cmd),strlen(RMT_CMD_REDIS_MIGRATE))) == 0 && msg->noreply != ctx->noreply) { _log(file, line, 0, "MSG CHECK Error: msg->noreply(%u) != ctx->noreply(%d)", msg->noreply, ctx->noreply); err = 1; } } if (err) goto error; return RMT_OK; error: MSG_DUMP(msg, LOG_ERR, 0); if (panic) { rmt_stacktrace(1); abort(); } return RMT_ERROR; }
/* Unwatch all the keys watched by this client. To clean the EXEC dirty * flag is up to the caller. */ void unwatchAllKeys(redisClient *c) { listIter li; listNode *ln; if (listLength(c->watched_keys) == 0) return; listRewind(c->watched_keys,&li); while((ln = listNext(&li))) { list *clients; watchedKey *wk; /* Lookup the watched key -> clients list and remove the client * from the list */ wk = listNodeValue(ln); clients = dictFetchValue(wk->db->watched_keys, wk->key); redisAssert(clients != NULL); listDelNode(clients,listSearchKey(clients,c)); /* Kill the entry at all if this was the only client */ if (listLength(clients) == 0) dictDelete(wk->db->watched_keys, wk->key); /* Remove this watched key from the client->watched list */ listDelNode(c->watched_keys,ln); decrRefCount(wk->key); zfree(wk); } }
/* *Function : mlistHead *Description: define 1st (head) element in the list in mlist *Parameters : hlist - mlist handle * list - list number to get 'next' element *Return : 1st (head) element in the list */ int mlistHead (HLIST hlist, int list) { mListDesc *mlist=(mListDesc*)listGetElem(hlist, list); if (!mlist) return RVERROR; if (!mlist->count) return RVERROR; return listNext(hlist, list); }
static void glueReplyBuffersIfNeeded(redisClient *c) { int copylen = 0; char buf[GLUEREPLY_UP_TO]; listNode *ln; listIter li; robj *o; listRewind(c->reply,&li); while((ln = listNext(&li))) { int objlen; o = ln->value; objlen = sdslen(o->ptr); if (copylen + objlen <= GLUEREPLY_UP_TO) { memcpy(buf+copylen,o->ptr,objlen); copylen += objlen; listDelNode(c->reply,ln); } else { if (copylen == 0) return; break; } } /* Now the output buffer is empty, add the new single element */ o = createObject(REDIS_STRING,sdsnewlen(buf,copylen)); listAddNodeHead(c->reply,o); }
felist *listCopy(felist *srcfirstnode, size_t nodesize) { felist *prevnode = NULL; felist *currnode = srcfirstnode; felist *result = NULL; if(srcfirstnode == NULL) return NULL; while(currnode != NULL) { felist *newnode = (felist *) malloc(sizeof(felist)); newnode->prev = prevnode; if(prevnode == NULL) { result = newnode; } else { prevnode->next = newnode; } newnode->next = NULL; newnode->node = (void *) malloc(nodesize); memcpy(newnode->node, currnode->node, nodesize); prevnode = newnode; currnode = listNext(currnode); } return result; }