Example #1
0
void zipmapRepr(unsigned char *p) {
    unsigned int l;

    printf("{status %u}",*p++);
    while(1) {
        if (p[0] == ZIPMAP_END) {
            printf("{end}");
            break;
        } else {
            unsigned char e;

            l = zipmapDecodeLength(p);
            printf("{key %u}",l);
            p += zipmapEncodeLength(NULL,l);
            if (l != 0 && fwrite(p,l,1,stdout) == 0) perror("fwrite");
            p += l;

            l = zipmapDecodeLength(p);
            printf("{value %u}",l);
            p += zipmapEncodeLength(NULL,l);
            e = *p++;
            if (l != 0 && fwrite(p,l,1,stdout) == 0) perror("fwrite");
            p += l+e;
            if (e) {
                printf("[");
                while(e--) printf(".");
                printf("]");
            }
        }
    }
    printf("\n");
}
Example #2
0
/* Search for a matching key, returning a pointer to the entry inside the
 * zipmap. Returns NULL if the key is not found.
 *
 * If NULL is returned, and totlen is not NULL, it is set to the entire
 * size of the zimap, so that the calling function will be able to
 * reallocate the original zipmap to make room for more entries. */
static unsigned char *zipmapLookupRaw(unsigned char *zm, unsigned char *key, unsigned int klen, unsigned int *totlen) {
    unsigned char *p = zm+1, *k = NULL;
    unsigned int l,llen;

    // 遍历zipmap
    while(*p != ZIPMAP_END) {
        unsigned char free;
        // 返回len表示的长度
        /* Match or skip the key */
        l = zipmapDecodeLength(p);
        // 返回要编码l表示的长度需要的字节数,1还是5字节
        llen = zipmapEncodeLength(NULL,l);
        // 看看Key是不是相等
        if (key != NULL && k == NULL && l == klen && !memcmp(p+llen,key,l)) {
            // 如果外部不想知道总长度的时候,直接返回
            /* Only return when the user doesn't care
             * for the total length of the zipmap. */
            if (totlen != NULL) {
                k = p;
            } else {
                return p;
            }
        }
        // p到达下一个元素的位置
        p += llen+l;
        /* Skip the value as well */
        l = zipmapDecodeLength(p);
        p += zipmapEncodeLength(NULL,l);
        free = p[0];
        p += l+1+free; /* +1 to skip the free byte */
    }
    // 返回zm的总字节长度
    if (totlen != NULL) *totlen = (unsigned int)(p-zm)+1;
    return k;
}
/* This function is used to iterate through all the zipmap elements.
 *
 * 这个函数用于遍历 zipmap 的所有元素。
 *
 * In the first call the first argument is the pointer to the zipmap + 1.
 *
 * 在第一次调用这个函数时, zm 参数的值为 zipmap + 1 
 * (也即是,指向 zipmap 的第一个节点)
 *
 * In the next calls what zipmapNext returns is used as first argument.
 *
 * 而在之后的调用中, zm 参数的值为之前调用 zipmapNext 时所返回的值。
 *
 * Example:
 * 
 * 示例:
 *
 * unsigned char *i = zipmapRewind(my_zipmap);
 * while((i = zipmapNext(i,&key,&klen,&value,&vlen)) != NULL) {
 *     printf("%d bytes key at $p\n", klen, key);
 *     printf("%d bytes value at $p\n", vlen, value);
 * }
 *
 * T = O(1)
 */
unsigned char *zipmapNext(unsigned char *zm, unsigned char **key, unsigned int *klen, unsigned char **value, unsigned int *vlen) {

    // 已到达列表末尾,停止迭代
    if (zm[0] == ZIPMAP_END) return NULL;

    // 取出键,并保存到 key 参数中
    if (key) {
        *key = zm;
        *klen = zipmapDecodeLength(zm);
        *key += ZIPMAP_LEN_BYTES(*klen);
    }
    // 越过键
    zm += zipmapRawKeyLength(zm);

    // 取出值,并保存到 value 参数中
    if (value) {
        *value = zm+1;
        *vlen = zipmapDecodeLength(zm);
        *value += ZIPMAP_LEN_BYTES(*vlen);
    }
    // 越过值
    zm += zipmapRawValueLength(zm);

    // 返回指向下一节点的指针
    return zm;
}
Example #4
0
/* Search for a matching key, returning a pointer to the entry inside the
 * zipmap. Returns NULL if the key is not found.
 *
 * If NULL is returned, and totlen is not NULL, it is set to the entire
 * size of the zimap, so that the calling function will be able to
 * reallocate the original zipmap to make room for more entries. */
static unsigned char *zipmapLookupRaw(unsigned char *zm, unsigned char *key, unsigned int klen, unsigned int *totlen) {
    unsigned char *p = zm+1, *k = NULL;
    unsigned int l,llen;

    while(*p != ZIPMAP_END) {
        unsigned char free;

        /* Match or skip the key */
        l = zipmapDecodeLength(p);
        llen = zipmapEncodeLength(NULL,l);
        if (key != NULL && k == NULL && l == klen && !memcmp(p+llen,key,l)) {
            /* Only return when the user doesn't care
             * for the total length of the zipmap. */
            if (totlen != NULL) {
                k = p;
            } else {
                return p;
            }
        }
        p += llen+l;
        /* Skip the value as well */
        l = zipmapDecodeLength(p);
        p += zipmapEncodeLength(NULL,l);
        free = p[0];
        p += l+1+free; /* +1 to skip the free byte */
    }
    if (totlen != NULL) *totlen = (unsigned int)(p-zm)+1;
    return k;
}
/* Search for a matching key, returning a pointer to the entry inside the
 * zipmap. Returns NULL if the key is not found.
 *
 * 在 zipmap 中查找和给定 key 匹配的节点:
 *
 *  1)找到的话就返回节点的指针。
 *
 *  2)没找到则返回 NULL 。
 *
 * If NULL is returned, and totlen is not NULL, it is set to the entire
 * size of the zimap, so that the calling function will be able to
 * reallocate the original zipmap to make room for more entries. 
 *
 * 如果没有找到相应的节点(函数返回 NULL),并且 totlen 不为 NULL ,
 * 那么 *totlen 的值将被设为整个 zipmap 的大小,
 * 这样调用者就可以根据 *totlen 的值,对 zipmap 进行内存重分配,
 * 从而让 zipmap 容纳更多节点。
 *
 * T = O(N^2)
 */
static unsigned char *zipmapLookupRaw(unsigned char *zm, unsigned char *key, unsigned int klen, unsigned int *totlen) {

    // zm+1 略过 <zmlen> 属性,将 p 指向 zipmap 的首个节点
    unsigned char *p = zm+1, *k = NULL;
    unsigned int l,llen;

    // 遍历整个 zipmap 来寻找
    // T = O(N^2)
    while(*p != ZIPMAP_END) {
        unsigned char free;

        /* Match or skip the key */
        // 计算键的长度
        l = zipmapDecodeLength(p);
        // 计算编码键的长度所需的字节数
        llen = zipmapEncodeLength(NULL,l);
        // 对比 key
        // T = O(N)
        if (key != NULL && k == NULL && l == klen && !memcmp(p+llen,key,l)) {
            /* Only return when the user doesn't care
             * for the total length of the zipmap. */
            if (totlen != NULL) {
                // 如果调用者需要知道整个 zipmap 的长度,那么记录找到的指针到变量 k
                // 之后遍历时,程序只计算 zipmap 剩余节点的长度,不再用 memcmp 进行对比
                // 因为 k 已经不为 NULL 了
                k = p;
            } else {
                // 如果调用者不需要知道整个 zipmap 的长度,那么直接返回 p 
                return p;
            }
        }

        // 越过键节点,指向值节点
        p += llen+l;

        /* Skip the value as well */
        // 计算值的长度
        l = zipmapDecodeLength(p);
        // 计算编码值的长度所需的字节数,
        // 并移动指针 p ,越过该 <len> 属性,指向 <free> 属性
        p += zipmapEncodeLength(NULL,l);
        // 取出 <free> 属性的值
        free = p[0];
        // 略过值节点,指向下一节点
        p += l+1+free; /* +1 to skip the free byte */
    }

    // 计算并记录 zipmap 的空间长度
    // + 1 是将 ZIPMAP_END 也计算在内
    if (totlen != NULL) *totlen = (unsigned int)(p-zm)+1;

    // 返回找到 key 的指针
    return k;
}
Example #6
0
/* This function is used to iterate through all the zipmap elements.
 * In the first call the first argument is the pointer to the zipmap + 1.
 * In the next calls what zipmapNext returns is used as first argument.
 * Example:
 *
 * unsigned char *i = zipmapRewind(my_zipmap);
 * while((i = zipmapNext(i,&key,&klen,&value,&vlen)) != NULL) {
 *     printf("%d bytes key at $p\n", klen, key);
 *     printf("%d bytes value at $p\n", vlen, value);
 * }
 */
unsigned char *zipmapNext(unsigned char *zm, unsigned char **key, unsigned int *klen, unsigned char **value, unsigned int *vlen) {
    if (zm[0] == ZIPMAP_END) return NULL;
    if (key) {
        *key = zm;
        *klen = zipmapDecodeLength(zm);
        *key += ZIPMAP_LEN_BYTES(*klen);
    }
    zm += zipmapRawKeyLength(zm);
    if (value) {
        *value = zm+1;
        *vlen = zipmapDecodeLength(zm);
        *value += ZIPMAP_LEN_BYTES(*vlen);
    }
    zm += zipmapRawValueLength(zm);
    return zm;
}
Example #7
0
/* Return the total amount used by a value
 * (encoded length + single byte free count + payload) */
static unsigned int zipmapRawValueLength(unsigned char *p) {
    unsigned int l = zipmapDecodeLength(p);
    unsigned int used;

    used = zipmapEncodeLength(NULL,l);
    used += p[used] + 1 + l;
    return used;
}
Example #8
0
/* Search a key and retrieve the pointer and len of the associated value.
 * If the key is found the function returns 1, otherwise 0. */
int zipmapGet(unsigned char *zm, unsigned char *key, unsigned int klen, unsigned char **value, unsigned int *vlen) {
    unsigned char *p;

    if ((p = zipmapLookupRaw(zm,key,klen,NULL)) == NULL) return 0;
    p += zipmapRawKeyLength(p);
    *vlen = zipmapDecodeLength(p);
    *value = p + ZIPMAP_LEN_BYTES(*vlen) + 1;
    return 1;
}
/* 获取value节点占用的字节数,即len字段 + 1个字节free字段 + value字符串长度 + 空闲空间大小 */
static unsigned int zipmapRawValueLength(unsigned char *p) {
    // 获取value字符串的长度
    unsigned int l = zipmapDecodeLength(p);
    unsigned int used;

    // 获取保存value字符串长度所需要的字节数
    used = zipmapEncodeLength(NULL,l);
    // p[used]里面存储着空闲空间的大小
    used += p[used] + 1 + l;
    return used;
}
 /* 按关键字key查找zipmap,如果totlen不为NULL,函数返回后存放zipmap占用的字节数 */
static unsigned char *zipmapLookupRaw(unsigned char *zm, unsigned char *key, unsigned int klen, unsigned int *totlen) {
    // zipmap中第1个字节是zmlen字段,zm+1跳过第1个字节
    unsigned char *p = zm+1, *k = NULL;
    unsigned int l,llen;

    // 从前往后查找
    while(*p != ZIPMAP_END) {
        unsigned char free;

        /* Match or skip the key */
        // 确定key字符串的长度
        l = zipmapDecodeLength(p);
        // 确定保存key字符串长度所需要的字节数,也就是len字段所需要的字节数
        llen = zipmapEncodeLength(NULL,l);
        // 比较当前key与给定key是否匹配
        if (key != NULL && k == NULL && l == klen && !memcmp(p+llen,key,l)) {
            /* Only return when the user doesn't care
             * for the total length of the zipmap. */
            // 如果totlen为NULL,表示函数调用者不关心zipmap占用的字节数,此时直接返回p,否则先记录下p指针然后继续遍历
            if (totlen != NULL) {
                k = p;
            } else {
                return p;
            }
        }
        // p加上llen和l,到了value节点处
        p += llen+l;
        /* Skip the value as well */
        // 确定value字符串的长度
        l = zipmapDecodeLength(p);
        // 确定保存value字符串长度所需要的字节数,也就是len字段所需要的字节数
        p += zipmapEncodeLength(NULL,l);
        // 读出free字段的值(前面我们讲过:free只占用一个字节)
        free = p[0];
        // 跳到下一个key节点的
        p += l+1+free; /* +1 to skip the free byte */
    }
    // 到这里遍历完整个zipmap,得到其占用的字节数
    if (totlen != NULL) *totlen = (unsigned int)(p-zm)+1;
    return k;
}
/* zipmap的迭代器式遍历函数,典型用法如下:
 *
 *      unsigned char *i = zipmapRewind(my_zipmap);
 *      while((i = zipmapNext(i,&key,&klen,&value,&vlen)) != NULL) {
 *          printf("%d bytes key at $p\n", klen, key);
 *          printf("%d bytes value at $p\n", vlen, value);
 *      }
 */
unsigned char *zipmapNext(unsigned char *zm, unsigned char **key, unsigned int *klen, unsigned char **value, unsigned int *vlen) {
    // 如果达到尾部,直接返回NULL
    if (zm[0] == ZIPMAP_END) return NULL;
    // 获取key
    if (key) {
        *key = zm;
        *klen = zipmapDecodeLength(zm);
        *key += ZIPMAP_LEN_BYTES(*klen);
    }
    zm += zipmapRawKeyLength(zm);
    // 获取value
    if (value) {
        // +1是为了跳过free字段,该字段占用一个字节
        *value = zm+1;
        *vlen = zipmapDecodeLength(zm);
        *value += ZIPMAP_LEN_BYTES(*vlen);
    }
    // 此时zm指向下一个键值对的首地址
    zm += zipmapRawValueLength(zm);
    return zm;
}
/* Return the total amount used by a value
 * (encoded length + single byte free count + payload) 
 *
 * 返回值所占用的字节总数
 *
 * 包括编码长度值所需的字节数,单个字节的 <free> 属性,以及值的长度本身
 *
 * T = O(1)
 */
static unsigned int zipmapRawValueLength(unsigned char *p) {

    // 取出值的长度
    unsigned int l = zipmapDecodeLength(p);
    unsigned int used;
    
    // 编码长度所需的字节数
    used = zipmapEncodeLength(NULL,l);
    // 计算总和
    used += p[used] + 1 + l;

    return used;
}
Example #13
0
/* Search for a matching key, returning a pointer to the entry inside the
 * zipmap. Returns NULL if the key is not found.
 *
 * If NULL is returned, and totlen is not NULL, it is set to the entire
 * size of the zimap, so that the calling function will be able to
 * reallocate the original zipmap to make room for more entries.
 *
 * If NULL is returned, and freeoff and freelen are not NULL, they are set
 * to the offset of the first empty space that can hold '*freelen' bytes
 * (freelen is an integer pointer used both to signal the required length
 * and to get the reply from the function). If there is not a suitable
 * free space block to hold the requested bytes, *freelen is set to 0. */
static unsigned char *zipmapLookupRaw(unsigned char *zm, unsigned char *key, unsigned int klen, unsigned int *totlen, unsigned int *freeoff, unsigned int *freelen) {
    unsigned char *p = zm+1;
    unsigned int l;
    unsigned int reqfreelen = 0; /* initialized just to prevent warning */

    if (freelen) {
        reqfreelen = *freelen;
        *freelen = 0;
        assert(reqfreelen != 0);
    }
    while(*p != ZIPMAP_END) {
        if (*p == ZIPMAP_EMPTY) {
            l = zipmapDecodeLength(p+1);
            /* if the user want a free space report, and this space is
             * enough, and we did't already found a suitable space... */
            if (freelen && l >= reqfreelen && *freelen == 0) {
                *freelen = l;
                *freeoff = p-zm;
            }
            p += l;
            zm[0] |= ZIPMAP_STATUS_FRAGMENTED;
        } else {
            unsigned char free;

            /* Match or skip the key */
            l = zipmapDecodeLength(p);
            if (l == klen && !memcmp(p+1,key,l)) return p;
            p += zipmapEncodeLength(NULL,l) + l;
            /* Skip the value as well */
            l = zipmapDecodeLength(p);
            p += zipmapEncodeLength(NULL,l);
            free = p[0];
            p += l+1+free; /* +1 to skip the free byte */
        }
    }
    if (totlen != NULL) *totlen = (unsigned int)(p-zm)+1;
    return NULL;
}
Example #14
0
void zipmapRepr(unsigned char *p) {
    unsigned int l;

    printf("{status %u}",*p++);
    while(1) {
        if (p[0] == ZIPMAP_END) {
            printf("{end}");
            break;
        } else if (p[0] == ZIPMAP_EMPTY) {
            l = zipmapDecodeLength(p+1);
            printf("{%u empty block}", l);
            p += l;
        } else {
            unsigned char e;

            l = zipmapDecodeLength(p);
            printf("{key %u}",l);
            p += zipmapEncodeLength(NULL,l);
            fwrite(p,l,1,stdout);
            p += l;

            l = zipmapDecodeLength(p);
            printf("{value %u}",l);
            p += zipmapEncodeLength(NULL,l);
            e = *p++;
            fwrite(p,l,1,stdout);
            p += l+e;
            if (e) {
                printf("[");
                while(e--) printf(".");
                printf("]");
            }
        }
    }
    printf("\n");
}
Example #15
0
/* Search a key and retrieve the pointer and len of the associated value.
 * If the key is found the function returns 1, otherwise 0. */
int zipmapXGet(unsigned char **zm, unsigned char *key, unsigned int klen,
        unsigned char **value, unsigned int *vlen, unsigned int timestamp) {
    unsigned char *p;

    if ((p = zipmapXLookupRaw(*zm,key,klen,NULL,NULL)) == NULL) return 0;
    p += zipmapRawKeyLength(p);
    unsigned int ts = *(unsigned int*)p;
    p += sizeof(unsigned int);
    *vlen = zipmapDecodeLength(p);
    *value = p + ZIPMAP_LEN_BYTES(*vlen) + 1;
    if (ts < timestamp) {
        *vlen = 0;
        *value = NULL;
        return 0;
    }

    return 1;
}
/* Search a key and retrieve the pointer and len of the associated value.
 * If the key is found the function returns 1, otherwise 0. 
 *
 * 在 zipmap 中按 key 进行查找,
 * 将值的指针保存到 *value 中,并将值的长度保存到 *vlen 中。
 *
 * 成功找到值时函数返回 1 ,没找到则返回 0 。
 *
 * T = O(N^2)
 */
int zipmapGet(unsigned char *zm, unsigned char *key, unsigned int klen, unsigned char **value, unsigned int *vlen) {
    unsigned char *p;

    // 在 zipmap 中按 key 查找
    // 没找到直接返回 0 
    // T = O(N^2)
    if ((p = zipmapLookupRaw(zm,key,klen,NULL)) == NULL) return 0;

    // 越过键,指向值
    p += zipmapRawKeyLength(p);
    // 取出值的长度
    *vlen = zipmapDecodeLength(p);
    // 将 *value 指向值, +1 为越过 <free> 属性
    *value = p + ZIPMAP_LEN_BYTES(*vlen) + 1;

    // 找到,返回 1 
    return 1;
}
/* 获取key节点占用的字节数,即len字段 + key字符串长度 */
static unsigned int zipmapRawKeyLength(unsigned char *p) {
    // 获取key字符串的长度
    unsigned int l = zipmapDecodeLength(p);
    // 加上保存key字符串长度所需要的字节数
    return zipmapEncodeLength(NULL,l) + l;
}
Example #18
0
/* Return the total amount used by a key (encoded length + payload) */
static unsigned int zipmapRawKeyLength(unsigned char *p) {
    unsigned int l = zipmapDecodeLength(p);
    return zipmapEncodeLength(NULL,l) + l;
}