Exemplo n.º 1
0
/* get data for socket / fd being monitored. Create if not found*/
aeSockState *aeGetSockState(void *apistate, int fd) {
    int sindex;
    listNode *node;
    list *socklist;
    aeSockState *sockState;
    if (apistate == NULL) return NULL;

    sindex = aeSocketIndex(fd);
    socklist = &(((aeApiState *)apistate)->lookup[sindex]);
    node = listFirst(socklist);
    while (node != NULL) {
        sockState = (aeSockState *)listNodeValue(node);
        if (sockState->fd == fd) {
            return sockState;
        }
        node = listNextNode(node);
    }
    // not found. Do lazy create of sockState.
    sockState = (aeSockState *) zmalloc(sizeof(aeSockState));
    if (sockState != NULL) {
        sockState->fd = fd;
        sockState->masks = 0;
        sockState->wreqs = 0;
        sockState->reqs = NULL;
        memset(&sockState->wreqlist, 0, sizeof(sockState->wreqlist));
        memset(&sockState->remoteAddress, 0, sizeof(sockState->remoteAddress));

        if (listAddNodeHead(socklist, sockState) != NULL) {
            return sockState;
        } else {
            zfree(sockState);
        }
    }
    return NULL;
}
Exemplo n.º 2
0
/* put object in list if deletes are deferred.
 * return 1 if deferred, 0 otherwise */
int deferFreeObject(void *obj) {
    if (deferObjDelete != NULL && server.isBackgroundSaving == 1) {
        listAddNodeHead(deferObjDelete, obj);
        return 1;
    }
    return 0;
}
Exemplo n.º 3
0
/* delete data for socket / fd being monitored
   or move to the closing queue if operations are pending.
   Return 1 if deleted or not found, 0 if pending*/
void aeDelSockState(void *apistate, aeSockState *sockState) {
    int sindex;
    list *socklist;

    if (apistate == NULL) return;

    if (sockState->wreqs == 0 &&
            (sockState->masks & (READ_QUEUED | CONNECT_PENDING | SOCKET_ATTACHED | CLOSE_PENDING)) == 0) {
        // see if in active list
        sindex = aeSocketIndex(sockState->fd);
        socklist = &(((aeApiState *)apistate)->lookup[sindex]);
        if (removeMatchFromList(socklist, sockState) == 1) {
            zfree(sockState);
            return;
        }
        // try closing list
        socklist = &(((aeApiState *)apistate)->closing);
        if (removeMatchFromList(socklist, sockState) == 1) {
            zfree(sockState);
            return;
        }
    } else {
        // not safe to delete. Move to closing
        sindex = aeSocketIndex(sockState->fd);
        socklist = &(((aeApiState *)apistate)->lookup[sindex]);
        if (removeMatchFromList(socklist, sockState) == 1) {
            // removed from active list. add to closing list
            socklist = &(((aeApiState *)apistate)->closing);
            listAddNodeHead(socklist, sockState);
        }
    }
}
Exemplo n.º 4
0
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);
}
Exemplo n.º 5
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));
}
Exemplo n.º 6
0
static void decrRefCount(void *obj) {
    robj *o = obj;

    /* Object is a key of a swapped out value, or in the process of being
     * loaded. */
    if (server.vm_enabled &&
        (o->storage == REDIS_VM_SWAPPED || o->storage == REDIS_VM_LOADING))
    {
        if (o->storage == REDIS_VM_SWAPPED || o->storage == REDIS_VM_LOADING) {
            redisAssert(o->refcount == 1);
        }
        if (o->storage == REDIS_VM_LOADING) vmCancelThreadedIOJob(obj);
        redisAssert(o->type == REDIS_STRING);
        freeStringObject(o);
        vmMarkPagesFree(o->vm.page,o->vm.usedpages);
        pthread_mutex_lock(&server.obj_freelist_mutex);
        if (listLength(server.objfreelist) > REDIS_OBJFREELIST_MAX ||
            !listAddNodeHead(server.objfreelist,o))
            zfree(o);
        pthread_mutex_unlock(&server.obj_freelist_mutex);
        server.vm_stats_swapped_objects--;
        return;
    }
    /* Object is in memory, or in the process of being swapped out. */
    if (--(o->refcount) == 0) {
        if (server.vm_enabled && o->storage == REDIS_VM_SWAPPING)
            vmCancelThreadedIOJob(obj);
        switch(o->type) {
        case REDIS_STRING: freeStringObject(o); break;
        case REDIS_LIST: freeListObject(o); break;
        case REDIS_SET: freeSetObject(o); break;
        case REDIS_ZSET: freeZsetObject(o); break;
        case REDIS_HASH: freeHashObject(o); break;
        default: redisAssert(0); break;
        }
        if (server.vm_enabled) pthread_mutex_lock(&server.obj_freelist_mutex);
        if (listLength(server.objfreelist) > REDIS_OBJFREELIST_MAX ||
            !listAddNodeHead(server.objfreelist,o))
            zfree(o);
        if (server.vm_enabled) pthread_mutex_unlock(&server.obj_freelist_mutex);
    }
}
Exemplo n.º 7
0
pList *listInsertNode(pList *list, int direction, void *value) {
	if (list == NULL) return NULL;
	unsigned int mid = list->len/2;
	if (direction < mid) {
		if (direction < 0) return listAddNodeHead(list, value);
		
	}
	else {
		
	}
}
Exemplo n.º 8
0
int main()
{
    list * ls = listCreate();
    listIter *iter;
    listNode *node;

    char val1[] = "value1";
    char val2[] = "value2";
    char val3[] = "value3";

    listAddNodeHead(ls, val1);
    listAddNodeHead(ls, val2);
    listAddNodeHead(ls, val3);
    iter = listGetIterator(ls, AL_START_HEAD);

    while((node = listNext(iter)) != NULL) {
        printf("value = %s\n", (char*)node->value);
    }
    listReleaseIterator(iter);
	return 0;
}
Exemplo n.º 9
0
/* serperated by comma */
int initUserList(list *l, char *s) {
    ASSERT(l && s && (strlen(s) > 0));

    l->match = userMatch;
    char *p1 = NULL;
    char *head = s;
    int i = 0;

    while (NULL != (p1 = strchr(head, TOKEN))) {
        p1[0] = '\0'; 
        dump(L_DEBUG, "user:%s", head);
        listAddNodeHead(l, head);
        head = p1 + 1;
        i++;
    }

    dump(L_DEBUG, "user:%s", head);
    listAddNodeHead(l, head);
    i++;

    return i;
}
Exemplo n.º 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));
}
Exemplo n.º 11
0
void decrRefCount(void *obj) {
    robj *o = obj;

    /* Object is a swapped out value, or in the process of being loaded. */
    if (server.vm_enabled &&
        (o->storage == REDIS_VM_SWAPPED || o->storage == REDIS_VM_LOADING))
    {
        vmpointer *vp = obj;
        if (o->storage == REDIS_VM_LOADING) vmCancelThreadedIOJob(o);
        vmMarkPagesFree(vp->page,vp->usedpages);
        server.vm_stats_swapped_objects--;
        zfree(vp);
        return;
    }

    if (o->refcount <= 0) redisPanic("decrRefCount against refcount <= 0");
    /* Object is in memory, or in the process of being swapped out.
     *
     * If the object is being swapped out, abort the operation on
     * decrRefCount even if the refcount does not drop to 0: the object
     * is referenced at least two times, as value of the key AND as
     * job->val in the iojob. So if we don't invalidate the iojob, when it is
     * done but the relevant key was removed in the meantime, the
     * complete jobs handler will not find the key about the job and the
     * assert will fail. */
    if (server.vm_enabled && o->storage == REDIS_VM_SWAPPING)
        vmCancelThreadedIOJob(o);
    if (--(o->refcount) == 0) {
        switch(o->type) {
        case REDIS_STRING: freeStringObject(o); break;
        case REDIS_LIST: freeListObject(o); break;
        case REDIS_SET: freeSetObject(o); break;
        case REDIS_ZSET: freeZsetObject(o); break;
        case REDIS_HASH: freeHashObject(o); break;
        default: redisPanic("Unknown object type"); break;
        }
        o->ptr = NULL; /* defensive programming. We'll see NULL in traces. */
        if (server.vm_enabled) pthread_mutex_lock(&server.obj_freelist_mutex);
        if (listLength(server.objfreelist) > REDIS_OBJFREELIST_MAX ||
            !listAddNodeHead(server.objfreelist,o))
            zfree(o);
        if (server.vm_enabled) pthread_mutex_unlock(&server.obj_freelist_mutex);
    }
}
Exemplo n.º 12
0
/*
 * prepend small(small than a mbuf) content into msg
 */
int
msg_prepend(struct msg *msg, uint8_t *pos, size_t n)
{
    mbuf_base *mb = msg->mb;
    struct mbuf *mbuf;

    mbuf = mbuf_get(mb);
    if (mbuf == NULL) {
        return RMT_ENOMEM;
    }

    ASSERT(n <= mbuf_size(mbuf));

    mbuf_copy(mbuf, pos, n);
    msg->mlen += (uint32_t)n;

    listAddNodeHead(msg->data, mbuf);

    return RMT_OK;
}
Exemplo n.º 13
0
static bool fts_index_add(fts_t *fts, fts_doc_t *doc) {
    int i, len, nonstopwords;
    sds *terms;

    terms = sds_tokenize(doc->doc->ptr, &len, &nonstopwords);
    if (!terms) return false;
    for (i = 0; i < len; i++) {
        sds term = terms[i];
        list *idx;
        listNode *ln;

        if (sdslen(term) == 0) {
            sdsfree(term);
            continue;
        }

        idx = dict_get(fts->index, term);
        if (!idx) {
            idx = index_list_create();
            dict_set(fts->index, term, idx);
        }
        ln = listSearchKey(idx, doc);
        if (ln) {
            index_item_t *idi = ln->value;
            idi->tf++;
        } else {
            index_item_t *idi = rr_malloc(sizeof(*idi));
            idi->doc = doc;
            idi->tf = 1;
            listAddNodeHead(idx, idi);
        }
        sdsfree(term);
    }
    rr_free(terms);
    doc->len = nonstopwords;
    fts->len += doc->len;
    return true;
}
Exemplo n.º 14
0
void listTypePush(robj *subject, robj *value, int where) {
    /* Check if we need to convert the ziplist */
    listTypeTryConversion(subject,value);
    if (subject->encoding == REDIS_ENCODING_ZIPLIST &&
        ziplistLen(subject->ptr) >= server.list_max_ziplist_entries)
            listTypeConvert(subject,REDIS_ENCODING_LINKEDLIST);

    if (subject->encoding == REDIS_ENCODING_ZIPLIST) {
        int pos = (where == REDIS_HEAD) ? ZIPLIST_HEAD : ZIPLIST_TAIL;
        value = getDecodedObject(value);
        subject->ptr = ziplistPush(subject->ptr,value->ptr,sdslen(value->ptr),pos);
        decrRefCount(value);
    } else if (subject->encoding == REDIS_ENCODING_LINKEDLIST) {
        if (where == REDIS_HEAD) {
            listAddNodeHead(subject->ptr,value);
        } else {
            listAddNodeTail(subject->ptr,value);
        }
        incrRefCount(value);
    } else {
        redisPanic("Unknown list encoding");
    }
}
Exemplo n.º 15
0
/*
 * prepend small(small than a mbuf) content into msg
 */
int
msg_prepend_format(struct msg *msg, const char *fmt, ...)
{
    mbuf_base *mb = msg->mb;
    struct mbuf *mbuf;
    int32_t n;
    va_list args;

    mbuf = mbuf_get(mb);
    if (mbuf == NULL) {
        return RMT_ENOMEM;
    }

    va_start(args, fmt);
    n = rmt_vscnprintf(mbuf->last, mbuf_size(mbuf), fmt, args);
    va_end(args);

    mbuf->last += n;
    msg->mlen += (uint32_t)n;

    listAddNodeHead(msg->data, mbuf);
    
    return RMT_OK;
}
Exemplo n.º 16
0
int 
main(int argc, char *argv[])
{
    unsigned char *zl, *p;
    unsigned char *entry;
    unsigned int elen;
    long long value;

    /* If an argument is given, use it as the random seed. */
    if (argc == 2)
        srand(atoi(argv[1]));

    zl = createIntList();
    ziplistRepr(zl);

    zl = createList();
    ziplistRepr(zl);

    pop(zl,ZIPLIST_TAIL);
    ziplistRepr(zl);

    pop(zl,ZIPLIST_HEAD);
    ziplistRepr(zl);

    pop(zl,ZIPLIST_TAIL);
    ziplistRepr(zl);

    pop(zl,ZIPLIST_TAIL);
    ziplistRepr(zl);

    printf("Get element at index 3:\n");
    {
        zl = createList();
        p = ziplistIndex(zl, 3);
        if (!ziplistGet(p, &entry, &elen, &value)) {
            printf("ERROR: Could not access index 3\n");
            return 1;
        }
        if (entry) {
            if (elen && fwrite(entry,elen,1,stdout) == 0) perror("fwrite");
            printf("\n");
        } else {
            printf("%lld\n", value);
        }
        printf("\n");
    }

    printf("Get element at index 4 (out of range):\n");
    {
        zl = createList();
        p = ziplistIndex(zl, 4);
        if (p == NULL) {
            printf("No entry\n");
        } else {
            printf("ERROR: Out of range index should return NULL, returned offset: %ld\n", p-zl);
            return 1;
        }
        printf("\n");
    }

    printf("Get element at index -1 (last element):\n");
    {
        zl = createList();
        p = ziplistIndex(zl, -1);
        if (!ziplistGet(p, &entry, &elen, &value)) {
            printf("ERROR: Could not access index -1\n");
            return 1;
        }
        if (entry) {
            if (elen && fwrite(entry,elen,1,stdout) == 0) perror("fwrite");
            printf("\n");
        } else {
            printf("%lld\n", value);
        }
        printf("\n");
    }

    printf("Get element at index -4 (first element):\n");
    {
        zl = createList();
        p = ziplistIndex(zl, -4);
        if (!ziplistGet(p, &entry, &elen, &value)) {
            printf("ERROR: Could not access index -4\n");
            return 1;
        }
        if (entry) {
            if (elen && fwrite(entry,elen,1,stdout) == 0) perror("fwrite");
            printf("\n");
        } else {
            printf("%lld\n", value);
        }
        printf("\n");
    }

    printf("Get element at index -5 (reverse out of range):\n");
    {
        zl = createList();
        p = ziplistIndex(zl, -5);
        if (p == NULL) {
            printf("No entry\n");
        } else {
            printf("ERROR: Out of range index should return NULL, returned offset: %ld\n", p-zl);
            return 1;
        }
        printf("\n");
    }

    printf("Iterate list from 0 to end:\n");
    {
        zl = createList();
        p = ziplistIndex(zl, 0);
        while (ziplistGet(p, &entry, &elen, &value)) {
            printf("Entry: ");
            if (entry) {
                if (elen && fwrite(entry,elen,1,stdout) == 0) perror("fwrite");
            } else {
                printf("%lld", value);
            }
            p = ziplistNext(zl,p);
            printf("\n");
        }
        printf("\n");
    }

    printf("Iterate list from 1 to end:\n");
    {
        zl = createList();
        p = ziplistIndex(zl, 1);
        while (ziplistGet(p, &entry, &elen, &value)) {
            printf("Entry: ");
            if (entry) {
                if (elen && fwrite(entry,elen,1,stdout) == 0) perror("fwrite");
            } else {
                printf("%lld", value);
            }
            p = ziplistNext(zl,p);
            printf("\n");
        }
        printf("\n");
    }

    printf("Iterate list from 2 to end:\n");
    {
        zl = createList();
        p = ziplistIndex(zl, 2);
        while (ziplistGet(p, &entry, &elen, &value)) {
            printf("Entry: ");
            if (entry) {
                if (elen && fwrite(entry,elen,1,stdout) == 0) perror("fwrite");
            } else {
                printf("%lld", value);
            }
            p = ziplistNext(zl,p);
            printf("\n");
        }
        printf("\n");
    }

    printf("Iterate starting out of range:\n");
    {
        zl = createList();
        p = ziplistIndex(zl, 4);
        if (!ziplistGet(p, &entry, &elen, &value)) {
            printf("No entry\n");
        } else {
            printf("ERROR\n");
        }
        printf("\n");
    }

    printf("Iterate from back to front:\n");
    {
        zl = createList();
        p = ziplistIndex(zl, -1);
        while (ziplistGet(p, &entry, &elen, &value)) {
            printf("Entry: ");
            if (entry) {
                if (elen && fwrite(entry,elen,1,stdout) == 0) perror("fwrite");
            } else {
                printf("%lld", value);
            }
            p = ziplistPrev(zl,p);
            printf("\n");
        }
        printf("\n");
    }

    printf("Iterate from back to front, deleting all items:\n");
    {
        zl = createList();
        p = ziplistIndex(zl, -1);
        while (ziplistGet(p, &entry, &elen, &value)) {
            printf("Entry: ");
            if (entry) {
                if (elen && fwrite(entry,elen,1,stdout) == 0) perror("fwrite");
            } else {
                printf("%lld", value);
            }
            zl = ziplistDelete(zl,&p);
            p = ziplistPrev(zl,p);
            printf("\n");
        }
        printf("\n");
    }

    printf("Delete inclusive range 0,0:\n");
    {
        zl = createList();
        zl = ziplistDeleteRange(zl, 0, 1);
        ziplistRepr(zl);
    }

    printf("Delete inclusive range 0,1:\n");
    {
        zl = createList();
        zl = ziplistDeleteRange(zl, 0, 2);
        ziplistRepr(zl);
    }

    printf("Delete inclusive range 1,2:\n");
    {
        zl = createList();
        zl = ziplistDeleteRange(zl, 1, 2);
        ziplistRepr(zl);
    }

    printf("Delete with start index out of range:\n");
    {
        zl = createList();
        zl = ziplistDeleteRange(zl, 5, 1);
        ziplistRepr(zl);
    }

    printf("Delete with num overflow:\n");
    {
        zl = createList();
        zl = ziplistDeleteRange(zl, 1, 5);
        ziplistRepr(zl);
    }

    printf("Delete foo while iterating:\n");
    {
        zl = createList();
        p = ziplistIndex(zl,0);
        while (ziplistGet(p,&entry,&elen,&value)) {
            if (entry && strncmp("foo",(char*)entry,elen) == 0) {
                printf("Delete foo\n");
                zl = ziplistDelete(zl,&p);
            } else {
                printf("Entry: ");
                if (entry) {
                    if (elen && fwrite(entry,elen,1,stdout) == 0)
                        perror("fwrite");
                } else {
                    printf("%lld",value);
                }
                p = ziplistNext(zl,p);
                printf("\n");
            }
        }
        printf("\n");
        ziplistRepr(zl);
    }

    printf("Regression test for >255 byte strings:\n");
    {
        char v1[257],v2[257];
        memset(v1,'x',256);
        memset(v2,'y',256);
        zl = ziplistNew();
        zl = ziplistPush(zl,(unsigned char*)v1,strlen(v1),ZIPLIST_TAIL);
        zl = ziplistPush(zl,(unsigned char*)v2,strlen(v2),ZIPLIST_TAIL);

        /* Pop values again and compare their value. */
        p = ziplistIndex(zl,0);
        assert(ziplistGet(p,&entry,&elen,&value));
        assert(strncmp(v1,(char*)entry,elen) == 0);
        p = ziplistIndex(zl,1);
        assert(ziplistGet(p,&entry,&elen,&value));
        assert(strncmp(v2,(char*)entry,elen) == 0);
        printf("SUCCESS\n\n");
    }

    printf("Regression test deleting next to last entries:\n");
    {
        char v[3][257];
        zlentry e[3];
        int i;

        for (i = 0; i < (sizeof(v)/sizeof(v[0])); i++) {
            memset(v[i], 'a' + i, sizeof(v[0]));
        }

        v[0][256] = '\0';
        v[1][  1] = '\0';
        v[2][256] = '\0';

        zl = ziplistNew();
        for (i = 0; i < (sizeof(v)/sizeof(v[0])); i++) {
            zl = ziplistPush(zl, (unsigned char *) v[i], strlen(v[i]), ZIPLIST_TAIL);
        }

        verify(zl, e);

        assert(e[0].prevrawlensize == 1);
        assert(e[1].prevrawlensize == 5);
        assert(e[2].prevrawlensize == 1);

        /* Deleting entry 1 will increase `prevrawlensize` for entry 2 */
        unsigned char *p = e[1].p;
        zl = ziplistDelete(zl, &p);

        verify(zl, e);

        assert(e[0].prevrawlensize == 1);
        assert(e[1].prevrawlensize == 5);

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

    printf("Create long list and check indices:\n");
    {
        zl = ziplistNew();
        char buf[32];
        int i,len;
        for (i = 0; i < 1000; i++) {
            len = sprintf(buf,"%d",i);
            zl = ziplistPush(zl,(unsigned char*)buf,len,ZIPLIST_TAIL);
        }
        for (i = 0; i < 1000; i++) {
            p = ziplistIndex(zl,i);
            assert(ziplistGet(p,NULL,NULL,&value));
            assert(i == value);

            p = ziplistIndex(zl,-i-1);
            assert(ziplistGet(p,NULL,NULL,&value));
            assert(999-i == value);
        }
        printf("SUCCESS\n\n");
    }

    printf("Compare strings with ziplist entries:\n");
    {
        zl = createList();
        p = ziplistIndex(zl,0);
        if (!ziplistCompare(p,(unsigned char*)"hello",5)) {
            printf("ERROR: not \"hello\"\n");
            return 1;
        }
        if (ziplistCompare(p,(unsigned char*)"hella",5)) {
            printf("ERROR: \"hella\"\n");
            return 1;
        }

        p = ziplistIndex(zl,3);
        if (!ziplistCompare(p,(unsigned char*)"1024",4)) {
            printf("ERROR: not \"1024\"\n");
            return 1;
        }
        if (ziplistCompare(p,(unsigned char*)"1025",4)) {
            printf("ERROR: \"1025\"\n");
            return 1;
        }
        printf("SUCCESS\n\n");
    }

    printf("Stress with random payloads of different encoding:\n");
    {
        int i,j,len,where;
        unsigned char *p;
        char buf[1024];
        int buflen;
        list *ref;
        listNode *refnode;

        /* Hold temp vars from ziplist */
        unsigned char *sstr;
        unsigned int slen;
        long long sval;

        for (i = 0; i < 20000; i++) {
            zl = ziplistNew();
            ref = listCreate();
            listSetFreeMethod(ref, sdsfree);
            len = rand() % 256;

            /* Create lists */
            for (j = 0; j < len; j++) {
                where = (rand() & 1) ? ZIPLIST_HEAD : ZIPLIST_TAIL;
                if (rand() % 2) {
                    buflen = randstring(buf,1,sizeof(buf)-1);
                } else {
                    switch(rand() % 3) {
                    case 0:
                        buflen = sprintf(buf,"%lld",(0LL + rand()) >> 20);
                        break;
                    case 1:
                        buflen = sprintf(buf,"%lld",(0LL + rand()));
                        break;
                    case 2:
                        buflen = sprintf(buf,"%lld",(0LL + rand()) << 20);
                        break;
                    default:
                        assert(NULL);
                    }
                }

                /* Add to ziplist */
                zl = ziplistPush(zl, (unsigned char*)buf, buflen, where);

                /* Add to reference list */
                if (where == ZIPLIST_HEAD) {
                    listAddNodeHead(ref,sdsnewlen(buf, buflen));
                } else if (where == ZIPLIST_TAIL) {
                    listAddNodeTail(ref,sdsnewlen(buf, buflen));
                } else {
                    assert(NULL);
                }
            }

            assert(listLength(ref) == ziplistLen(zl));
            for (j = 0; j < len; j++) {
                /* Naive way to get elements, but similar to the stresser
                 * executed from the Tcl test suite. */
                p = ziplistIndex(zl,j);
                refnode = listIndex(ref,j);

                assert(ziplistGet(p,&sstr,&slen,&sval));
                if (sstr == NULL) {
                    buflen = sprintf(buf,"%lld",sval);
                } else {
                    buflen = slen;
                    memcpy(buf,sstr,buflen);
                    buf[buflen] = '\0';
                }
                assert(memcmp(buf,listNodeValue(refnode),buflen) == 0);
            }
            zfree(zl);
            listRelease(ref);
        }
        printf("SUCCESS\n\n");
    }

    printf("Stress with variable ziplist size:\n");
    {
        stress(ZIPLIST_HEAD,100000,16384,256);
        stress(ZIPLIST_TAIL,100000,16384,256);
    }

    return 0;
}
Exemplo n.º 17
0
static void dictDbValDeferDestructor(void *privdata, void *val) {
    DICT_NOTUSED(privdata);

    listAddNodeHead(deferObjDelete, val);
}
Exemplo n.º 18
0
/* dictionary destructors for defering delete */
void dictDbKeyDeferDestructor(void *privdata, void *val) {
    DICT_NOTUSED(privdata);

    listAddNodeHead(deferSdsDelete, val);
}
Exemplo n.º 19
0
/* EXPLANATION: The join algorithm
    0.) for each table in join
    1.) pointers to ALL candidate columns & lengths are saved to a tuplet
    2.) this tuplet is then stored in a (Btree or HashTable) for L8R joining
  NOTE: (CON) This is only efficient for small table joins [if at all :)]
*/
static void joinAddColsFromInd(join_add_cols_t *a, robj *rset[], cswc_t *w) {
    cu32_t  cresp[MAX_JOIN_INDXS];
    int     row_len = 0;
    int     nresp   = 0;
    aobj   *akey    = a->ajk;

    for (int i = 0; i < a->qcols; i++) {
        int tmatch = a->j_tbls[i];
        if (tmatch == a->itable) {
            cresp[nresp].s  = getCopyColStr(a->btr, a->rrow, a->j_cols[i],
                                            akey, tmatch, &cresp[nresp].len);
            row_len        += cresp[nresp].len + 1; // +1 for OUTPUT_DELIM
            nresp++;
        }
    }
    row_len--; // no DELIM on final col
    if (a->j_ind_len[a->index] < row_len) a->j_ind_len[a->index] = row_len;

    a->jind_ncols[a->index] = nresp;
    char *ind_row           = malloc(nresp * (PTR_SIZE + UINT_SIZE));
    char *list_val          = ind_row;
    for (int i = 0; i < nresp; i++) { /* fill in ind_row */
        memcpy(ind_row, &cresp[i].s, PTR_SIZE);
        ind_row += PTR_SIZE;
        memcpy(ind_row, &cresp[i].len, UINT_SIZE);
        ind_row += UINT_SIZE;
    }

    /* only index matching "obt" needs to have ORDER_BY column */
    /* TODO does this for every column for this index - only 1st is needed */
    if (w->obt[0] == a->itable) {
        obsl_t *ob  = create_obsl(list_val, 1); /* DESTROY ME 011 */
        list_val    = (char *)ob; /* in ORDER BY list_val -> obsl_t */
        OB_asc[0]   = w->asc[0];
        OB_ctype[0] = Tbl[server.dbid][w->tmatch].col_type[w->obc[0]];
        assignObKey(w, a->btr, a->rrow, akey, 0, ob);
    }

    // TODO unify, refactor, etc..
    //
    // NOTE: (clarification of clusterFUcT implementation)
    //       1st index: BT         of Lists
    //       2nd index: ValSetDict of AppendSets (should be List)
    if (a->index == 0) { // first joined index needs BTREE (i.e. sorted)
        joinRowEntry  k;
        k.key           = createStringRobjFromAobj(a->ajk);
        joinRowEntry *x = btJoinFindVal(a->jbtr, &k);

        if (x) {
            list *ll = (list *)x->val;
            listAddNodeTail(ll, list_val);
        } else {
            joinRowEntry *jre = (joinRowEntry *)malloc(sizeof(joinRowEntry));
            list         *ll  = listCreate(); /* listRelease freeListOfIndRow*/
            jre->key          = k.key;
            jre->val          = (void *)ll;
            listAddNodeHead(ll, list_val);
            btJoinAddRow(a->jbtr, jre);
        }
    } else { // rest of the joined indices are redis DICTs for speed
        robj      *res_setobj;
        robj      *ind_row_obj = createObject(REDIS_JOINROW, list_val);
        robj      *key         = createStringRobjFromAobj(a->ajk);
        dictEntry *rde         = dictFind(rset[a->index]->ptr, key);
        if (!rde) {
            // create AppendSet "list"
            res_setobj = createAppendSetObject();
            dictAdd(rset[a->index]->ptr, key, res_setobj);
        } else {
            res_setobj = dictGetEntryVal(rde);
            decrRefCount(key);
        }
        dictAdd(res_setobj->ptr, ind_row_obj, NULL); // push to (list per jk)
    }
}