Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit1b7fcde

Browse files
committed
添加 redis-check-aof.c 的注释
1 parent383c1a8 commit1b7fcde

File tree

1 file changed

+110
-1
lines changed

1 file changed

+110
-1
lines changed

‎src/redis-check-aof.c

Lines changed: 110 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,9 +42,17 @@
4242
sprintf(error, "0x%16llx: %s", (long long)epos, __buf); \
4343
}
4444

45+
// 保存错误信息
4546
staticcharerror[1024];
47+
48+
// 文件读取的当前偏移量
4649
staticoff_tepos;
4750

51+
/*
52+
* 确认 buf 是以 \r\n 结尾的新行。
53+
*
54+
* 确认成功返回 1 ,读入失败返回 0 ,并打印错误信息。
55+
*/
4856
intconsumeNewline(char*buf) {
4957
if (strncmp(buf,"\r\n",2)!=0) {
5058
ERROR("Expected \\r\\n, got: %02x%02x",buf[0],buf[1]);
@@ -53,32 +61,62 @@ int consumeNewline(char *buf) {
5361
return1;
5462
}
5563

64+
/*
65+
* 从 fp 中读入一个以 prefix 为前缀的 long 值,并将它保存到 *target 中。
66+
*
67+
* 读入成功返回 1 ,读入出错返回 0 ,并打印错误信息。
68+
*/
5669
intreadLong(FILE*fp,charprefix,long*target) {
5770
charbuf[128],*eptr;
71+
5872
epos=ftello(fp);
73+
74+
// 读入行
5975
if (fgets(buf,sizeof(buf),fp)==NULL) {
6076
return0;
6177
}
78+
79+
// 确保前缀相同
6280
if (buf[0]!=prefix) {
6381
ERROR("Expected prefix '%c', got: '%c'",buf[0],prefix);
6482
return0;
6583
}
84+
85+
// 将字符串转换成 long 值
6686
*target=strtol(buf+1,&eptr,10);
87+
6788
returnconsumeNewline(eptr);
6889
}
6990

91+
/*
92+
* 从 fp 中读取指定的字节,并将值保存到 *target 中。
93+
*
94+
* 如果读取的量和 length 参数不相同,那么返回 0 ,并打印错误信息。
95+
* 读取成功则返回 1 。
96+
*/
7097
intreadBytes(FILE*fp,char*target,longlength) {
7198
longreal;
99+
72100
epos=ftello(fp);
101+
73102
real=fread(target,1,length,fp);
74103
if (real!=length) {
75104
ERROR("Expected to read %ld bytes, got %ld bytes",length,real);
76105
return0;
77106
}
107+
78108
return1;
79109
}
80110

111+
/*
112+
* 读取字符串
113+
*
114+
* 读取成功函数返回 1 ,并将值保存在 target 指针中。
115+
* 失败返回 0 。
116+
*/
81117
intreadString(FILE*fp,char**target) {
118+
119+
// 读取字符串的长度
82120
longlen;
83121
*target=NULL;
84122
if (!readLong(fp,'$',&len)) {
@@ -87,69 +125,117 @@ int readString(FILE *fp, char** target) {
87125

88126
/* Increase length to also consume \r\n */
89127
len+=2;
128+
129+
// 为字符串分配空间
90130
*target= (char*)malloc(len);
131+
132+
// 读取内容
91133
if (!readBytes(fp,*target,len)) {
92134
return0;
93135
}
136+
137+
// 确认 \r\n
94138
if (!consumeNewline(*target+len-2)) {
95139
return0;
96140
}
141+
97142
(*target)[len-2]='\0';
143+
98144
return1;
99145
}
100146

147+
/*
148+
* 读取参数数量
149+
*
150+
* 读取成功函数返回 1 ,并将参数数量保存到 target 中。
151+
* 读取失败返回 0 。
152+
*/
101153
intreadArgc(FILE*fp,long*target) {
102154
returnreadLong(fp,'*',target);
103155
}
104156

157+
/*
158+
* 返回一个偏移量,这个偏移量可能是:
159+
*
160+
* 1)文件的末尾
161+
* 2)文件首次出现读入错误的地方
162+
* 3)文件第一个没有 EXEC 匹配的 MULTI 的位置
163+
*/
105164
off_tprocess(FILE*fp) {
106165
longargc;
107166
off_tpos=0;
108167
inti,multi=0;
109168
char*str;
110169

111170
while(1) {
171+
172+
// 定位到最后一个 MULTI 出现的偏移量
112173
if (!multi)pos=ftello(fp);
174+
175+
// 读取参数的个数
113176
if (!readArgc(fp,&argc))break;
114177

178+
// 遍历各个参数
179+
// 参数包括命令以及命令参数
180+
// 比如 SET key value
181+
// SET 就是第一个参数,而 key 和 value 就是第二和第三个参数
115182
for (i=0;i<argc;i++) {
183+
184+
// 读取参数
116185
if (!readString(fp,&str))break;
186+
187+
// 检查命令是否 MULTI 或者 EXEC
117188
if (i==0) {
118189
if (strcasecmp(str,"multi")==0) {
190+
// 记录一个 MULTI
191+
// 如果前面已经有一个 MULTI ,那么报错(MULTI 不应该嵌套)
119192
if (multi++) {
120193
ERROR("Unexpected MULTI");
121194
break;
122195
}
123196
}elseif (strcasecmp(str,"exec")==0) {
197+
// 清除一个 MULTI 记录
198+
// 如果前面没有 MULTI ,那么报错(MULTI 和 EXEC 应该一对对出现)
124199
if (--multi) {
125200
ERROR("Unexpected EXEC");
126201
break;
127202
}
128203
}
129204
}
205+
206+
// 释放
130207
free(str);
131208
}
132209

133-
/* Stop if the loop did not finish */
210+
/* Stop if the loop did not finish
211+
*
212+
* 如果 for 循环没有正常结束,那么跳出 while
213+
*/
134214
if (i<argc) {
135215
if (str)free(str);
136216
break;
137217
}
138218
}
139219

220+
// 文件读取完了,但是没有找到和 MULTI 对应的 EXEC
140221
if (feof(fp)&&multi&&strlen(error)==0) {
141222
ERROR("Reached EOF before reading EXEC for MULTI");
142223
}
224+
225+
// 如果有错误出现,那么打印错误
143226
if (strlen(error)>0) {
144227
printf("%s\n",error);
145228
}
229+
230+
// 返回偏移量
146231
returnpos;
147232
}
148233

149234
intmain(intargc,char**argv) {
150235
char*filename;
151236
intfix=0;
152237

238+
// 选项,如果不带 --fix 就只检查,不进行修复
153239
if (argc<2) {
154240
printf("Usage: %s [--fix] <file.aof>\n",argv[0]);
155241
exit(1);
@@ -167,30 +253,45 @@ int main(int argc, char **argv) {
167253
exit(1);
168254
}
169255

256+
// 打开指定文件
170257
FILE*fp=fopen(filename,"r+");
171258
if (fp==NULL) {
172259
printf("Cannot open file: %s\n",filename);
173260
exit(1);
174261
}
175262

263+
// 读取文件信息
176264
structredis_statsb;
177265
if (redis_fstat(fileno(fp),&sb)==-1) {
178266
printf("Cannot stat file: %s\n",filename);
179267
exit(1);
180268
}
181269

270+
// 取出文件的大小
182271
off_tsize=sb.st_size;
183272
if (size==0) {
184273
printf("Empty file: %s\n",filename);
185274
exit(1);
186275
}
187276

277+
// 如果文件出错,那么这个偏移量指向:
278+
// 1) 第一个不符合格式的位置
279+
// 2) 第一个没有 EXEC 对应的 MULTI 的位置
280+
// 如果文件没有出错,那么这个偏移量指向:
281+
// 3) 文件末尾
188282
off_tpos=process(fp);
283+
// 计算偏移量距离文件末尾有多远
189284
off_tdiff=size-pos;
190285
printf("AOF analyzed: size=%lld, ok_up_to=%lld, diff=%lld\n",
191286
(long long)size, (long long)pos, (long long)diff);
287+
288+
// 大于 0 表示未到达文件末尾,出错
192289
if (diff>0) {
290+
291+
// fix 模式:尝试修复文件
193292
if (fix) {
293+
294+
// 尝试从出错的位置开始,一直删除到文件的末尾
194295
charbuf[2];
195296
printf("This will shrink the AOF from %lld bytes, with %lld bytes, to %lld bytes\n",(long long)size,(long long)diff,(long long)pos);
196297
printf("Continue? [y/N]: ");
@@ -199,20 +300,28 @@ int main(int argc, char **argv) {
199300
printf("Aborting...\n");
200301
exit(1);
201302
}
303+
304+
// 删除不正确的内容
202305
if (ftruncate(fileno(fp),pos)==-1) {
203306
printf("Failed to truncate AOF\n");
204307
exit(1);
205308
}else {
206309
printf("Successfully truncated AOF\n");
207310
}
311+
312+
// 非 fix 模式:只报告文件不合法
208313
}else {
209314
printf("AOF is not valid\n");
210315
exit(1);
211316
}
317+
318+
// 等于 0 表示文件已经顺利读完,无错
212319
}else {
213320
printf("AOF is valid\n");
214321
}
215322

323+
// 关闭文件
216324
fclose(fp);
325+
217326
return0;
218327
}

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp