lighttpd 之五 数据结构

1.1 bitset数据结构

       bitset数据结构提供对bit位操作的封装。提供对bit的置位操作,清位操作,测试位操作等常用位操作。

       相关部分源码:

          bitset.h

          bitset.c

        在高版本的lighttpd源码中已经删除。

1.2 buffer数据结构

   1.2.1 结构说明

        buffer结构体以及其相关实现函数替lighttpd管理者字符串的内存使用与操作。在Web服务器中,很多的处理

  都是针对字符串进行的,比如客户端请求的URI地址,发送的query参数、post提交的数据、服务器的响应内容等

  都是一些字符串的集合。因此提供对字符串的灵活操作以及封装对字符串的高效处理,不管是对前期的lighttpd功能

 开发还是对后期lighttpd实际执行的效率都有着至关重要的作用。

      相关部分源码:

           buffer.h

           buffer.c

     1.2.2 结构定义

  

/* generic string + binary data container; contains a terminating 0 in both
 * cases
 *
 * used == 0 indicates a special "empty" state (unset config values); ptr
 * might be NULL too then. otherwise an empty string has used == 1 (and ptr[0]
 * == 0);
 *
 * copy/append functions will ensure used >= 1 (i.e. never leave it in the
 * special empty state); only buffer_copy_buffer will copy the special empty
 * state.
 */
typedef struct {
    char *ptr;

    /* "used" includes a terminating 0 */
    size_t used;
    /* size of allocated buffer at *ptr */
    size_t size;
} buffer;

1.3 data_xxxxx数据结构

       1.3.1 结构说明

                 data_xxxxx数据结构体表示的是一类数据结构体,总览lighttpd的137个源文件,不难发现有几个文件命名

          很一致的源文件,它们是data_array.c,data_config.c,data_count.c、data_fastcgi.c、data_integer.c、data_string.c.,这

           些文件实现的是lighttpd中非常重要的基础数据结构部分、本节就来分析它们是怎么组织的,它们之间到底是什么关系。

                本节相关部分源码:

                array.h

                array.c

       1.3.2 结构定义

                data_xxxxx数据结构全部都定义在array.h头文件内、包括有data_unset、data_array、data_config、data_count、

           data_fastcgi、data_integer、data_string。data_unset是基础,首先查看data_unset结构体,很简单,里面就一个

          DATA_UNSET宏,将其展开后就是其结构体元素。另外的几个结构体,也都是第一个元素为DATA_UNSET宏,另外各个

          结构体再包含有自己特有的一些属性元素。在结构体的初始化函数data_xxxxx_ini()内,各自结构体实现源文件内提供的

          接口函数都将赋值给对应的结构体函数指针字段,这样在对data_unset操作时会根据其实际类型而调用不同的函数,如果

          利用面向对象的思想来看待这些结构体,很容易想到把data_unset看做基类,而其他data_array等看作子类,这实现的

          就是所谓的继承和多态效果,这样一来我们可以画出他们之间的UML图,如下所示。lighttpd开发者利用C语言来模拟面

          向对象的实现,一方面使得程序数据结构扩展灵活,具有面向对象技术的优势,另一方面又拥有C语言本身操作数据的

         便利。在lighttpd源代码的其它地方,还可以看到作者的这种灵活设计。

                

#define DATA_IS_STRING(x) (x->type == TYPE_STRING)

typedef enum { TYPE_UNSET, TYPE_STRING, TYPE_OTHER, TYPE_ARRAY, TYPE_INTEGER, TYPE_DONOTUSE, TYPE_CONFIG } data_type_t;
#define DATA_UNSET \
    data_type_t type; \
    buffer *key; \
    int is_index_key; /* 1 if key is a array index (autogenerated keys) */ \
    struct data_unset *(*copy)(const struct data_unset *src); \
    void (* free)(struct data_unset *p); \
    void (* reset)(struct data_unset *p); \
    int (*insert_dup)(struct data_unset *dst, struct data_unset *src); \
    void (*print)(const struct data_unset *p, int depth)

typedef struct data_unset {
    DATA_UNSET;
} data_unset;

typedef struct {
    data_unset  **data;

    size_t *sorted;

    size_t used; /* <= SSIZE_MAX */
    size_t size;

    size_t unique_ndx;
} array;

typedef struct {
    DATA_UNSET;

    buffer *value;
} data_string;

data_string *data_string_init(void);
data_string *data_response_init(void);

typedef struct {
    DATA_UNSET;

    array *value;
} data_array;

data_array *data_array_init(void);

/**
 * possible compare ops in the configfile parser
 */
typedef enum {
    CONFIG_COND_UNSET,
    CONFIG_COND_EQ,      /** == */
    CONFIG_COND_MATCH,   /** =~ */
    CONFIG_COND_NE,      /** != */
    CONFIG_COND_NOMATCH, /** !~ */
    CONFIG_COND_ELSE     /** (always true if reached) */
} config_cond_t;

/**
 * possible fields to match against
 */
typedef enum {
    COMP_UNSET,
    COMP_SERVER_SOCKET,
    COMP_HTTP_URL,
    COMP_HTTP_HOST,
    COMP_HTTP_REFERER,        /*(subsumed by COMP_HTTP_REQUEST_HEADER)*/
    COMP_HTTP_USER_AGENT,     /*(subsumed by COMP_HTTP_REQUEST_HEADER)*/
    COMP_HTTP_LANGUAGE,       /*(subsumed by COMP_HTTP_REQUEST_HEADER)*/
    COMP_HTTP_COOKIE,         /*(subsumed by COMP_HTTP_REQUEST_HEADER)*/
    COMP_HTTP_REMOTE_IP,
    COMP_HTTP_QUERY_STRING,
    COMP_HTTP_SCHEME,
    COMP_HTTP_REQUEST_METHOD,
    COMP_HTTP_REQUEST_HEADER,

    COMP_LAST_ELEMENT
} comp_key_t;

/* $HTTP["host"] ==    "incremental.home.kneschke.de" { ... }
 * for print:   comp_key      op    string
 * for compare: comp          cond  string/regex
 */

typedef struct data_config data_config;
DEFINE_TYPED_VECTOR_NO_RELEASE(config_weak, data_config*);

struct data_config {
    DATA_UNSET;

    array *value;

    buffer *comp_tag;
    buffer *comp_key;
    comp_key_t comp;

    config_cond_t cond;
    buffer *op;

    int context_ndx; /* more or less like an id */
    vector_config_weak children;
    /* nested */
    data_config *parent;
    /* for chaining only */
    data_config *prev;
    data_config *next;

    buffer *string;
#ifdef HAVE_PCRE_H
    pcre   *regex;
    pcre_extra *regex_study;
#endif
};

data_config *data_config_init(void);

typedef struct {
    DATA_UNSET;

    int value;
} data_integer;

1.4 chunk数据结构

       1.4.1 结构说明

           chunk结构体是lighttpd源码内另一个极其重要的数据结构,lighttpd接受客户端请求的数据以及对客户端

  发送响应的数据就是通过chunk结构体来组织的,本节将分析这个数据结构体。

          本节相关部分源码:

           chunk.h

           chunk.c

           1.4.2 结定义

            chunk指定了两种块类型,一种是MEM_CHUNK,一种是FILE_CHUNK,对于各自块类型给出了相应的数据保存结构字

   段。另外有个next字段可以将各个chunk结构体连接起来组成链表。chunk数据结构定义在对应的chunk.h头文件内。

    

typedef struct chunk {
    enum { MEM_CHUNK, FILE_CHUNK } type;

    buffer *mem; /* either the storage of the mem-chunk or the read-ahead buffer */

    struct {
        /* filechunk */
        buffer *name; /* name of the file */
        off_t  start; /* starting offset in the file */
        off_t  length; /* octets to send from the starting offset */

        int    fd;
        struct {
            char   *start; /* the start pointer of the mmap'ed area */
            size_t length; /* size of the mmap'ed area */
            off_t  offset; /* start is <n> octet away from the start of the file */
        } mmap;

        int is_temp; /* file is temporary and will be deleted if on cleanup */
    } file;

    /* the size of the chunk is either:
     * - mem-chunk: buffer_string_length(chunk::mem)
     * - file-chunk: chunk::file.length
     */
    off_t  offset; /* octets sent from this chunk */

    struct chunk *next;
} chunk;

typedef struct {
    chunk *first;
    chunk *last;

    chunk *unused;
    size_t unused_chunks;

    off_t bytes_in, bytes_out;

    array *tempdirs;
    unsigned int upload_temp_file_size;
    unsigned int tempdir_idx;
} chunkqueue;

1.5 keyvalue数据结构

       1.5.1 结构说明

               keyvalue结构体正如其命名所示,主要用来将两个值(一个整型key,一个字符串类型value)一一对应地关联起来,并

     提供相应的结构使我们可以从key找到对应的value,也可以从value获取到对应的可以,这主要用于在人阅读(字符串类型使

    得人更容易理解)与机器操作(整型对于机器来说更容易操作)至二级进行快速切换,下面来分析这个数据结构体。

              本节相关部分源码:

              keyvalue.h

              keyvalue.c

      

        1.5.2 结定义

            keyvalue仅包含两个字段,在对应的keyvalue.h头文件内定义,但是另外几个keyvalue类型的数组在后面第10章要经常

    看到,这里也列出来,结构清单如下:

           

struct server;
struct cond_cache_t;

/* sources:
 * - [RFC2616], Section 9
 *   (or http://tools.ietf.org/html/draft-ietf-httpbis-p2-semantics-22)
 * - http://tools.ietf.org/html/draft-ietf-httpbis-method-registrations-11, Appendix A
 *
 * http://tools.ietf.org/html/draft-ietf-httpbis-p2-semantics-22, Section 8.1 defines
 * a new registry (not available yet):
 *   http://www.iana.org/assignments/http-methods
 */

typedef enum {
    HTTP_METHOD_UNSET = -1,
    HTTP_METHOD_GET,               /* [RFC2616], Section 9.3 */
    HTTP_METHOD_HEAD,              /* [RFC2616], Section 9.4 */
    HTTP_METHOD_POST,              /* [RFC2616], Section 9.5 */
    HTTP_METHOD_PUT,               /* [RFC2616], Section 9.6 */
    HTTP_METHOD_DELETE,            /* [RFC2616], Section 9.7 */
    HTTP_METHOD_CONNECT,           /* [RFC2616], Section 9.9 */
    HTTP_METHOD_OPTIONS,           /* [RFC2616], Section 9.2 */
    HTTP_METHOD_TRACE,             /* [RFC2616], Section 9.8 */
    HTTP_METHOD_ACL,               /* [RFC3744], Section 8.1 */
    HTTP_METHOD_BASELINE_CONTROL,  /* [RFC3253], Section 12.6 */
    HTTP_METHOD_BIND,              /* [RFC5842], Section 4 */
    HTTP_METHOD_CHECKIN,           /* [RFC3253], Section 4.4 and [RFC3253], Section 9.4 */
    HTTP_METHOD_CHECKOUT,          /* [RFC3253], Section 4.3 and [RFC3253], Section 8.8 */
    HTTP_METHOD_COPY,              /* [RFC4918], Section 9.8 */
    HTTP_METHOD_LABEL,             /* [RFC3253], Section 8.2 */
    HTTP_METHOD_LINK,              /* [RFC2068], Section 19.6.1.2 */
    HTTP_METHOD_LOCK,              /* [RFC4918], Section 9.10 */
    HTTP_METHOD_MERGE,             /* [RFC3253], Section 11.2 */
    HTTP_METHOD_MKACTIVITY,        /* [RFC3253], Section 13.5 */
    HTTP_METHOD_MKCALENDAR,        /* [RFC4791], Section 5.3.1 */
    HTTP_METHOD_MKCOL,             /* [RFC4918], Section 9.3 */
    HTTP_METHOD_MKREDIRECTREF,     /* [RFC4437], Section 6 */
    HTTP_METHOD_MKWORKSPACE,       /* [RFC3253], Section 6.3 */
    HTTP_METHOD_MOVE,              /* [RFC4918], Section 9.9 */
    HTTP_METHOD_ORDERPATCH,        /* [RFC3648], Section 7 */
    HTTP_METHOD_PATCH,             /* [RFC5789], Section 2 */
    HTTP_METHOD_PROPFIND,          /* [RFC4918], Section 9.1 */
    HTTP_METHOD_PROPPATCH,         /* [RFC4918], Section 9.2 */
    HTTP_METHOD_REBIND,            /* [RFC5842], Section 6 */
    HTTP_METHOD_REPORT,            /* [RFC3253], Section 3.6 */
    HTTP_METHOD_SEARCH,            /* [RFC5323], Section 2 */
    HTTP_METHOD_UNBIND,            /* [RFC5842], Section 5 */
    HTTP_METHOD_UNCHECKOUT,        /* [RFC3253], Section 4.5 */
    HTTP_METHOD_UNLINK,            /* [RFC2068], Section 19.6.1.3 */
    HTTP_METHOD_UNLOCK,            /* [RFC4918], Section 9.11 */
    HTTP_METHOD_UPDATE,            /* [RFC3253], Section 7.1 */
    HTTP_METHOD_UPDATEREDIRECTREF, /* [RFC4437], Section 7 */
    HTTP_METHOD_VERSION_CONTROL    /* [RFC3253], Section 3.5 */
} http_method_t;

typedef enum { HTTP_VERSION_UNSET = -1, HTTP_VERSION_1_0, HTTP_VERSION_1_1 } http_version_t;

typedef struct {
    int key;

    const char *value;
} keyvalue;

typedef struct {
#ifdef HAVE_PCRE_H
    pcre *key;
    pcre_extra *key_extra;
#endif

    buffer *value;
} pcre_keyvalue;

typedef struct {
    pcre_keyvalue **kv;
    size_t used;
    size_t size;
} pcre_keyvalue_buffer;

猜你喜欢

转载自blog.csdn.net/caofengtao1314/article/details/82734579