和上一次的現象差不多:資料量小時一切正常,稍微大一點monitord就會沒響應。
具體跟蹤之,發現如下現象:
(1)MonitorServer給monitord發送請求,一切都正常;但是沒有收到monitord返回的響應;
(2)monitord收到並解析請求,一切正常;
(3)monitord執行請求,一切正常;
(4)最後一步:monitord更新設定檔,逾時。
崩潰。。。
寫檔案居然會逾時?這得多大的資料量阿,俺們的資料量也沒達到這麼恐怖的底部呀?
廢話少說,扒開代碼一看,徹底拜服:
1 static int set_threshold_cfg() 2 { 3 ... 4 5 int i=0; 6 for(;i<num; i++) 7 { 8 ConfigSetKey(); 9 }10 ...11 }12 13 int ConfigSetKey(void *CFG_file, void *section, void *key, void *buf)14 { 15 FILE *fp1, *fp2; 16 char buf1[MAX_CFG_BUF + 1]; 17 int line_no, line_no1, n, ret, ret2; 18 char *tmpfname; 19 20 ret = ConfigGetKey(CFG_file, section, key, buf1); 21 if(ret <= CFG_ERR && ret != CFG_ERR_OPEN_FILE) return ret; 22 if(ret == CFG_ERR_OPEN_FILE || ret == CFG_SECTION_NOT_FOUND) 23 { 24 25 if((fp1 = fopen((char *)CFG_file, "a")) == NULL) 26 27 return CFG_ERR_CREATE_FILE; 28 29 if(fprintf(fp1, "%c%s%c\n", CFG_ssl, section, CFG_ssr) == EOF) 30 { 31 fclose(fp1); 32 return CFG_ERR_WRITE_FILE; 33 } 34 if(fprintf(fp1, "%s=%s\n", key, buf) == EOF) 35 { 36 fclose(fp1); 37 return CFG_ERR_WRITE_FILE; 38 } 39 fclose(fp1); 40 return CFG_OK; 41 } 42 if((tmpfname = tmpnam(NULL)) == NULL)43 {44 return CFG_ERR_CREATE_FILE; 45 }46 if((fp2 = fopen(tmpfname, "w")) == NULL)47 return CFG_ERR_CREATE_FILE; 48 ret2 = CFG_ERR_OPEN_FILE; 49 50 if((fp1 = fopen((char *)CFG_file, "rb")) == NULL) goto w_cfg_end; 51 52 if(ret == CFG_KEY_NOT_FOUND) 53 line_no1 = CFG_section_line_no; 54 else /* ret = CFG_OK */ 55 line_no1 = CFG_key_line_no - 1; 56 for(line_no = 0; line_no < line_no1; line_no++) 57 { 58 ret2 = CFG_ERR_READ_FILE; 59 n = FileGetLine(fp1, buf1, MAX_CFG_BUF); 60 if(n < 0) goto w_cfg_end; 61 ret2 = CFG_ERR_WRITE_FILE; 62 if(fprintf(fp2, "%s\n", buf1) == EOF) goto w_cfg_end; 63 } 64 if(ret != CFG_KEY_NOT_FOUND) 65 for( ; line_no < line_no1+CFG_key_lines; line_no++) 66 { 67 ret2 = CFG_ERR_READ_FILE; 68 n = FileGetLine(fp1, buf1, MAX_CFG_BUF); 69 if(n < 0) goto w_cfg_end; 70 } 71 ret2 = CFG_ERR_WRITE_FILE; 72 if(fprintf(fp2, "%s=%s\n", key, buf) == EOF) goto w_cfg_end; 73 while(1) 74 { 75 ret2 = CFG_ERR_READ_FILE; 76 n = FileGetLine(fp1, buf1, MAX_CFG_BUF); 77 if(n < -1) goto w_cfg_end; 78 if(n < 0) break; 79 ret2 = CFG_ERR_WRITE_FILE; 80 if(fprintf(fp2, "%s\n", buf1) == EOF) goto w_cfg_end; 81 } 82 ret2 = CFG_OK; 83 w_cfg_end: 84 if(fp1 != NULL) fclose(fp1); 85 if(fp2 != NULL) fclose(fp2); 86 if(ret2 == CFG_OK) 87 { 88 ret = FileCopy(tmpfname, CFG_file); 89 if(ret != 0) return CFG_ERR_CREATE_FILE; 90 } 91 remove(tmpfname); 92 return ret2; 93 }
每寫入一項配置就執行一次“開啟/關閉檔案”操作,算下來每個請求大概要執行幾萬次開啟/關閉檔案操作,逾時也就不奇怪了。
找到問題根源,就很好解決了:將寫設定檔函數重寫,只執行一次開啟/關閉檔案操作。具體過程略。