<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                ThinkChat2.0新版上線,更智能更精彩,支持會話、畫圖、視頻、閱讀、搜索等,送10W Token,即刻開啟你的AI之旅 廣告
                ? ? ? ? 每個系統都會有類似一個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_REPLACEMENT void 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文件也存在我們意想不到的的設計。
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看