redis6.0ソースデュアルエンドチェーンテーブル

21014 ワード

redisではリストキー、パブリケーションとサブスクリプション、スロークエリー、モニタなどにチェーンテーブルが使用され、Redisサーバ自体はチェーンテーブルで複数のクライアントの状態情報を保存し、チェーンテーブルを使用してクライアント出力バッファを構築します.
チェーンテーブルノードadlist.h/listNode
typedef struct listNode {
    struct listNode *prev;//    
    struct listNode *next;//    
    void *value;//   
} listNode;
typedef struct list {
    listNode *head;//    
    listNode *tail;//    
    //       
    void *(*dup)(void *ptr);
    //       
    void (*free)(void *ptr);
    //       
    int (*match)(void *ptr, void *key);
    unsigned long len;
} list;

チェーンテーブル操作
新しいチェーンテーブルの作成
ノードを含まない新しいチェーンテーブルを作成
list *listCreate(void)
{
    struct list *list;
	//    
    if ((list = zmalloc(sizeof(*list))) == NULL)
        return NULL;
    //     
    list->head = list->tail = NULL;
    list->len = 0;
    list->dup = NULL;
    list->free = NULL;
    list->match = NULL;
    return list;
}

チェーンテーブルヘッダに新しいノードを挿入
list *listAddNodeHead(list *list, void *value)
{
    listNode *node;

    if ((node = zmalloc(sizeof(*node))) == NULL)
        return NULL;
    node->value = value;
    if (list->len == 0) {
        list->head = list->tail = node;
        node->prev = node->next = NULL;
    } else {
        node->prev = NULL;
        node->next = list->head;
        list->head->prev = node;
        list->head = node;
    }
    list->len++;
    return list;
}

チェーンテーブルの末尾に新しいノードを挿入
list *listAddNodeTail(list *list, void *value)
{
    listNode *node;

    if ((node = zmalloc(sizeof(*node))) == NULL)
        return NULL;
    node->value = value;
    if (list->len == 0) {
        list->head = list->tail = node;
        node->prev = node->next = NULL;
    } else {
        node->prev = list->tail;
        node->next = NULL;
        list->tail->next = node;
        list->tail = node;
    }
    list->len++;
    return list;
}

list構造マクロ実装の関数
/* Functions implemented as macros */
#define listLength(l) ((l)->len)  //      
#define listFirst(l) ((l)->head) //         
#define listLast(l) ((l)->tail)  //         
#define listPrevNode(n) ((n)->prev) //           
#define listNextNode(n) ((n)->next) //           
#define listNodeValue(n) ((n)->value)//        

#define listSetDupMethod(l,m) ((l)->dup = (m))
#define listSetFreeMethod(l,m) ((l)->free = (m))
#define listSetMatchMethod(l,m) ((l)->match = (m))

#define listGetDupMethod(l) ((l)->dup)
#define listGetFreeMethod(l) ((l)->free)
#define listGetMatchMethod(l) ((l)->match)

反復器
typedef struct listIter {
    listNode *next;
    int direction;
} listIter;
  • listNodeは、特定のノード情報
  • である.
  • direction遍歴方向AL_START_HEADは頭から尾へAL_を遍歴するSTART_TAILは尾部から頭部に向かって
  • を遍歴する.
    チェーンテーブルに基づいて反復器を得る
    listIter *listGetIterator(list *list, int direction)
    {
        listIter *iter;
    
        if ((iter = zmalloc(sizeof(*iter))) == NULL) return NULL;
        if (direction == AL_START_HEAD)
            iter->next = list->head;
        else
            iter->next = list->tail;
        iter->direction = direction;
        return iter;
    }
    

    かいほう反復器
    void listReleaseIterator(listIter *iter) {
        zfree(iter);
    }
    
    listNode *listNext(listIter *iter)
    {
        listNode *current = iter->next;
    
        if (current != NULL) {
            if (iter->direction == AL_START_HEAD)
                iter->next = current->next;
            else
                iter->next = current->prev;
        }
        return current;
    }
    

    チェーンテーブルとkeyが一致するノードのクエリー
    listNode *listSearchKey(list *list, void *key)
    {
        listIter iter;
        listNode *node;
    	//     ->      
        listRewind(list, &iter);
        //           
        while((node = listNext(&iter)) != NULL) {
            if (list->match) {
                if (list->match(node->value, key)) {
                    return node;
                }
            } else {
                if (key == node->value) {
                    return node;
                }
            }
        }
        return NULL;
    }
    

    もっと説明して、私のgithub:go成神の道に注目してください.