亚洲免费在线-亚洲免费在线播放-亚洲免费在线观看-亚洲免费在线观看视频-亚洲免费在线看-亚洲免费在线视频

redis源碼筆記-adlist

系統 2335 0

adlist是redis自己是實現的一個通用的雙向鏈表。

------------------------------------------------adlist.h---------------------------------------------------

      
        #ifndef __ADLIST_H__


      
      
        #define
      
       __ADLIST_H__




      
        /*
      
      
         Node, List, and Iterator are the only data structures used currently. 
      
      
        */
      
      
        



typedef 
      
      
        struct
      
      
         listNode {


      
      
        struct
      
       listNode *
      
        prev;


      
      
        struct
      
       listNode *
      
        next;


      
      
        void
      
       *
      
        value;

} listNode;        雙向鏈表,存的結構是一個指針void
      
      *
      
        



typedef 
      
      
        struct
      
      
         listIter {

listNode 
      
      *
      
        next;


      
      
        int
      
      
         direction;

} listIter;          迭代器,可以向前遍歷,也可以向后遍歷;



typedef 
      
      
        struct
      
      
         list {

listNode 
      
      *
      
        head;

listNode 
      
      *
      
        tail;


      
      
        void
      
       *(*dup)(
      
        void
      
       *
      
        ptr);


      
      
        void
      
       (*free)(
      
        void
      
       *
      
        ptr);


      
      
        int
      
       (*match)(
      
        void
      
       *ptr, 
      
        void
      
       *
      
        key);

unsigned 
      
      
        int
      
      
         len;

} list;                鏈表本身的結構,頭、尾指針,同時一個函數指針dup用于在復制鏈表(list or listNode
      
      ?
      
        )調用,一個函數指針free在釋放鏈表時調用,一個函數指針match用來作匹配時調用,以及一個記錄鏈表長度的字段;注意三個函數指針是list的成員,也就是被所有list node共用,因此listNode應該具有共性。




      
      
        /*
      
      
         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))   set三個函數指針的方法




      
        #define
      
       listGetDupMethod(l) ((l)->dup)


      
        #define
      
       listGetFree(l) ((l)->free)


      
        #define
      
       listGetMatchMethod(l) ((l)->match)       get三個函數指針的方法




      
        /*
      
      
         Prototypes 
      
      
        */
      
      
        

list 
      
      *listCreate(
      
        void
      
      
        );            創建鏈表


      
      
        void
      
       listRelease(list *
      
        list);      釋放鏈表

list 
      
      *listAddNodeHead(list *list, 
      
        void
      
       *
      
        value);       在表頭加一個結點

list 
      
      *listAddNodeTail(list *list, 
      
        void
      
       *
      
        value);         在表尾加一個結點

list 
      
      *listInsertNode(list *list, listNode *old_node, 
      
        void
      
       *value, 
      
        int
      
      
         after);


      
      
        void
      
       listDelNode(list *list, listNode *
      
        node);

listIter 
      
      *listGetIterator(list *list, 
      
        int
      
      
         direction);

listNode 
      
      *listNext(listIter *
      
        iter);


      
      
        void
      
       listReleaseIterator(listIter *
      
        iter);

list 
      
      *listDup(list *
      
        orig);

listNode 
      
      *listSearchKey(list *list, 
      
        void
      
       *
      
        key);

listNode 
      
      *listIndex(list *list, 
      
        int
      
      
         index);


      
      
        void
      
       listRewind(list *list, listIter *
      
        li);


      
      
        void
      
       listRewindTail(list *list, listIter *
      
        li);




      
      
        /*
      
      
         Directions for iterators 
      
      
        */
      
      
        #define
      
       AL_START_HEAD 0         


      
        #define
      
       AL_START_TAIL 1          定義迭代器方向




      
        #endif
      
       /* __ADLIST_H__ */
    

?

?

------------------------------------------------adlist.c---------------------------------------------------

      
          1
      
       #include <stdlib.h>


      
          2
      
       #include 
      
        "
      
      
        adlist.h
      
      
        "
      
      
          3
      
       #include 
      
        "
      
      
        zmalloc.h
      
      
        "     //redis對內存分配庫函數的一個封裝,用于stat目的
      
      
          4
      
      
          5
      
      
        /*
      
      
         Create a new list. The created list can be freed with


      
      
          6
      
      
         * AlFreeList(), but private value of every node need to be freed


      
      
          7
      
      
         * by the user before to call AlFreeList().


      
      
          8
      
      
         *


      
      
          9
      
      
         * On error, NULL is returned. Otherwise the pointer to the new list. 
      
      
        */
      
      
         10
      
       list *listCreate(
      
        void
      
      
        )


      
      
         11
      
      
        {


      
      
         12
      
      
        struct
      
       list *
      
        list;


      
      
         13
      
      
         14
      
      
        if
      
       ((list = zmalloc(
      
        sizeof
      
      (*list))) ==
      
         NULL)


      
      
         15
      
      
        return
      
      
         NULL;


      
      
         16
      
           list->head = list->tail =
      
         NULL;


      
      
         17
      
           list->len = 
      
        0
      
      
        ;


      
      
         18
      
           list->dup =
      
         NULL;


      
      
         19
      
           list->free =
      
         NULL;


      
      
         20
      
           list->match =
      
         NULL;


      
      
         21
      
      
        return
      
      
         list;


      
      
         22
      
      
        }    //這個函數創建的list是個裸的list,三個函數指針需要自行調用set賦值


      
      
         23
      
      
         24
      
      
        /*
      
      
         Free the whole list.


      
      
         25
      
      
         *


      
      
         26
      
      
         * This function can't fail. 
      
      
        */
      
      
         27
      
      
        void
      
       listRelease(list *
      
        list)


      
      
         28
      
      
        {


      
      
         29
      
           unsigned 
      
        int
      
      
         len;


      
      
         30
      
           listNode *current, *
      
        next;


      
      
         31
      
      
         32
      
           current = list->
      
        head;


      
      
         33
      
           len = list->
      
        len;


      
      
         34
      
      
        while
      
      (len--
      
        ) {


      
      
         35
      
               next = current->
      
        next;


      
      
         36
      
      
        if
      
       (list->free) list->free(current->
      
        value);      //


      
      
         37
      
      
                zfree(current);


      
      
         38
      
               current =
      
         next;


      
      
         39
      
      
            }


      
      
         40
      
      
            zfree(list);


      
      
         41
      
      
        }       //先用free釋放listNode中保存的元素,然后釋放結點,最后釋放鏈表本身。在鏈表操作中,注意在釋放當前結點時,需要保存后續結點的值


      
      
         42
      
      
         43
      
      
        /*
      
      
         Add a new node to the list, to head, contaning the specified 'value'


      
      
         44
      
      
         * pointer as value.


      
      
         45
      
      
         *


      
      
         46
      
      
         * On error, NULL is returned and no operation is performed (i.e. the


      
      
         47
      
      
         * list remains unaltered).


      
      
         48
      
      
         * On success the 'list' pointer you pass to the function is returned. 
      
      
        */
      
      
         49
      
       list *listAddNodeHead(list *list, 
      
        void
      
       *
      
        value)


      
      
         50
      
      
        {


      
      
         51
      
           listNode *
      
        node;


      
      
         52
      
      
         53
      
      
        if
      
       ((node = zmalloc(
      
        sizeof
      
      (*node))) ==
      
         NULL)


      
      
         54
      
      
        return
      
      
         NULL;


      
      
         55
      
           node->value =
      
         value;


      
      
         56
      
      
        if
      
       (list->len == 
      
        0
      
      
        ) {


      
      
         57
      
               list->head = list->tail =
      
         node;


      
      
         58
      
               node->prev = node->next =
      
         NULL;


      
      
         59
      
           } 
      
        else
      
      
         {


      
      
         60
      
               node->prev =
      
         NULL;


      
      
         61
      
               node->next = list->
      
        head;


      
      
         62
      
               list->head->prev =
      
         node;


      
      
         63
      
               list->head =
      
         node;


      
      
         64
      
      
            }


      
      
         65
      
           list->len++
      
        ;


      
      
         66
      
      
        return
      
      
         list;


      
      
         67
      
      
        }


      
      
         68
      
      
         69
      
      
        /*
      
      
         Add a new node to the list, to tail, contaning the specified 'value'


      
      
         70
      
      
         * pointer as value.


      
      
         71
      
      
         *


      
      
         72
      
      
         * On error, NULL is returned and no operation is performed (i.e. the


      
      
         73
      
      
         * list remains unaltered).


      
      
         74
      
      
         * On success the 'list' pointer you pass to the function is returned. 
      
      
        */
      
      
         75
      
       list *listAddNodeTail(list *list, 
      
        void
      
       *
      
        value)


      
      
         76
      
      
        {


      
      
         77
      
           listNode *
      
        node;


      
      
         78
      
      
         79
      
      
        if
      
       ((node = zmalloc(
      
        sizeof
      
      (*node))) ==
      
         NULL)


      
      
         80
      
      
        return
      
      
         NULL;


      
      
         81
      
           node->value =
      
         value;


      
      
         82
      
      
        if
      
       (list->len == 
      
        0
      
      
        ) {


      
      
         83
      
               list->head = list->tail =
      
         node;


      
      
         84
      
               node->prev = node->next =
      
         NULL;


      
      
         85
      
           } 
      
        else
      
      
         {


      
      
         86
      
               node->prev = list->
      
        tail;


      
      
         87
      
               node->next =
      
         NULL;


      
      
         88
      
               list->tail->next =
      
         node;


      
      
         89
      
               list->tail =
      
         node;


      
      
         90
      
      
            }


      
      
         91
      
           list->len++
      
        ;


      
      
         92
      
      
        return
      
      
         list;


      
      
         93
      
      
        }


      
      
         94
      
      
         95
      
       list *listInsertNode(list *list, listNode *old_node, 
      
        void
      
       *value, 
      
        int
      
      
         after) {


      
      
         96
      
           listNode *
      
        node;


      
      
         97
      
      
         98
      
      
        if
      
       ((node = zmalloc(
      
        sizeof
      
      (*node))) ==
      
         NULL)


      
      
         99
      
      
        return
      
      
         NULL;


      
      
        100
      
           node->value =
      
         value;


      
      
        101
      
      
        if
      
      
         (after) {


      
      
        102
      
               node->prev =
      
         old_node;


      
      
        103
      
               node->next = old_node->
      
        next;


      
      
        104
      
      
        if
      
       (list->tail ==
      
         old_node) {


      
      
        105
      
                   list->tail =
      
         node;


      
      
        106
      
      
                }


      
      
        107
      
           } 
      
        else
      
      
         {


      
      
        108
      
               node->next =
      
         old_node;


      
      
        109
      
               node->prev = old_node->
      
        prev;


      
      
        110
      
      
        if
      
       (list->head ==
      
         old_node) {


      
      
        111
      
                   list->head =
      
         node;


      
      
        112
      
      
                }


      
      
        113
      
      
            }


      
      
        114
      
      
        if
      
       (node->prev !=
      
         NULL) {


      
      
        115
      
               node->prev->next =
      
         node;


      
      
        116
      
      
            }


      
      
        117
      
      
        if
      
       (node->next !=
      
         NULL) {


      
      
        118
      
               node->next->prev =
      
         node;


      
      
        119
      
      
            }


      
      
        120
      
           list->len++
      
        ;


      
      
        121
      
      
        return
      
      
         list;


      
      
        122
      
      
        }


      
      
        123
      
      
        124
      
      
        /*
      
      
         Remove the specified node from the specified list.


      
      
        125
      
      
         * It's up to the caller to free the private value of the node.


      
      
        126
      
      
         *


      
      
        127
      
      
         * This function can't fail. 
      
      
        */
      
      
        128
      
      
        void
      
       listDelNode(list *list, listNode *
      
        node)


      
      
        129
      
      
        {


      
      
        130
      
      
        if
      
       (node->
      
        prev)


      
      
        131
      
               node->prev->next = node->
      
        next;


      
      
        132
      
      
        else
      
      
        133
      
               list->head = node->
      
        next;


      
      
        134
      
      
        if
      
       (node->
      
        next)


      
      
        135
      
               node->next->prev = node->
      
        prev;


      
      
        136
      
      
        else
      
      
        137
      
               list->tail = node->
      
        prev;


      
      
        138
      
      
        if
      
       (list->free) list->free(node->
      
        value);


      
      
        139
      
      
            zfree(node);


      
      
        140
      
           list->len--
      
        ;


      
      
        141
      
      
        }


      
      
        142
      
      
        143
      
      
        /*
      
      
         Returns a list iterator 'iter'. After the initialization every


      
      
        144
      
      
         * call to listNext() will return the next element of the list.


      
      
        145
      
      
         *


      
      
        146
      
      
         * This function can't fail. 
      
      
        */
      
      
        147
      
       listIter *listGetIterator(list *list, 
      
        int
      
      
         direction)


      
      
        148
      
      
        {


      
      
        149
      
           listIter *
      
        iter;


      
      
        150
      
      
        151
      
      
        if
      
       ((iter = zmalloc(
      
        sizeof
      
      (*iter))) == NULL) 
      
        return
      
      
         NULL;


      
      
        152
      
      
        if
      
       (direction ==
      
         AL_START_HEAD)


      
      
        153
      
               iter->next = list->
      
        head;


      
      
        154
      
      
        else
      
      
        155
      
               iter->next = list->
      
        tail;


      
      
        156
      
           iter->direction =
      
         direction;


      
      
        157
      
      
        return
      
      
         iter;


      
      
        158
      
      
        }


      
      
        159
      
      
        160
      
      
        /*
      
      
         Release the iterator memory 
      
      
        */
      
      
        161
      
      
        void
      
       listReleaseIterator(listIter *
      
        iter) {


      
      
        162
      
      
            zfree(iter);


      
      
        163
      
      
        }


      
      
        164
      
      
        165
      
      
        /*
      
      
         Create an iterator in the list private iterator structure 
      
      
        */
      
      
        166
      
      
        void
      
       listRewind(list *list, listIter *
      
        li) {


      
      
        167
      
           li->next = list->
      
        head;


      
      
        168
      
           li->direction =
      
         AL_START_HEAD;


      
      
        169
      
      
        }


      
      
        170
      
      
        171
      
      
        void
      
       listRewindTail(list *list, listIter *
      
        li) {


      
      
        172
      
           li->next = list->
      
        tail;


      
      
        173
      
           li->direction =
      
         AL_START_TAIL;


      
      
        174
      
      
        }


      
      
        175
      
      
        176
      
      
        /*
      
      
         Return the next element of an iterator.


      
      
        177
      
      
         * It's valid to remove the currently returned element using


      
      
        178
      
      
         * listDelNode(), but not to remove other elements.


      
      
        179
      
      
         *


      
      
        180
      
      
         * The function returns a pointer to the next element of the list,


      
      
        181
      
      
         * or NULL if there are no more elements, so the classical usage patter


      
      
        182
      
      
         * is:


      
      
        183
      
      
         *


      
      
        184
      
      
         * iter = listGetIterator(list,<direction>);


      
      
        185
      
      
         * while ((node = listNext(iter)) != NULL) {


      
      
        186
      
      
         *     doSomethingWith(listNodeValue(node));


      
      
        187
      
      
         * }


      
      
        188
      
      
         *


      
      
        189
      
      
         * 
      
      
        */
      
      
        190
      
       listNode *listNext(listIter *
      
        iter)


      
      
        191
      
      
        {


      
      
        192
      
           listNode *current = iter->
      
        next;


      
      
        193
      
      
        194
      
      
        if
      
       (current !=
      
         NULL) {


      
      
        195
      
      
        if
      
       (iter->direction ==
      
         AL_START_HEAD)


      
      
        196
      
                   iter->next = current->
      
        next;


      
      
        197
      
      
        else
      
      
        198
      
                   iter->next = current->
      
        prev;


      
      
        199
      
      
            }


      
      
        200
      
      
        return
      
      
         current;


      
      
        201
      
      
        }       //注意這個函數,如果對返回值作delete操作,iter并未失效


      
      
        202
      
      
        203
      
      
        /*
      
      
         Duplicate the whole list. On out of memory NULL is returned.


      
      
        204
      
      
         * On success a copy of the original list is returned.


      
      
        205
      
      
         *


      
      
        206
      
      
         * The 'Dup' method set with listSetDupMethod() function is used


      
      
        207
      
      
         * to copy the node value. Otherwise the same pointer value of


      
      
        208
      
      
         * the original node is used as value of the copied node.


      
      
        209
      
      
         *


      
      
        210
      
      
         * The original list both on success or error is never modified. 
      
      
        */
      
      
        211
      
       list *listDup(list *
      
        orig)


      
      
        212
      
      
        {


      
      
        213
      
           list *
      
        copy;


      
      
        214
      
           listIter *
      
        iter;


      
      
        215
      
           listNode *
      
        node;


      
      
        216
      
      
        217
      
      
        if
      
       ((copy = listCreate()) ==
      
         NULL)


      
      
        218
      
      
        return
      
      
         NULL;


      
      
        219
      
           copy->dup = orig->
      
        dup;


      
      
        220
      
           copy->free = orig->
      
        free;


      
      
        221
      
           copy->match = orig->
      
        match;


      
      
        222
      
           iter =
      
         listGetIterator(orig, AL_START_HEAD);


      
      
        223
      
      
        while
      
      ((node = listNext(iter)) !=
      
         NULL) {


      
      
        224
      
      
        void
      
       *
      
        value;


      
      
        225
      
      
        226
      
      
        if
      
       (copy->
      
        dup) {


      
      
        227
      
                   value = copy->dup(node->
      
        value);


      
      
        228
      
      
        if
      
       (value ==
      
         NULL) {


      
      
        229
      
      
                        listRelease(copy);


      
      
        230
      
      
                        listReleaseIterator(iter);


      
      
        231
      
      
        return
      
      
         NULL;


      
      
        232
      
      
                    }


      
      
        233
      
               } 
      
        else
      
      
        234
      
                   value = node->
      
        value;


      
      
        235
      
      
        if
      
       (listAddNodeTail(copy, value) ==
      
         NULL) {


      
      
        236
      
      
                    listRelease(copy);       
        
          //這里疑似有內存泄露,如果copy->dup被指定,并為value成功分配了內存,但addNodeTail的時候失敗了,這塊內存就沒人管了。 
        
      
      
        237
      
      
                    listReleaseIterator(iter);


      
      
        238
      
      
        return
      
      
         NULL; 


      
      
        239
      
      
                }


      
      
        240
      
      
            }


      
      
        241
      
      
            listReleaseIterator(iter);


      
      
        242
      
      
        return
      
      
         copy;


      
      
        243
      
      
        }  //如果沒有指定dup函數則是個淺拷貝,否則是個深拷貝。


      
      
        244
      
      
        245
      
      
        /*
      
      
         Search the list for a node matching a given key.


      
      
        246
      
      
         * The match is performed using the 'match' method


      
      
        247
      
      
         * set with listSetMatchMethod(). If no 'match' method


      
      
        248
      
      
         * is set, the 'value' pointer of every node is directly


      
      
        249
      
      
         * compared with the 'key' pointer.


      
      
        250
      
      
         *


      
      
        251
      
      
         * On success the first matching node pointer is returned


      
      
        252
      
      
         * (search starts from head). If no matching node exists


      
      
        253
      
      
         * NULL is returned. 
      
      
        */
      
      
        254
      
       listNode *listSearchKey(list *list, 
      
        void
      
       *
      
        key)


      
      
        255
      
      
        {


      
      
        256
      
           listIter *
      
        iter;


      
      
        257
      
           listNode *
      
        node;


      
      
        258
      
      
        259
      
           iter =
      
         listGetIterator(list, AL_START_HEAD);


      
      
        260
      
      
        while
      
      ((node = listNext(iter)) !=
      
         NULL) {


      
      
        261
      
      
        if
      
       (list->
      
        match) {


      
      
        262
      
      
        if
      
       (list->match(node->
      
        value, key)) {


      
      
        263
      
      
                        listReleaseIterator(iter);


      
      
        264
      
      
        return
      
      
         node;


      
      
        265
      
      
                    }


      
      
        266
      
               } 
      
        else
      
      
         {


      
      
        267
      
      
        if
      
       (key == node->
      
        value) {


      
      
        268
      
      
                        listReleaseIterator(iter);


      
      
        269
      
      
        return
      
      
         node;


      
      
        270
      
      
                    }


      
      
        271
      
      
                }


      
      
        272
      
      
            }


      
      
        273
      
      
            listReleaseIterator(iter);


      
      
        274
      
      
        return
      
      
         NULL;


      
      
        275
      
      
        } //O(n)的復雜度,n是鏈表長度


      
      
        276
      
      
        277
      
      
        /*
      
      
         Return the element at the specified zero-based index


      
      
        278
      
      
         * where 0 is the head, 1 is the element next to head


      
      
        279
      
      
         * and so on. Negative integers are used in order to count


      
      
        280
      
      
         * from the tail, -1 is the last element, -2 the penultimante


      
      
        281
      
      
         * and so on. If the index is out of range NULL is returned. 
      
      
        */
      
      
        282
      
       listNode *listIndex(list *list, 
      
        int
      
      
         index) {


      
      
        283
      
           listNode *
      
        n;


      
      
        284
      
      
        285
      
      
        if
      
       (index < 
      
        0
      
      
        ) {


      
      
        286
      
               index = (-index)-
      
        1
      
      
        ; //注意從后邊往前數時index的處理


      
      
        287
      
               n = list->
      
        tail;


      
      
        288
      
      
        while
      
      (index-- && n) n = n->
      
        prev;


      
      
        289
      
           } 
      
        else
      
      
         {


      
      
        290
      
               n = list->
      
        head;


      
      
        291
      
      
        while
      
      (index-- && n) n = n->
      
        next;


      
      
        292
      
      
            }


      
      
        293
      
      
        return
      
      
         n;


      
      
        294
      
       }
    

redis源碼筆記-adlist


更多文章、技術交流、商務合作、聯系博主

微信掃碼或搜索:z360901061

微信掃一掃加我為好友

QQ號聯系: 360901061

您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點擊下面給點支持吧,站長非常感激您!手機微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點擊微信右上角掃一掃功能,選擇支付二維碼完成支付。

【本文對您有幫助就好】

您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描上面二維碼支持博主2元、5元、10元、自定義金額等您想捐的金額吧,站長會非常 感謝您的哦!!!

發表我的評論
最新評論 總共0條評論
主站蜘蛛池模板: 操一操干一干 | 热久久在线 | 色综合综合网 | 91免费网站在线看入口黄 | 伊人狠狠丁香婷婷综合色 | 九九福利影院 | 嫩操影院 | 99中文在线 | 91欧美亚洲| 久久国内免费视频 | 亚洲精品久久久久久久久久ty | 国产日产欧美精品 | 日本一级α一片免费视频 | 久久综合综合久久狠狠狠97色 | 狠狠色丁香婷婷久久综合不卡 | 超乳w真性中出し冲田杏梨101 | 中文字幕亚洲第一 | 免费观看黄色a一级录像 | 色综合天天综合网国产人 | 婷婷激情视频 | 婷婷的久久五月综合先锋影音 | 欧美男女爱爱视频 | 女人18毛片a级18毛多水真多 | 久久黑丝| 四虎8848精品永久在线观看 | 欧美性狂猛bbbbxxxx | 日韩一级欧美一级毛片在 | 免费视频网站一级人爱视频 | 国产精品久久一区二区三区 | 正在播放亚洲 | 国产 福利 在线 | 激情综合在线 | 天天射天天射 | 香蕉视频在线观看免费 | 中国性猛交xxxxx免费看 | 综合久久网 | 国产免费一区二区三区在线 | 亚洲欧美日本在线观看 | 国产成人综合日韩精品婷婷九月 | 四虎永久网址影院 | 欧美网色 |