Redis源碼解析(十六)--- config設定檔

來源:互聯網
上載者:User

標籤:nosql資料庫   記憶體資料庫   redis   

          每個系統都會有類似一個config設定檔,config檔案裡的內容想想都知道,一定就是那麼一些固定的一行行的屬性代碼了,今天在看redis代碼中的config屬性,那拉下來的一筆,的確多,目測在50至100個屬性左右。如果就此將config每個屬性代表什麼意思不是我的風格,也一定是很乏味的,所以我的特點就是在代碼中去理解程式員在寫這類代碼時的思路,和茫茫代碼中的亮點。我們知道,redis啟動並執行環境包括很多種的,windows,Linux,mac os等等,不同的作業系統,當然有些屬性就不能支援了,所以在redis中的config.h標頭檔中跟據電腦所屬於的作業系統,做了很多的預先處理,比如說,在Linux等系統上,是可以支援修改進程名稱的:

/* Check if we can use setproctitle(). * BSD systems have support for it, we provide an implementation for * Linux and osx. *//* 檢查是否能調用setproctitle(),這個方法是Linux上修改進程名稱的方法 *//* 這裡通過判斷是否是BSD系統,BSD是Berkeley Systems Distrobution的縮寫,是一種UNIX版本 */#if (defined __NetBSD__ || defined __FreeBSD__ || defined __OpenBSD__)#define USE_SETPROCTITLE#endif#if (defined __linux || defined __APPLE__)#define USE_SETPROCTITLE#define INIT_SETPROCTITLE_REPLACEMENTvoid spt_init(int argc, char *argv[]);void setproctitle(const char *fmt, ...);#endif
當然這隻是我提到的一點,也就是說,redis在異構系統的處理上,考慮的還是非常周全的。我們主要看看config主要的操作檔案,先看看裡面的一些API:

 /* Config file API */int yesnotoi(char *s) /* 判斷字元是否為yes */void appendServerSaveParams(time_t seconds, int changes) /* 追加server save參數 */void resetServerSaveParams(void) /* 重設server的save參數,即釋放server的serverParams */void loadServerConfigFromString(char *config) /* 從字串中載入server屬性配置 */void loadServerConfig(char *filename, char *options) /* 從檔案中載入server配置 */void configSetCommand(redisClient *c) /* 根據redisClient中的參數設定server的配置 */#define config_get_string_field(_name,_var) /* 宏定義了擷取字串範圍的方法 */#define config_get_bool_field(_name,_var) /* 宏定義了擷取布爾範圍的方法,值在這裡值為yes或no */#define config_get_numerical_field(_name,_var) /* 宏定義了擷取數字類型範圍的方法 */void configGetCommand(redisClient *c) /* 擷取配置資訊命令,以Replay給用戶端的方式 */void rewriteConfigAppendLine(struct rewriteConfigState *state, sds line) /* 添加配置字串行 */void rewriteConfigAddLineNumberToOption(struct rewriteConfigState *state, sds option, int linenum) /* 添加字典line-option */void rewriteConfigMarkAsProcessed(struct rewriteConfigState *state, char *option) /* rewriteConfigState重寫option選項 */struct rewriteConfigState *rewriteConfigReadOldFile(char *path) /* 讀取老設定檔資訊,檔案如果不可讀或不存在,返回NULL */void rewriteConfigRewriteLine(struct rewriteConfigState *state, char *option, sds line, int force) /* 是否覆蓋configline */int rewriteConfigFormatMemory(char *buf, size_t len, long long bytes) /* 格式化byte大小的顯示,避免long long 類型超長的顯示 */void rewriteConfigBytesOption(struct rewriteConfigState *state, char *option, long long value, long long defvalue) /* 往config中寫入某類型配置,後面的幾個方法類似 */void rewriteConfigYesNoOption(struct rewriteConfigState *state, char *option, int value, int defvalue) /* 同上 */void rewriteConfigStringOption(struct rewriteConfigState *state, char *option, char *value, char *defvalue) /* 同上 */void rewriteConfigNumericalOption(struct rewriteConfigState *state, char *option, long long value, long long defvalue) /* 同上 */void rewriteConfigOctalOption(struct rewriteConfigState *state, char *option, int value, int defvalue) /* 同上 */void rewriteConfigEnumOption(struct rewriteConfigState *state, char *option, int value, ...) /* 同上 */void rewriteConfigSyslogfacilityOption(struct rewriteConfigState *state) /* 同上 */void rewriteConfigSaveOption(struct rewriteConfigState *state) /* 同上 */void rewriteConfigDirOption(struct rewriteConfigState *state) /* 同上 */void rewriteConfigSlaveofOption(struct rewriteConfigState *state) /* 同上 */void rewriteConfigNotifykeyspaceeventsOption(struct rewriteConfigState *state) /* 同上 */void rewriteConfigClientoutputbufferlimitOption(struct rewriteConfigState *state) /* 同上 */void rewriteConfigBindOption(struct rewriteConfigState *state) /* 同上 */sds rewriteConfigGetContentFromState(struct rewriteConfigState *state) /* confifstate中擷取配置資訊字串 */void rewriteConfigReleaseState(struct rewriteConfigState *state) /* configstate釋放空間 */void rewriteConfigRemoveOrphaned(struct rewriteConfigState *state) /* 置空state 的line配置 */int rewriteConfigOverwriteFile(char *configfile, sds content) /* 字串屬性寫入覆蓋源檔案 */int rewriteConfig(char *path) /* 將當前的屬性讀入到檔案中,步驟:(1).將當前server屬性讀入configstate(2).configstate屬性變為字串(3).將字串寫入檔案 */void configCommand(redisClient *c) /* 用戶端config命令調用方法 */
上面的API的數量確實有點恐怖,我大體總結一下,在config.c中的主要操作:

1.從config設定檔中讀取配置到server屬性中

2.將當前server的設定的屬性寫入配置中

上面的其他方法都是為上面的2個要求服務的。所以redis在這裡設計一個叫rewriteConfigState的結構體角色,裡面儲存了屬性配置的字串數組,一個字串數組代表一種屬性設定。比如現在要把當前的配置讀入設定檔中操作:

int rewriteConfig(char *path) /* 將當前的屬性讀入到檔案中,步驟:(1).將當前server屬性讀入configstate(2).configstate屬性變為字串(3).將字串寫入檔案 */
下面看看redis代碼中的這個configstate結構體的構造:

/* The config rewrite state. */struct rewriteConfigState {//這裡存放著option-line的映射    dict *option_to_line; /* Option -> list of config file lines map */    dict *rewritten;      /* Dictionary of already processed options */    //當前設定檔中的行數    int numlines;         /* Number of lines in current config */    //當前行字串    sds *lines;           /* Current lines as an array of sds strings */    int has_tail;         /* True if we already added directives that were                             not present in the original config file. */};
其中的lines就是具體的屬性,第一個opition-line的映射指的是哪行對應什麼屬性名稱。在config操作檔案中,還提到了一個“maxmemory”的概念,中文意思可以瞭解為“最大記憶‘:

/* We use the following dictionary type to store where a configuration * option is mentioned in the old configuration file, so it's * like "maxmemory" -> list of line numbers (first line is zero). *//* 下面定義了幾個字典類型用來儲存老的設定檔中的一些資訊,像記錄類似,like "maxmemory" */
也就是在redis檔案中,可以存在老的設定檔,舊的屬性可以通過老檔案讀入再次寫入新配置中,達到了記錄曆史配置記錄的作用。老設定檔讀出的屬性同樣是存在於中間的configstate結構體中:

/* Read the old file, split it into lines to populate a newly created * config rewrite state, and return it to the caller. * * If it is impossible to read the old file, NULL is returned. * If the old file does not exist at all, an empty state is returned. *//* 讀取老設定檔資訊,檔案如果不可讀或不存在,返回NULL */struct rewriteConfigState *rewriteConfigReadOldFile(char *path) {    FILE *fp = fopen(path,"r");    struct rewriteConfigState *state = zmalloc(sizeof(*state));    char buf[REDIS_CONFIGLINE_MAX+1];    int linenum = -1;    if (fp == NULL && errno != ENOENT) return NULL;    state->option_to_line = dictCreate(&optionToLineDictType,NULL);    state->rewritten = dictCreate(&optionSetDictType,NULL);    state->numlines = 0;    state->lines = NULL;    state->has_tail = 0;    if (fp == NULL) return state;    /* Read the old file line by line, populate the state. */    while(fgets(buf,REDIS_CONFIGLINE_MAX+1,fp) != NULL) {        int argc;        sds *argv;        sds line = sdstrim(sdsnew(buf),"\r\n\t ");        linenum++; /* Zero based, so we init at -1 */        /* Handle comments and empty lines. */        //處理注釋和空行        if (line[0] == '#' || line[0] == '\0') {            if (!state->has_tail && !strcmp(line,REDIS_CONFIG_REWRITE_SIGNATURE))                state->has_tail = 1;            rewriteConfigAppendLine(state,line);            continue;        }        /* Not a comment, split into arguments. */        argv = sdssplitargs(line,&argc);        if (argv == NULL) {            /* Apparently the line is unparsable for some reason, for             * instance it may have unbalanced quotes. Load it as a             * comment. */            sds aux = sdsnew("# ??? ");            aux = sdscatsds(aux,line);            sdsfree(line);            //將老的配置屬性讀入configstate結構體            rewriteConfigAppendLine(state,aux);            continue;        }        sdstolower(argv[0]); /* We only want lowercase config directives. */        /* Now we populate the state according to the content of this line.         * Append the line and populate the option -> line numbers map. */        rewriteConfigAppendLine(state,line);        rewriteConfigAddLineNumberToOption(state,argv[0],linenum);        sdsfreesplitres(argv,argc);    }    fclose(fp);        //返回configstate,裡面記錄了一些老的設定檔中的配置行資訊    return state;}
又一次用到了configstate的結構體。小小config檔案也存在我們意想不到的的設計。

Redis源碼解析(十六)--- config設定檔

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.