/* 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; 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; }
/* * 订阅一个频道,订阅成功返回 1, 如果返回 0, 则客户端已经订阅过这个频道 */ int pubsubSubscribeChannel(redisClient *c, robj *channel) { dictEntry *de; list *clients = NULL; int retval = 0; /* Add the channel to the client -> channels hash table */ if (dictAdd(c->pubsub_channels,channel,NULL) == DICT_OK) { retval = 1; incrRefCount(channel); /* Add the client to the channel -> list of clients hash table */ de = dictFind(server.pubsub_channels,channel); if (de == NULL) { clients = listCreate(); dictAdd(server.pubsub_channels,channel,clients); incrRefCount(channel); } else { clients = dictGetVal(de); } listAddNodeTail(clients,c); } /* Notify the client */ addReply(c,shared.mbulkhdr[3]); addReply(c,shared.subscribebulk); addReplyBulk(c,channel); addReplyLongLong(c,clientSubscriptionsCount(c)); return retval; }
/* Subscribe a client to a pattern. Returns 1 if the operation succeeded, or 0 if the client was already subscribed to that pattern. * * 设置客户端 c 订阅模式 pattern 。 * * 订阅成功返回 1 ,如果客户端已经订阅了该模式,那么返回 0 。 */ int pubsubSubscribePattern(redisClient *c, robj *pattern) { int retval = 0; // 在链表中查找模式,看客户端是否已经订阅了这个模式 // 这里为什么不像 channel 那样,用字典来进行检测呢? // 虽然 pattern 的数量一般来说并不多 if (listSearchKey(c->pubsub_patterns,pattern) == NULL) { // 如果没有的话,执行以下代码 retval = 1; pubsubPattern *pat; // 将 pattern 添加到 c->pubsub_patterns 链表中 listAddNodeTail(c->pubsub_patterns,pattern); incrRefCount(pattern); // 创建并设置新的 pubsubPattern 结构 pat = zmalloc(sizeof(*pat)); pat->pattern = getDecodedObject(pattern); pat->client = c; // 添加到末尾 listAddNodeTail(server.pubsub_patterns,pat); } /* Notify the client */ // 回复客户端。 // 示例: // redis 127.0.0.1:6379> PSUBSCRIBE xxx* // Reading messages... (press Ctrl-C to quit) // 1) "psubscribe" // 2) "xxx*" // 3) (integer) 1 addReply(c,shared.mbulkhdr[3]); // 回复 "psubscribe" 字符串 addReply(c,shared.psubscribebulk); // 回复被订阅的模式 addReplyBulk(c,pattern); // 回复客户端订阅的频道和模式的总数 addReplyLongLong(c,dictSize(c->pubsub_channels)+listLength(c->pubsub_patterns)); return retval; }
redisClient *createClient(int fd) { redisClient *c = zmalloc(sizeof(redisClient)); /* passing -1 as fd it is possible to create a non connected client. * This is useful since all the Redis commands needs to be executed * in the context of a client. When commands are executed in other * contexts (for instance a Lua script) we need a non connected client. */ if (fd != -1) { anetNonBlock(NULL,fd); anetEnableTcpNoDelay(NULL,fd); if (server.tcpkeepalive) anetKeepAlive(NULL,fd,server.tcpkeepalive); if (aeCreateFileEvent(server.el,fd,AE_READABLE, readQueryFromClient, c) == AE_ERR) { close(fd); zfree(c); return NULL; } } selectDb(c,0); c->fd = fd; c->name = NULL; c->bufpos = 0; c->querybuf = sdsempty(); c->querybuf_peak = 0; c->reqtype = 0; c->argc = 0; c->argv = NULL; c->cmd = c->lastcmd = NULL; c->multibulklen = 0; c->bulklen = -1; c->sentlen = 0; c->flags = 0; c->ctime = c->lastinteraction = server.unixtime; c->authenticated = 0; c->replstate = REDIS_REPL_NONE; c->slave_listening_port = 0; c->reply = listCreate(); c->reply_bytes = 0; c->obuf_soft_limit_reached_time = 0; listSetFreeMethod(c->reply,decrRefCount); listSetDupMethod(c->reply,dupClientReplyValue); c->bpop.keys = dictCreate(&setDictType,NULL); c->bpop.timeout = 0; c->bpop.target = NULL; c->io_keys = listCreate(); c->watched_keys = listCreate(); listSetFreeMethod(c->io_keys,decrRefCount); c->pubsub_channels = dictCreate(&setDictType,NULL); c->pubsub_patterns = listCreate(); listSetFreeMethod(c->pubsub_patterns,decrRefCount); listSetMatchMethod(c->pubsub_patterns,listMatchObjects); if (fd != -1) listAddNodeTail(server.clients,c); initClientMultiState(c); return c; }
// HTTP_LUA_COMMANDS HTTP_LUA_COMMANDS HTTP_LUA_COMMANDS HTTP_LUA_COMMANDS static void addHttpResponseHeader(sds name, sds value) { if (!server.alc.CurrClient->http.resp_hdr) { server.alc.CurrClient->http.resp_hdr = listCreate(); server.alc.CurrClient->http.resp_hdr->free = free_two_sds; } two_sds *ss = init_two_sds(name, value); // Store RESP Headers in List listAddNodeTail(server.alc.CurrClient->http.resp_hdr, ss); }
/* Subscribe a client to a channel. Returns 1 if the operation succeeded, or * 0 if the client was already subscribed to that channel. * * 设置客户端 c 订阅频道 channel 。 * * 订阅成功返回 1 ,如果客户端已经订阅了该频道,那么返回 0 。 */ int pubsubSubscribeChannel(redisClient *c, robj *channel) { dictEntry *de; list *clients = NULL; int retval = 0; /* Add the channel to the client -> channels hash table */ // 将 channels 填接到 c->pubsub_channels 的集合中(值为 NULL 的字典视为集合) if (dictAdd(c->pubsub_channels,channel,NULL) == DICT_OK) { retval = 1; incrRefCount(channel); // 关联示意图 // { // 频道名 订阅频道的客户端 // 'channel-a' : [c1, c2, c3], // 'channel-b' : [c5, c2, c1], // 'channel-c' : [c10, c2, c1] // } /* Add the client to the channel -> list of clients hash table */ // 从 pubsub_channels 字典中取出保存着所有订阅了 channel 的客户端的链表 // 如果 channel 不存在于字典,那么添加进去 de = dictFind(server.pubsub_channels,channel); if (de == NULL) { clients = listCreate(); dictAdd(server.pubsub_channels,channel,clients); incrRefCount(channel); } else { clients = dictGetVal(de); } // before: // 'channel' : [c1, c2] // after: // 'channel' : [c1, c2, c3] // 将客户端添加到链表的末尾 listAddNodeTail(clients,c); } /* Notify the client */ // 回复客户端。 // 示例: // redis 127.0.0.1:6379> SUBSCRIBE xxx // Reading messages... (press Ctrl-C to quit) // 1) "subscribe" // 2) "xxx" // 3) (integer) 1 addReply(c,shared.mbulkhdr[3]); // "subscribe\n" 字符串 addReply(c,shared.subscribebulk); // 被订阅的客户端 addReplyBulk(c,channel); // 客户端订阅的频道和模式总数 addReplyLongLong(c,dictSize(c->pubsub_channels)+listLength(c->pubsub_patterns)); return retval; }
static void unmapFDToIndex(aeEventLoop *eventLoop, socket_t s) { fdi_t fdi = lookupFDI(eventLoop, s); if (fdi == INVALID_FDI) { return; } dictDelete(eventLoop->fdiMap->map, (void *)s); listAddNodeTail(eventLoop->fdiMap->recycle_pool, (void *)fdi); }
void create_list() { int n,i; int *elem; list *ll; ll=listCreate(); printf("给你的链表起个名字吧:(限于字母)"); scanf("%s",ll->name); printf("输入初始化时候链表需要插入多少元素:"); scanf("%d",&n); printf("依次输入插入的元素:"); for(i=0;i<n;i++){ elem=(int*)malloc(sizeof(int)); scanf("%d",elem); ll=listAddNodeTail(ll,elem); } listall=listAddNodeTail(listall,ll); printf("创建完毕!\n"); }
robj *rdbLoadNRL(FILE *fp) { robj *iname; unsigned int u; d_l_t *nrlind = malloc(sizeof(d_l_t)); nrlind->l1 = listCreate(); list *nrltoks = nrlind->l1; nrlind->l2 = listCreate(); list *nrlcols = nrlind->l2; if ((u = rdbLoadLen(fp, NULL)) == REDIS_RDB_LENERR) return NULL; nrlind->num = (int)u; int imatch = nrlind->num; if (!(iname = rdbLoadStringObject(fp))) return NULL; if ((u = rdbLoadLen(fp, NULL)) == REDIS_RDB_LENERR) return NULL; int tmatch = (int)u; unsigned int ssize; if ((ssize = rdbLoadLen(fp, NULL)) == REDIS_RDB_LENERR) return NULL; for (uint32 i = 0; i < ssize; i++) { robj *r; if (!(r = rdbLoadStringObject(fp))) return NULL; listAddNodeTail(nrltoks, sdsdup(r->ptr)); decrRefCount(r); } if ((ssize = rdbLoadLen(fp, NULL)) == REDIS_RDB_LENERR) return NULL; for (uint32 i = 0; i < ssize; i++) { uint32 col; if ((col = rdbLoadLen(fp, NULL)) == REDIS_RDB_LENERR) return NULL; listAddNodeTail(nrlcols, (void *)(long)col); } Index[server.dbid][imatch].obj = iname; Index[server.dbid][imatch].table = tmatch; Index[server.dbid][imatch].column = -1; Index[server.dbid][imatch].type = COL_TYPE_NONE; Index[server.dbid][imatch].virt = 0; Index[server.dbid][imatch].nrl = 1; int dbid = server.dbid; if (Num_indx[dbid] < (imatch + 1)) Num_indx[dbid] = imatch + 1; return createObject(REDIS_NRL_INDEX, nrlind); }
/* * 监视给定 key * * T = O(N) */ void watchForKey(redisClient *c, robj *key) { list *clients = NULL; listIter li; listNode *ln; watchedKey *wk; /* Check if we are already watching for this key */ // 检查该 key 是否已经被 WATCH // (出现在 WATCH 命令调用时一个 key 被输入多次的情况) // 如果是的话,直接返回 // O(N) 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 */ } // key 未被监视 // 根据 key ,将客户端加入到 DB 的监视 key 字典中 /* This key is not already watched in this DB. Let's add it */ // O(1) clients = dictFetchValue(c->db->watched_keys,key); if (!clients) { clients = listCreate(); dictAdd(c->db->watched_keys,key,clients); incrRefCount(key); } listAddNodeTail(clients,c); // 将 key 添加到客户端的监视列表中 /* Add the new key to the lits of keys watched by this client */ // O(1) wk = zmalloc(sizeof(*wk)); wk->key = key; wk->db = c->db; incrRefCount(key); listAddNodeTail(c->watched_keys,wk); }
/* node can be NULL so node_name is a seperate parameter. */ shard *counterAddShard(counter *cntr, clusterNode* node, const char *node_name) { shard *shrd = zcalloc(sizeof(shard)); shrd->node = node; memcpy(shrd->node_name,node_name,CLUSTER_NAMELEN); if (node == myself) { serverAssert(cntr->myshard == NULL); cntr->myshard = shrd; } listAddNodeTail(cntr->shards, shrd); return shrd; }
/* Subscribe a client to a pattern. Returns 1 if the operation succeeded, or 0 if the client was already subscribed to that pattern. */ int pubsubSubscribePattern(redisClient *c, robj *pattern) { int retval = 0; if (listSearchKey(c->pubsub_patterns,pattern) == NULL) { retval = 1; pubsubPattern *pat; listAddNodeTail(c->pubsub_patterns,pattern); incrRefCount(pattern); pat = zmalloc(sizeof(*pat)); pat->pattern = getDecodedObject(pattern); pat->client = c; listAddNodeTail(server.pubsub_patterns,pat); } /* Notify the client */ addReply(c,shared.mbulkhdr[3]); addReply(c,shared.psubscribebulk); addReplyBulk(c,pattern); addReplyLongLong(c,dictSize(c->pubsub_channels)+listLength(c->pubsub_patterns)); return retval; }
void addReply(redisClient *c, robj *obj) { if (listLength(c->reply) == 0 && (c->replstate == REDIS_REPL_NONE || c->replstate == REDIS_REPL_ONLINE) && aeCreateFileEvent(server.el, c->fd, AE_WRITABLE, sendReplyToClient, c) == AE_ERR) return; if (server.vm_enabled && obj->storage != REDIS_VM_MEMORY) { obj = dupStringObject(obj); obj->refcount = 0; /* getDecodedObject() will increment the refcount */ } listAddNodeTail(c->reply,getDecodedObject(obj)); }
void bioCreateBackgroundJob(int type, void *arg1, void *arg2, void *arg3) { struct bio_job *job = zmalloc(sizeof(*job)); job->time = time(NULL); job->arg1 = arg1; job->arg2 = arg2; job->arg3 = arg3; pthread_mutex_lock(&bio_mutex[type]); listAddNodeTail(bio_jobs[type],job); bio_pending[type]++; pthread_cond_signal(&bio_condvar[type]); pthread_mutex_unlock(&bio_mutex[type]); }
// WATCH 某个 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 */ // 所有被 WATCHED 的 KEY 都被放在 redisClient.watched_keys 链表中 // 遍历这个链表,查看这个 KEY 是否已经处于监视状态(WATCHED) 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 */ // 如果 KEY 还没有被 WATCH 过,那么对它进行 WATCH clients = dictFetchValue(c->db->watched_keys,key); if (!clients) { // 如果 clients 链表不存在 // 说明这个客户端是第一个监视这个 DB 的这个 KEY 的客户端 // 那么 clients 创建链表,并将它添加到 c->db->watched_keys 字典中 clients = listCreate(); dictAdd(c->db->watched_keys,key,clients); incrRefCount(key); } // 将客户端添加到 clients 链表 listAddNodeTail(clients,c); /* Add the new key to the lits of keys watched by this client */ // 除了 c->db->watched_keys 之外 // 还要将被 WATCH 的 KEY 添加到 c->watched_keys wk = zmalloc(sizeof(*wk)); wk->key = key; wk->db = c->db; incrRefCount(key); listAddNodeTail(c->watched_keys,wk); }
redisClient *createClient(int fd) { redisClient *c = zmalloc(sizeof(redisClient)); c->bufpos = 0; anetNonBlock(NULL,fd); anetTcpNoDelay(NULL,fd); if (!c) return NULL; if (aeCreateFileEvent(server.el,fd,AE_READABLE, readQueryFromClient, c) == AE_ERR) { #ifdef _WIN32 closesocket(fd); #else close(fd); #endif zfree(c); return NULL; } selectDb(c,0); c->fd = fd; c->querybuf = sdsempty(); c->reqtype = 0; c->argc = 0; c->argv = NULL; c->multibulklen = 0; c->bulklen = -1; c->sentlen = 0; c->flags = 0; c->lastinteraction = time(NULL); c->authenticated = 0; c->replstate = REDIS_REPL_NONE; c->reply = listCreate(); listSetFreeMethod(c->reply,decrRefCount); listSetDupMethod(c->reply,dupClientReplyValue); c->bpop.keys = NULL; c->bpop.count = 0; c->bpop.timeout = 0; c->bpop.target = NULL; c->io_keys = listCreate(); c->watched_keys = listCreate(); listSetFreeMethod(c->io_keys,decrRefCount); c->pubsub_channels = dictCreate(&setDictType,NULL); c->pubsub_patterns = listCreate(); listSetFreeMethod(c->pubsub_patterns,decrRefCount); listSetMatchMethod(c->pubsub_patterns,listMatchObjects); listAddNodeTail(server.clients,c); initClientMultiState(c); return c; }
ugClient *createClient(int fd) { ugClient *c = zmalloc(sizeof(ugClient)); memset(c,0,sizeof(ugClient)); if (fd != -1) { anetNonBlock(NULL,fd); anetEnableTcpNoDelay(NULL,fd); if (server.tcpkeepalive) anetKeepAlive(NULL, fd, server.tcpkeepalive); if (aeCreateFileEvent(server.el, fd, AE_READABLE, readQueryFromClient, c) == AE_ERR) { #ifdef _WIN32 aeWinCloseSocket(fd); #else close(fd); #endif zfree(c); return NULL; } } if (server.config->password == NULL) { c->authenticated = 1; } c->querybuf = sdsempty(); c->fd = fd; c->ctime = c->lastinteraction = time(NULL); c->multibulklen = 0; c->bulklen = -1; c->reply = listCreate(); c->reply_bytes = 0; c->bufpos = 0; c->sentlen = 0; /* listSetDupMethod(c->reply, listDupReplyObjects); */ listSetFreeMethod(c->reply, listFreeReplyObjects); c->pubsub_channels = dictCreate(&callbackDict, NULL); c->pubsub_patterns = listCreate(); listSetMatchMethod(c->pubsub_patterns, listMatchPubsubPattern); listSetFreeMethod(c->pubsub_patterns, listFreePubsubPattern); /* c->pubsub_patterns = listCreate(); */ if (!server.clients) { server.clients = createClientlist(); } listAddNodeTail(server.clients, c); return c; }
void dup_list() { listNode *node; list *orig=found_list(&node); list *ll; if(orig){ ll=listDup(orig); printf("输入复制过后的链表名称:"); scanf("%s",(ll->name)); listall=listAddNodeTail(listall,ll); printf("复制成功\n"); }else{ printf("没有这个链表\n"); } }
/* 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); // 将监视键添加到 redisClient.watched_keys 的尾部 /* Add the new key to the list of keys watched by this client */ wk = zmalloc(sizeof(*wk)); wk->key = key; wk->db = c->db; incrRefCount(key); listAddNodeTail(c->watched_keys,wk); }
/* Parses "xxx$col1 yyy$col2 zzz" -> "xxx[col1] yyy[col2] zzz" */ bool parseNRLcmd(char *o_s, list *nrltoks, list *nrlcols, int tmatch) { char *s = strchr(o_s, '$'); if (!s) { listAddNodeTail(nrltoks, sdsdup(o_s)); /* freed in freeNrlIndexObject */ } else { while (1) { s++; /* advance past "$" */ char *nxo = s; while (isalnum(*nxo) || *nxo == '_') nxo++; /* col must be alpnum */ int cmatch = find_column_n(tmatch, s, nxo - s); if (cmatch == -1) return 0; listAddNodeTail(nrlcols, (void *)(long)(cmatch + 1)); /* 0!=NULL */ listAddNodeTail(nrltoks, sdsnewlen(o_s, (s - 1) - o_s)); /*no "$"*/ char *nexts = strchr(s, '$'); /* var is '$' delimed */ if (!nexts) { /* no more vars */ if (*nxo) listAddNodeTail(nrltoks, sdsnewlen(nxo, strlen(nxo))); break; } o_s = nxo; s = nexts; } } return 1; }
// 让client监视所有的指定的key void watchForKey(client *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 */ // 如果数据库中该键没有被client监视则添加它 clients = dictFetchValue(c->db->watched_keys,key); // 没有被client监视 if (!clients) { // 创建一个空链表 clients = listCreate(); // 值是被client监控的key,键是client,添加到数据库的watched_keys字典中 dictAdd(c->db->watched_keys,key,clients); incrRefCount(key); } // 将当前client添加到监视该key的client链表的尾部 listAddNodeTail(clients,c); /* Add the new key to the list of keys watched by this client */ // 将新的被监视的key和与该key关联的数据库加入到客户端的watched_keys中 wk = zmalloc(sizeof(*wk)); wk->key = key; wk->db = c->db; incrRefCount(key); listAddNodeTail(c->watched_keys,wk); }
//创建一个后台任务 void bioCreateBackgroundJob(int type, void *arg1, void *arg2, void *arg3) { struct bio_job *job = zmalloc(sizeof(*job)); //初始化变量 job->time = time(NULL); job->arg1 = arg1; job->arg2 = arg2; job->arg3 = arg3; //多线程环境,操作任务队列时,需要使用mutex防止冲突 pthread_mutex_lock(&bio_mutex[type]); listAddNodeTail(bio_jobs[type],job); bio_pending[type]++; //通知操作线程有新任务添加 pthread_cond_signal(&bio_condvar[type]); pthread_mutex_unlock(&bio_mutex[type]); }
static client createClient(void) { client c = zmalloc(sizeof(struct _client)); c->context = redisAsyncConnect(config.hostip,config.hostport); c->context->data = c; redisAsyncSetDisconnectCallback(c->context,clientDisconnected); if (c->context->err) { fprintf(stderr,"Connect: %s\n",c->context->errstr); exit(1); } redisAeAttach(config.el,c->context); listAddNodeTail(config.clients,c); issueRequest(c); return c; }
/* Unblock a client calling the right function depending on the kind * of operation the client is blocking for. * 不阻塞客户端 * 取消给定的客户端的阻塞状态*/ void unblockClient(redisClient *c) { if (c->btype == REDIS_BLOCKED_LIST) { unblockClientWaitingData(c); } else if (c->btype == REDIS_BLOCKED_WAIT) { unblockClientWaitingReplicas(c); } else { redisPanic("Unknown btype in unblockClient()."); } /* Clear the flags, and put the client in the unblocked list so that * we'll process new commands in its query buffer ASAP. */ c->flags &= ~REDIS_BLOCKED; c->flags |= REDIS_UNBLOCKED; c->btype = REDIS_BLOCKED_NONE; server.bpop_blocked_clients--; listAddNodeTail(server.unblocked_clients,c); }
list *listDup(list *orign) /*{{{*/ { list *cpy; listIter *iter; listNode *node; if((cpy = listCreate()) == NULL) { return NULL; } cpy->free = orign->free; cpy->dup = orign->dup; cpy->match = orign->match; iter = listGetIterator(orign, AL_START_HEAD); while((node = listNext(iter)) != NULL) { void *value; if(cpy->dup) { value = cpy->dup(node->value); if(value == NULL) { listRelease(cpy); listReleaseIterator(iter); return NULL; } } else { value = node->value; } //出错只有一种情况,就是malloc失败了,return NULL; if(listAddNodeTail(cpy, value) == NULL) { listRelease(cpy); listReleaseIterator(iter); return NULL; } } listReleaseIterator(iter); return cpy; }
/** *创建后台作业部分 只对aof部分 */ void bioCreateBackgroundJob(int type, void *arg1, void *arg2, void *arg3) { struct bio_job *job = zmalloc(sizeof(*job)); job->time = time(NULL); job->arg1 = arg1; job->arg2 = arg2; job->arg3 = arg3; pthread_mutex_lock(&bio_mutex[type]); listAddNodeTail(bio_jobs[type],job); bio_pending[type]++; /** pthread_cond_signal函数的作用是发送一个信号给另外一个正在处于阻塞等待状态的线程,使其脱离阻塞状态,继续执行.如果没有线程处在阻塞等待状态,pthread_cond_signal也会成功返回。 但使用pthread_cond_signal不会有“惊群现象”产生,他最多只给一个线程发信号。假如有多个线程正在阻塞等待着这个条件变量的话,那么是根据各等待线程优先级的高低确定哪个线程接收到信号开始继续执行。如果各线程优先级相同,则根据等待时间的长短来确定哪个线程获得信号。但无论如何一个pthread_cond_signal调用最多发信一次。 另外,互斥量的作用一般是用于对某个资源进行互斥性的存取,很多时候是用来保证操作是一个原子性的操作,是不可中断的。 */ pthread_cond_signal(&bio_condvar[type]); pthread_mutex_unlock(&bio_mutex[type]); }
/* monitor state changes for a socket */ static int aeApiAddEvent(aeEventLoop *eventLoop, int fd, int mask) { aeApiState *state = (aeApiState *)eventLoop->apidata; aeSockState *sockstate = aeGetSockState(state, fd); if (sockstate == NULL) { errno = WSAEINVAL; return -1; } if (mask & AE_READABLE) { sockstate->masks |= AE_READABLE; if ((sockstate->masks & CONNECT_PENDING) == 0) { if (sockstate->masks & LISTEN_SOCK) { /* actually a listen. Do not treat as read */ } else { if ((sockstate->masks & READ_QUEUED) == 0) { // queue up a 0 byte read aeWinReceiveDone(fd); } } } } if (mask & AE_WRITABLE) { sockstate->masks |= AE_WRITABLE; if ((sockstate->masks & CONNECT_PENDING) == 0) { // if no write active, then need to queue write ready if (sockstate->wreqs == 0) { asendreq *areq = (asendreq *)zmalloc(sizeof(asendreq)); memset(areq, 0, sizeof(asendreq)); if (PostQueuedCompletionStatus(state->iocp, 0, fd, &areq->ov) == 0) { errno = GetLastError(); zfree(areq); return -1; } sockstate->wreqs++; listAddNodeTail(&sockstate->wreqlist, areq); } } } return 0; }
int continue_http_session(cli *c) { if (c->argc < 2) return 1; // IGNORE Headers w/ no values if (!strcasecmp(c->argv[0]->ptr, "Connection:")) { if (!strcasecmp(c->argv[1]->ptr, "Keep-Alive")) c->http.ka = 1; if (!strcasecmp(c->argv[1]->ptr, "Close")) c->http.ka = 0; } if (!strcasecmp(c->argv[0]->ptr, "Content-Length:")) { c->http.req_clen = atoi(c->argv[1]->ptr); } sds hval = sdsdup(c->argv[1]->ptr); // DESTROY ME 084 for (int i = 2; i < c->argc; i++) { hval = sdscatlen(hval, " ", 1); //TODO this assumes single space hval = sdscatlen(hval, c->argv[i]->ptr, sdslen(c->argv[i]->ptr)); } two_sds *ss = init_two_sds(c->argv[0]->ptr, hval); sdsfree(hval); // DESTROYED 084 listAddNodeTail(c->http.req_hdr, ss); // Store REQ Headers in List return 1; }
void insert_list() { listNode *node; list *ll=found_list(&node); int *elem; if(ll){ elem=(int*)malloc(sizeof(int)); printf("输入要插入的元素:"); scanf("%d",elem); if((listAddNodeTail(ll,elem))!=NULL){ printf("插入成功\n"); }else{ printf("插入失败\n"); } }else{ printf("没有这个链表\n"); } }
static client createClient(char *cmd, size_t len) { int j; client c = zmalloc(sizeof(struct _client)); if (config.hostsocket == NULL) { c->context = redisConnectNonBlock(config.hostip,config.hostport); } else { c->context = redisConnectUnixNonBlock(config.hostsocket); } if (c->context->err) { fprintf(stderr,"Could not connect to Redis at "); if (config.hostsocket == NULL) fprintf(stderr,"%s:%d: %s\n",config.hostip,config.hostport,c->context->errstr); else fprintf(stderr,"%s: %s\n",config.hostsocket,c->context->errstr); exit(1); } /* Suppress hiredis cleanup of unused buffers for max speed. */ c->context->reader->maxbuf = 0; /* Queue N requests accordingly to the pipeline size. */ c->obuf = sdsempty(); for (j = 0; j < config.pipeline; j++) c->obuf = sdscatlen(c->obuf,cmd,len); c->randlen = 0; c->written = 0; c->pending = config.pipeline; /* Find substrings in the output buffer that need to be randomized. */ if (config.randomkeys) { char *p = c->obuf; while ((p = strstr(p,":rand:")) != NULL) { assert(c->randlen < (signed)(sizeof(c->randptr)/sizeof(char*))); c->randptr[c->randlen++] = p+6; p += 6; } } /* redisSetReplyObjectFunctions(c->context,NULL); */ aeCreateFileEvent(config.el,c->context->fd,AE_WRITABLE,writeHandler,c); listAddNodeTail(config.clients,c); config.liveclients++; return c; }