Exemple #1
0
void ltrimCommand(redisClient *c) {
    robj *o;
    long start, end, llen, j, ltrim, rtrim;
    list *list;
    listNode *ln;
    int slotnum = keyHashSlot(c->argv[1]->ptr, sdslen(c->argv[1]->ptr));

    if ((getLongFromObjectOrReply(c, c->argv[2], &start, NULL) != REDIS_OK) ||
        (getLongFromObjectOrReply(c, c->argv[3], &end, NULL) != REDIS_OK)) return;

    if ((o = lookupKeyWriteOrReply(c,c->argv[1],shared.ok,slotnum)) == NULL ||
        checkType(c,o,REDIS_LIST)) return;
    llen = listTypeLength(o);

    /* convert negative indexes */
    if (start < 0) start = llen+start;
    if (end < 0) end = llen+end;
    if (start < 0) start = 0;

    /* Invariant: start >= 0, so this test will be true when end < 0.
     * The range is empty when start > end or start >= length. */
    if (start > end || start >= llen) {
        /* Out of range start or start > end result in empty list */
        ltrim = llen;
        rtrim = 0;
    } else {
        if (end >= llen) end = llen-1;
        ltrim = start;
        rtrim = llen-end-1;
    }

    /* Remove list elements to perform the trim */
    if (o->encoding == REDIS_ENCODING_ZIPLIST) {
        o->ptr = ziplistDeleteRange(o->ptr,0,ltrim);
        o->ptr = ziplistDeleteRange(o->ptr,-rtrim,rtrim);
    } else if (o->encoding == REDIS_ENCODING_LINKEDLIST) {
        list = o->ptr;
        for (j = 0; j < ltrim; j++) {
            ln = listFirst(list);
            listDelNode(list,ln);
        }
        for (j = 0; j < rtrim; j++) {
            ln = listLast(list);
            listDelNode(list,ln);
        }
    } else {
        redisPanic("Unknown list encoding");
    }

    notifyKeyspaceEvent(REDIS_NOTIFY_LIST,"ltrim",c->argv[1],c->db->id);
    if (listTypeLength(o) == 0) {
        dbDelete(c->db,c->argv[1],slotnum);
        notifyKeyspaceEvent(REDIS_NOTIFY_GENERIC,"del",c->argv[1],c->db->id);
    }
    signalModifiedKey(c->db,c->argv[1],slotnum);
    server.dirty++;
    addReply(c,shared.ok);
}
Exemple #2
0
/* Push a new entry into the slow log.
 * This function will make sure to trim the slow log accordingly to the
 * configured max length. */
void slowlogPushEntryIfNeeded(robj **argv, int argc, long long duration) {
    if (server.slowlog_log_slower_than < 0) return; /* Slowlog disabled */
    if (duration >= server.slowlog_log_slower_than)
        listAddNodeHead(server.slowlog,slowlogCreateEntry(argv,argc,duration));

    /* Remove old entries if needed. */
    while (listLength(server.slowlog) > server.slowlog_max_len)
        listDelNode(server.slowlog,listLast(server.slowlog));
}
Exemple #3
0
felist *listAddLast(felist *root, felist *l) {
  if (root != NULL) {
    felist *tmp = listLast(root);
    tmp->next = l;
    l->prev = tmp;
    return root;
  }
  return l;
}
Exemple #4
0
/* Return the current size of the AOF rerwite buffer. */
unsigned long aofRewriteBufferSize(void) {
    listNode *ln = listLast(server.aof_rewrite_buf_blocks);
    aofrwblock *block = ln ? ln->value : NULL;

    if (block == NULL) return 0;
    unsigned long size =
        (listLength(server.aof_rewrite_buf_blocks)-1) * AOF_RW_BUF_BLOCK_SIZE;
    size += block->used;
    return size;
}
Exemple #5
0
void *IOThreadEntryPoint(void *arg) {
    iojob *j;
    listNode *ln;
    REDIS_NOTUSED(arg);

    pthread_detach(pthread_self());
    while(1) {
        /* Get a new job to process */
        lockThreadedIO();
        if (listLength(server.io_newjobs) == 0) {
            /* No new jobs in queue, exit. */
            redisLog(REDIS_DEBUG,"Thread %ld exiting, nothing to do",
                (long) pthread_self());
            server.io_active_threads--;
            unlockThreadedIO();
            return NULL;
        }
        ln = listFirst(server.io_newjobs);
        j = ln->value;
        listDelNode(server.io_newjobs,ln);
        /* Add the job in the processing queue */
        j->thread = pthread_self();
        listAddNodeTail(server.io_processing,j);
        ln = listLast(server.io_processing); /* We use ln later to remove it */
        unlockThreadedIO();
        redisLog(REDIS_DEBUG,"Thread %ld got a new job (type %d): %p about key '%s'",
            (long) pthread_self(), j->type, (void*)j, (char*)j->key->ptr);

        /* Process the Job */
        if (j->type == REDIS_IOJOB_LOAD) {
            vmpointer *vp = (vmpointer*)j->id;
            j->val = vmReadObjectFromSwap(j->page,vp->vtype);
        } else if (j->type == REDIS_IOJOB_PREPARE_SWAP) {
            j->pages = rdbSavedObjectPages(j->val);
        } else if (j->type == REDIS_IOJOB_DO_SWAP) {
            if (vmWriteObjectOnSwap(j->val,j->page) == REDIS_ERR)
                j->canceled = 1;
        }

        /* Done: insert the job into the processed queue */
        redisLog(REDIS_DEBUG,"Thread %ld completed the job: %p (key %s)",
            (long) pthread_self(), (void*)j, (char*)j->key->ptr);

        lockThreadedIO();
        listDelNode(server.io_processing,ln);
        listAddNodeTail(server.io_processed,j);
        unlockThreadedIO();

        /* Signal the main thread there is new stuff to process */
        redisAssert(write(server.io_ready_pipe_write,"x",1) == 1);
    }
    return NULL; /* never reached */
}
Exemple #6
0
felist *listCat(felist *l1, felist *l2) {
  felist *t;

  if (l1 == NULL) return l2;
  else if (l2 == NULL) return l1;
  else {
    t = listLast(l1);
    t->next = l2;
    l2->prev = t;
  }
  return l1;
}
Exemple #7
0
void ltrimCommand(redisClient *c) {
    robj *o;
    int start = atoi(c->argv[2]->ptr);
    int end = atoi(c->argv[3]->ptr);
    int llen;
    int j, ltrim, rtrim;
    list *list;
    listNode *ln;

    if ((o = lookupKeyWriteOrReply(c,c->argv[1],shared.ok)) == NULL ||
        checkType(c,o,REDIS_LIST)) return;
    llen = listTypeLength(o);

    /* convert negative indexes */
    if (start < 0) start = llen+start;
    if (end < 0) end = llen+end;
    if (start < 0) start = 0;

    /* Invariant: start >= 0, so this test will be true when end < 0.
     * The range is empty when start > end or start >= length. */
    if (start > end || start >= llen) {
        /* Out of range start or start > end result in empty list */
        ltrim = llen;
        rtrim = 0;
    } else {
        if (end >= llen) end = llen-1;
        ltrim = start;
        rtrim = llen-end-1;
    }

    /* Remove list elements to perform the trim */
    if (o->encoding == REDIS_ENCODING_ZIPLIST) {
        o->ptr = ziplistDeleteRange(o->ptr,0,ltrim);
        o->ptr = ziplistDeleteRange(o->ptr,-rtrim,rtrim);
    } else if (o->encoding == REDIS_ENCODING_LINKEDLIST) {
        list = o->ptr;
        for (j = 0; j < ltrim; j++) {
            ln = listFirst(list);
            listDelNode(list,ln);
        }
        for (j = 0; j < rtrim; j++) {
            ln = listLast(list);
            listDelNode(list,ln);
        }
    } else {
        redisPanic("Unknown list encoding");
    }
    if (listTypeLength(o) == 0) dbDelete(c->db,c->argv[1]);
    signalModifiedKey(c->db,c->argv[1]);
    server.dirty++;
    addReply(c,shared.ok);
}
Exemple #8
0
unsigned long aofRewriteBufferSize(void){
    /*return the contents size of current AOF rewrite buffer*/
    listNode *last;
    unsigned long lastused, size;

    if((last = listLast(server.aof_rewrite_buf_blocks)) == NULL){
         return 0;
    }
    lastused = (last->value)->used;
    size = (listLength(server.aof_rewrite_buf_blocks)-1)*AOF_RW_BUF_BLOCK_SIZE + lastused;

    return size;
}
void *listLastValue(list *l)
{
    listNode *node;
    
    if (l == NULL) {
        return NULL;
    }

    node = listLast(l);
    if (node == NULL) {
        return NULL;
    }

    return listNodeValue(node);
}
Exemple #10
0
/* Push a new entry into the slow log.
 *
 * 如果参数 duration 超过服务器设置的上限时间,
 * 那么将一个新条目以 FIFO 顺序推入到慢查询日志中。
 *
 * This function will make sure to trim the slow log accordingly to the
 * configured max length.
 *
 * 根据服务器设置的最大日志长度,可能会对日志进行截断(trim)
 */
void slowlogPushEntryIfNeeded(robj **argv, int argc, long long duration)
{

    // 慢查询功能未开启,直接返回
    if (server.slowlog_log_slower_than < 0) return; /* Slowlog disabled */

    // 如果执行时间超过服务器设置的上限,那么将命令添加到慢查询日志
    if (duration >= server.slowlog_log_slower_than)
        // 新日志添加到链表表头
        listAddNodeHead(server.slowlog,slowlogCreateEntry(argv,argc,duration));

    /* Remove old entries if needed. */
    // 如果日志数量过多,那么进行删除
    while (listLength(server.slowlog) > server.slowlog_max_len)
        listDelNode(server.slowlog,listLast(server.slowlog));
}
Exemple #11
0
void aofRewriteBufferAppend(unsigned char *s, unsigned long len){
    /*add string s at the end of AOF buffer, assign a new block if needed*/
    listNode *last;
    aofrwblock *block;
    unsigned int clen;
    int counts;

    last = listLast(server.aof_rewrite_buf_blocks);
    if(last){
        block = last->value;
    }
    else{
        block = NULL;
    }

    while(len > 0){
        if(block){
            clen = (block->free < len)? block->free: len;
            memcpy(block->buf, s, clen);
            block->free -= clen;
            block->used += clen;
            s += clen;
            len -= clen;
        }
        if(len){
            block = zmalloc(sizeof(aofrwblock));
            block->free = AOF_RW_BUF_BLOCK_SIZE;
            block->used = 0;
            listAddNodeTail(server.aof_rewrite_buf_blocks, block);
            /*NOTICE when node number is coming to n*10, WARNING when n*100*/
            counts = listLength(server.aof_rewrite_buf_blocks);
            if(((counts+1) % 100) == 0){
                xredisLog(XREDIS_WARNING, "Background AOF buffer size: %lu MB", aofRewriteBufferSize()/(1024*1024));
            }
            else if(((counts+1)%10) == 0){
                xredisLog(XREDIS_NOTICE, "Background AOF buffer size: %lu MB", aofRewriteBufferSize()/(1024*1024));
            }
        }
    }
}
Exemple #12
0
/* Append data to the AOF rewrite buffer, allocating new blocks if needed. */
void aofRewriteBufferAppend(unsigned char *s, unsigned long len) {
    listNode *ln = listLast(server.aof_rewrite_buf_blocks);
    aofrwblock *block = ln ? ln->value : NULL;

    while(len) {
        /* If we already got at least an allocated block, try appending
         * at least some piece into it. */
        if (block) {
            unsigned long thislen = (block->free < len) ? block->free : len;
            if (thislen) {  /* The current block is not already full. */
                memcpy(block->buf+block->used, s, thislen);
                block->used += thislen;
                block->free -= thislen;
                s += thislen;
                len -= thislen;
            }
        }

        if (len) { /* First block to allocate, or need another block. */
            int numblocks;

            block = zmalloc(sizeof(*block));
            block->free = AOF_RW_BUF_BLOCK_SIZE;
            block->used = 0;
            listAddNodeTail(server.aof_rewrite_buf_blocks,block);

            /* Log every time we cross more 10 or 100 blocks, respectively
             * as a notice or warning. */
            numblocks = listLength(server.aof_rewrite_buf_blocks);
            if (((numblocks+1) % 10) == 0) {
                int level = ((numblocks+1) % 100) == 0 ? REDIS_WARNING :
                                                         REDIS_NOTICE;
                redisLog(level,"Background AOF buffer size: %lu MB",
                    aofRewriteBufferSize()/(1024*1024));
            }
        }
    }
}
struct mbuf *
msg_ensure_mbuf(struct msg *msg, size_t len)
{
    listNode *node;
    mbuf_base *mb = msg->mb;
    struct mbuf *mbuf;

    node = listLast(msg->data);
    
    if (node == NULL ||
        mbuf_size(listNodeValue(node)) < len) {
        mbuf = mbuf_get(mb);
        if (mbuf == NULL) {
            return NULL;
        }

        listAddNodeTail(msg->data, mbuf);
    } else {
        mbuf = listNodeValue(node);
    }

    return mbuf;
}
Exemple #14
0
robj *listTypePop(robj *subject, int where) {
    robj *value = NULL;
    if (subject->encoding == REDIS_ENCODING_ZIPLIST) {
        unsigned char *p;
        unsigned char *vstr;
        unsigned int vlen;
        long long vlong;
        int pos = (where == REDIS_HEAD) ? 0 : -1;
        p = ziplistIndex(subject->ptr,pos);
        if (ziplistGet(p,&vstr,&vlen,&vlong)) {
            if (vstr) {
                value = createStringObject((char*)vstr,vlen);
            } else {
                value = createStringObjectFromLongLong(vlong);
            }
            /* We only need to delete an element when it exists */
            subject->ptr = ziplistDelete(subject->ptr,&p);
        }
    } else if (subject->encoding == REDIS_ENCODING_LINKEDLIST) {
        list *list = subject->ptr;
        listNode *ln;
        if (where == REDIS_HEAD) {
            ln = listFirst(list);
        } else {
            ln = listLast(list);
        }
        if (ln != NULL) {
            value = listNodeValue(ln);
            incrRefCount(value);
            listDelNode(list,ln);
        }
    } else {
        redisPanic("Unknown list encoding");
    }
    return value;
}
Exemple #15
0
int main(int argc,char **argv) {
	list_t list;
	int index;
	char *arg;
	int elements;
	/* Initialize our list. */
	listInitialize(&list);
	/* Fill our list with all command line arguments given, but skip the
	 * first argument since that's our needle (see below -> listSearch()). */
	for(index=2;index<argc;index++) {
		/* Append the argument to our list. */
		if(listAppend(&list,(void *)argv[index])!=listRtrnOk) {
			fprintf(stderr,"Can't create item!\n");
			break;
		}
		/* Advance to this next position. By default listAppend() does not
		 * advance our current pointer to the appended element. */
		listNext(&list);
	}
	/* Print all our arguments from the first to the last. */
	printf("First to last:\n");
	/* Does any argument exist? */
	if((arg=(char *)listFirst(&list))!=NULL) {
		/* Yes, we print it and... */
		do {
			printf("[%s]\n",arg);
			/* ...advance to the next argument, untill none left. */
		} while((arg=(char *)listNext(&list))!=NULL);
	} else {
		printf("empty list\n");
	}
	/* Print all our arguments from the last to the first. */
	printf("Last to first:\n");
	/* Does any argument exist? */
	if((arg=(char *)listLast(&list))!=NULL) {
		/* Yes, we print it and... */
		do {
			printf("[%s]\n",arg);
			/* ...advance to the next argument, untill none left. */
		} while((arg=(char *)listPrevious(&list))!=NULL);
	} else {
		printf("empty list\n");
	}
	/* If there do exist enough arguments... */
	if(argc>=2) {
		/* ...search for the first one given... */
		arg=listSearch(&list,cmpr,(void *)argv[1]);
		/* ...and tell if it's found. */
		printf("searching for [%s]... %sfound\n",argv[1],arg!=NULL?"":"not ");
	}
	/* Randomly remove half of the arguments. */
	srandom(getpid());
	for(elements=listElements(&list)/2;elements>0;elements--) {
		int element=(random()%(argc-2))+2;
		arg=listSearch(&list,cmpr,(void *)argv[element]);
		printf("Removing [%s]... ",argv[element]);
		if(arg!=NULL) {
			listRemove(&list,NULL);
			printf("ok\n");
		} else {
			printf("not in the list!\n");
		}
	}
	/* Print all our arguments from the first to the last. */
	printf("First to last:\n");
	/* Does any argument exist? */
	if((arg=(char *)listFirst(&list))!=NULL) {
		/* Yes, we print it and... */
		do {
			printf("[%s]\n",arg);
			/* ...advance to the next argument, untill none left. */
		} while((arg=(char *)listNext(&list))!=NULL);
	} else {
		printf("empty list\n");
	}
	/* Print all our arguments from the last to the first. */
	printf("Last to first:\n");
	/* Does any argument exist? */
	if((arg=(char *)listLast(&list))!=NULL) {
		/* Yes, we print it and... */
		do {
			printf("[%s]\n",arg);
			/* ...advance to the next argument, untill none left. */
		} while((arg=(char *)listPrevious(&list))!=NULL);
	} else {
		printf("empty list\n");
	}

	/* Destroy the list and all its elements. */
	listDestroy(&list,garbageCollect);
	return(0);
}
Exemple #16
0
/* Remove all the entries from the current slow log. */
void slowlogReset(void) {
    while (listLength(server.slowlog) > 0)
        listDelNode(server.slowlog,listLast(server.slowlog));
}
Exemple #17
0
    if (c->fd <= 0) return REDIS_ERR;
    if (c->bufpos == 0 && 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 REDIS_ERR;
    return REDIS_OK;
}

/* Create a duplicate of the last object in the reply list when
 * it is not exclusively owned by the reply list. */
robj *dupLastObjectIfNeeded(list *reply) {
    robj *new, *cur;
    listNode *ln;
    redisAssert(listLength(reply) > 0);
    ln = listLast(reply);
    cur = listNodeValue(ln);
    if (cur->refcount > 1) {
        new = dupStringObject(cur);
        decrRefCount(cur);
        listNodeValue(ln) = new;
    }
    return listNodeValue(ln);
}

/* -----------------------------------------------------------------------------
 * Low level functions to add more data to output buffers.
 * -------------------------------------------------------------------------- */

int _addReplyToBuffer(redisClient *c, char *s, size_t len) {
    size_t available = sizeof(c->buf)-c->bufpos;
Exemple #18
0
int main() {
   TTable table;
   tableInit(&table);

   printf("\nTabulka by mela byt prazdna: \n");
   tablePrintOrder(table);
   printf("\n----------------------------\n");

   tableInsertFunction(&table, strCreateString("func1"));
   functionInsertVar(table.lastAddedFunc, strCreateString("var1func1"));
   functionInsertVar(table.lastAddedFunc, strCreateString("var2func1"));
   functionInsertVar(table.lastAddedFunc, strCreateString("var3func1"));

   printf("\nJedna funkce: \n");
   tablePrintOrder(table);
   printf("\n----------------------------\n");

   tableInsertFunction(&table, strCreateString("func2"));
   functionInsertVar(table.lastAddedFunc, strCreateString("var1func2"));
   functionInsertVar(table.lastAddedFunc, strCreateString("var2func2"));
   functionInsertVar(table.lastAddedFunc, strCreateString("var3func2"));

   printf("\nDve funkce: \n");
   tablePrintOrder(table);
   printf("\n----------------------------\n");

   tableInsertFunction(&table, strCreateString("func3"));
   functionInsertVar(table.lastAddedFunc, strCreateString("var1func3"));
   functionInsertVar(table.lastAddedFunc, strCreateString("var2func3"));
   functionInsertVar(table.lastAddedFunc, strCreateString("var3func3"));

   printf("\nVsechny: \n");
   tablePrintOrder(table);
   printf("\n----------------------------\n");

   // test heldani
   {

      TFunction *fceSearch;

      printf("\nObsahuje tabulka funkci %s? \t", "func1");
      fceSearch = tableSearchFunction(&table, strCreateString("func1"));
      if(fceSearch != NULL) {
         printf("ANO\n");
         printf("   Obsahuje funkce promenou %s?\t", "var1func1");
         if(functionSearchVar(fceSearch, strCreateString("var1func1")) != NULL)
            printf("ANO");
         else
            printf("NE");
      } else
         printf("NE\n");

      printf("\nObsahuje tabulka funkci %s? \t", "funcX");
      fceSearch = tableSearchFunction(&table, strCreateString("funcX"));
      if(fceSearch != NULL) {
         printf("ANO\n");
         printf("   Obsahuje funkce promenou %s?\t", "var1func1");
         if(functionSearchVar(fceSearch, strCreateString("var1func1")) != NULL)
            printf("ANO");
         else
            printf("NE");
      } else
         printf("NE\n");

      printf("\n----------------------------\n");
   }


   // test zásobníku:
   printf("TEST ZASOBNIKU:\n");
   printf("----------------------------\n");

   TStack s;
   stackInit(&s);

   prazdnyStack(s);

   TFunction *fce = tableSearchFunction(&table, strCreateString("func2"));
   TVar *id = functionSearchVar(fce, strCreateString("var1func2"));
   stackPush(&s, (void*)id);

   prazdnyStack(s);
   tiskniStack(&s);

   id = functionSearchVar(fce, strCreateString("var2func2"));
   stackPush(&s, (void*)id);
   tiskniStack(&s);
   id = functionSearchVar(fce, strCreateString("var3func2"));
   stackPush(&s, (void*)id);
   tiskniStack(&s);
   id = functionSearchVar(fce, strCreateString("var1func2"));
   stackPush(&s, (void*)id);
   tiskniStack(&s);


   TVar *data = (TVar*)stackTopPop(&s);
   if (data != NULL)  printf("Vybráno ze zásobníku: %s\n",data->name);
   else printf("Ukazatel je nulový! \n");
   prazdnyStack(s);

   data = (TVar*)stackTopPop(&s);
   if (data != NULL)  printf("Vybráno ze zásobníku: %s\n",data->name);
   else printf("Ukazatel je nulový! \n");
   prazdnyStack(s);

   data = (TVar*)stackTopPop(&s);
   if (data != NULL)  printf("Vybráno ze zásobníku: %s\n",data->name);
   else printf("Ukazatel je nulový! \n");
   prazdnyStack(s);

   tiskniStack(&s);
   stackDelete   (&s);
   prazdnyStack(s);
   tiskniStack(&s);

   data = (TVar*)stackTopPop(&s);
   if (data != NULL)  printf("Vybráno ze zásobníku: %s\n",data->name);
   else printf("Ukazatel je nulový! \n");
   printf("----------------------------\n");

   // test seznamu:
   printf("TEST SEZNAMU:\n");
   printf("----------------------------\n");


   TList L;
   listInit (&L);
   id = functionSearchVar(fce, strCreateString("var1func2"));
   TLItem *uk2 = listGetActive (&L);
   listSetActive(&L, uk2);
   aktivniList(L);

   listInsertLast(&L, id);
   tiskniList(&L);

   void *uk4 = listCopyLast(&L);
   printf("Zkopírováno:  %s\n",((TVar*)uk4)->name);


   aktivniList(L);
   listFirst(&L);
   tiskniList(&L);

   listLast(&L);
   tiskniList(&L);

   id = functionSearchVar(fce, strCreateString("var2func2"));
   listPostInsert(&L, id);
   tiskniList(&L);

   id = functionSearchVar(fce, strCreateString("var3func2"));
   listInsertLast(&L, id);
   tiskniList(&L);


   id = functionSearchVar(fce, strCreateString("var1func2"));
   listInsertLast(&L, id);
   tiskniList(&L);

   listFirst(&L);
   listSucc(&L);
   TLItem *uk = listGetActive (&L);
   tiskniList(&L);

   listLast(&L);
   tiskniList(&L);

   listSetActive(&L, uk);
   tiskniList(&L);

   aktivniList(L);
   listDeleteFirst(&L);
   tiskniList(&L);

   void *uk3 = listCopyLast(&L);
   printf("Zkopírováno:  %s\n",((TVar*)uk3)->name);
   listSucc(&L);
   tiskniList(&L);

   listActualize(&L, uk3);
   tiskniList(&L);

   listDispose (&L);
   printf("----------------------------\n");
   // konec testu seznamu

   printf("\nSmazu: \n");
   tableClear(&table);
   tablePrintOrder(table);
   printf("\n----------------------------\n");
}