国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 學(xué)院 > 開發(fā)設(shè)計 > 正文

redis-cli源碼分析

2019-11-09 13:35:09
字體:
供稿:網(wǎng)友

redis-cli中有兩個重要的結(jié)構(gòu)體,一個是redisContext與一個是config

typedef struct redisContext { int err; /* Error flags, 0 when there is no error */ char errstr[128]; /* String rePResentation of error when applicable */ int fd;//socket fd int flags; char *obuf; /* Write buffer */ redisReader *reader; /* Protocol reader */} redisContext;

redisContext跟redis-cli與redis server的tcp連接相關(guān)配置 config是redis-cli運行的配置文件,有初始化默認配置,也可以通過運行的時候傳遞參數(shù)修改配置

static struct config { aeEventLoop *el; const char *hostip; int hostport; const char *hostsocket; int numclients; int liveclients; int requests; int requests_issued; int requests_finished; int keysize; int datasize; int randomkeys; int randomkeys_keyspacelen; int keepalive; int pipeline; int showerrors; long long start; long long totlatency; long long *latency; const char *title; list *clients; int quiet; int csv; int loop; int idlemode; int dbnum; sds dbnumstr; char *tests; char *auth;} config;

在main函數(shù)中,首先對config結(jié)構(gòu)體中的配置進行初始化。 其中,config結(jié)構(gòu)體中sds是redis自定義的字符串數(shù)據(jù)結(jié)構(gòu),定義為typedef char* sds 配置spectrum_palette和spectrum_palette size兩個全局變量懷疑與cli命令行中的提示顏色有關(guān) 使用isatty函數(shù)判斷是否連接的是終端,從而配置config.output為OUTPUT_RAW或者OUTPUT_STANDARD 使用parSEOption(argc,argv)通過運行程序攜帶參數(shù)對config進行進一步配置 config配置完后開始根據(jù)配置配模式

1. latency mode 2. latency distribution mode 3. slave mode 4. get RDB mode 5. Pipe mode 6. stat mode 7. scan mode 8. LRU mode 9. Intrinsic latency mode

如果沒有任何附加命令,則運行默認的交互模式(interactive mode) /* Ignore SIGPIPE in interactive mode to force a reconnect */ signal(SIGPIPE, SIG_IGN);//忽略sigpipe,如果嘗試連接兩次已經(jīng)關(guān)閉的socket會導(dǎo)致sigpipe,告訴進程這個連接已經(jīng)斷開了,不要再寫了,一般客戶端默認退出,但是此處忽略SIGPIPE信號 /* Note that in repl mode we don’t abort on connection error. * A new attempt will be performed for every command send. */ cliConnect(0); repl(); 使用cliConnect(0)連接redis server服務(wù)器 cliConnect(0)中,使用anetKeepAlive運用TCP_KEEPALIVE選項防止超時

連接上redis server之后,調(diào)用repl(),開始讀取stdin運行redis命令 redpl中,首先設(shè)置是否接收多命令形式,然后初始化設(shè)置處理commond 命令行的回調(diào)函數(shù) 通過循環(huán)調(diào)用linenoise函數(shù),得到輸入的commond命令 linenoise有三種模式noTTY,unSuportedTerm,raw模式,一般使用的是raw模式 在linenoiseraw模式中,使用linenoiseEdit函數(shù)對每次輸入進行處理,從而達到較為友好的交互

static int linenoiseEdit(int stdin_fd, int stdout_fd, char *buf, size_t buflen, const char *prompt){ struct linenoiseState l; /* Populate the linenoise state that we pass to functions implementing * specific editing functionalities. */ l.ifd = stdin_fd; l.ofd = stdout_fd; l.buf = buf; l.buflen = buflen; l.prompt = prompt; l.plen = strlen(prompt); l.oldpos = l.pos = 0; l.len = 0; l.cols = getColumns(stdin_fd, stdout_fd); l.maxrows = 0; l.history_index = 0; /* Buffer starts empty. */ l.buf[0] = '/0'; l.buflen--; /* Make sure there is always space for the nulterm */ /* The latest history entry is always our current buffer, that * initially is just an empty string. */ linenoiseHistoryAdd(""); if (write(l.ofd,prompt,l.plen) == -1) return -1; while(1) { char c; int nread; char seq[3]; nread = read(l.ifd,&c,1); if (nread <= 0) return l.len; /* Only autocomplete when the callback is set. It returns < 0 when * there was an error reading from fd. Otherwise it will return the * character that should be handled next. */ if (c == 9 && completionCallback != NULL) { c = completeLine(&l); /* Return on errors */ if (c < 0) return l.len; /* Read next character when 0 */ if (c == 0) continue; } switch(c) { case ENTER: /* enter */ history_len--; free(history[history_len]); if (mlmode) linenoiseEditMoveEnd(&l); if (hintsCallback) { /* Force a refresh without hints to leave the previous * line as the user typed it after a newline. */ linenoiseHintsCallback *hc = hintsCallback; hintsCallback = NULL; refreshLine(&l); hintsCallback = hc; } return (int)l.len; case CTRL_C: /* ctrl-c */ errno = EAGAIN; return -1; case BACKSPACE: /* backspace */ case 8: /* ctrl-h */ linenoiseEditBackspace(&l); break; case CTRL_D: /* ctrl-d, remove char at right of cursor, or if the line is empty, act as end-of-file. */ if (l.len > 0) { linenoiseEditDelete(&l); } else { history_len--; free(history[history_len]); return -1; } break; case CTRL_T: /* ctrl-t, swaps current character with previous. */ if (l.pos > 0 && l.pos < l.len) { int aux = buf[l.pos-1]; buf[l.pos-1] = buf[l.pos]; buf[l.pos] = aux; if (l.pos != l.len-1) l.pos++; refreshLine(&l); } break; case CTRL_B: /* ctrl-b */ linenoiseEditMoveLeft(&l); break; case CTRL_F: /* ctrl-f */ linenoiseEditMoveRight(&l); break; case CTRL_P: /* ctrl-p */ linenoiseEditHistoryNext(&l, LINENOISE_HISTORY_PREV); break; case CTRL_N: /* ctrl-n */ linenoiseEditHistoryNext(&l, LINENOISE_HISTORY_NEXT); break; case ESC: /* escape sequence */ /* Read the next two bytes representing the escape sequence. * Use two calls to handle slow terminals returning the two * chars at different times. */ if (read(l.ifd,seq,1) == -1) break; if (read(l.ifd,seq+1,1) == -1) break; /* ESC [ sequences. */ if (seq[0] == '[') { if (seq[1] >= '0' && seq[1] <= '9') { /* Extended escape, read additional byte. */ if (read(l.ifd,seq+2,1) == -1) break; if (seq[2] == '~') { switch(seq[1]) { case '3': /* Delete key. */ linenoiseEditDelete(&l); break; } } } else { switch(seq[1]) { case 'A': /* Up */ linenoiseEditHistoryNext(&l, LINENOISE_HISTORY_PREV); break; case 'B': /* Down */ linenoiseEditHistoryNext(&l, LINENOISE_HISTORY_NEXT); break; case 'C': /* Right */ linenoiseEditMoveRight(&l); break; case 'D': /* Left */ linenoiseEditMoveLeft(&l); break; case 'H': /* Home */ linenoiseEditMoveHome(&l); break; case 'F': /* End*/ linenoiseEditMoveEnd(&l); break; } } } /* ESC O sequences. */ else if (seq[0] == 'O') { switch(seq[1]) { case 'H': /* Home */ linenoiseEditMoveHome(&l); break; case 'F': /* End*/ linenoiseEditMoveEnd(&l); break; } } break; default: if (linenoiseEditInsert(&l,c)) return -1; break; case CTRL_U: /* Ctrl+u, delete the whole line. */ buf[0] = '/0'; l.pos = l.len = 0; refreshLine(&l); break; case CTRL_K: /* Ctrl+k, delete from current to end of line. */ buf[l.pos] = '/0'; l.len = l.pos; refreshLine(&l); break; case CTRL_A: /* Ctrl+a, go to the start of the line */ linenoiseEditMoveHome(&l); break; case CTRL_E: /* ctrl+e, go to the end of the line */ linenoiseEditMoveEnd(&l); break; case CTRL_L: /* ctrl+l, clear screen */ linenoiseClearScreen(); refreshLine(&l); break; case CTRL_W: /* ctrl+w, delete previous Word */ linenoiseEditDeletePrevWord(&l); break; } } return l.len;}

在得到cli命令字符串后,先對把這些命令存到歷史文件里面,需要對該命令進行語義的分析,包括quit,exit,restart,connect,clear等等,然后進行相對應(yīng)的操作。 如果是與redis server相關(guān)的命令,則通過issueCommandRepeat函數(shù)發(fā)送和接收數(shù)據(jù)

static int issueCommandRepeat(int argc, char **argv, long repeat) { while (1) { config.cluster_reissue_command = 0; if (cliSendCommand(argc,argv,repeat) != REDIS_OK) { cliConnect(1); /* If we still cannot send the command print error. * We'll try to reconnect the next time. */ if (cliSendCommand(argc,argv,repeat) != REDIS_OK) { cliPrintContextError(); return REDIS_ERR; } } /* Issue the command again if we got redirected in cluster mode */ if (config.cluster_mode && config.cluster_reissue_command) { cliConnect(1); } else { break; } } return REDIS_OK;}
發(fā)表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發(fā)表
主站蜘蛛池模板: 河间市| 资溪县| 大渡口区| 云霄县| 黑水县| 夹江县| 漾濞| 新邵县| 天柱县| 荥经县| 贡嘎县| 南城县| 南投市| 武定县| 北京市| 新乡市| 和静县| 东乡族自治县| 手游| 西藏| 罗定市| 昭平县| 隆安县| 太康县| 碌曲县| 昭平县| 长岭县| 忻州市| 贡嘎县| 大庆市| 吴忠市| 承德县| 肇源县| 平和县| 新闻| 东辽县| 景谷| 方城县| 伊金霍洛旗| 随州市| 木里|