关键词搜索

源码搜索 ×
×

漫话Redis源码之三十

发布2021-12-12浏览523次

详情内容

几个读取和函数,挺直接明了,在处理边界问题和异常情况时,尤其要小心:

  1. int readLong(FILE *fp, char prefix, long *target) {
  2. char buf[128], *eptr;
  3. epos = ftello(fp);
  4. if (fgets(buf,sizeof(buf),fp) == NULL) {
  5. return 0;
  6. }
  7. if (buf[0] != prefix) {
  8. ERROR("Expected prefix '%c', got: '%c'",prefix,buf[0]);
  9. return 0;
  10. }
  11. *target = strtol(buf+1,&eptr,10);
  12. return consumeNewline(eptr);
  13. }
  14. int readBytes(FILE *fp, char *target, long length) {
  15. long real;
  16. epos = ftello(fp);
  17. real = fread(target,1,length,fp);
  18. if (real != length) {
  19. ERROR("Expected to read %ld bytes, got %ld bytes",length,real);
  20. return 0;
  21. }
  22. return 1;
  23. }
  24. int readString(FILE *fp, char** target) {
  25. long len;
  26. *target = NULL;
  27. if (!readLong(fp,'$',&len)) {
  28. return 0;
  29. }
  30. /* Increase length to also consume \r\n */
  31. len += 2;
  32. *target = (char*)zmalloc(len);
  33. if (!readBytes(fp,*target,len)) {
  34. return 0;
  35. }
  36. if (!consumeNewline(*target+len-2)) {
  37. return 0;
  38. }
  39. (*target)[len-2] = '\0';
  40. return 1;
  41. }
  42. int readArgc(FILE *fp, long *target) {
  43. return readLong(fp,'*',target);
  44. }
  45. off_t process(FILE *fp) {
  46. long argc;
  47. off_t pos = 0;
  48. int i, multi = 0;
  49. char *str;
  50. while(1) {
  51. if (!multi) pos = ftello(fp);
  52. if (!readArgc(fp, &argc)) break;
  53. for (i = 0; i < argc; i++) {
  54. if (!readString(fp,&str)) break;
  55. if (i == 0) {
  56. if (strcasecmp(str, "multi") == 0) {
  57. if (multi++) {
  58. ERROR("Unexpected MULTI");
  59. break;
  60. }
  61. } else if (strcasecmp(str, "exec") == 0) {
  62. if (--multi) {
  63. ERROR("Unexpected EXEC");
  64. break;
  65. }
  66. }
  67. }
  68. zfree(str);
  69. }
  70. /* Stop if the loop did not finish */
  71. if (i < argc) {
  72. if (str) zfree(str);
  73. break;
  74. }
  75. }
  76. if (feof(fp) && multi && strlen(error) == 0) {
  77. ERROR("Reached EOF before reading EXEC for MULTI");
  78. }
  79. if (strlen(error) > 0) {
  80. printf("%s\n", error);
  81. }
  82. return pos;
  83. }
  84. int redis_check_aof_main(int argc, char **argv) {
  85. char *filename;
  86. int fix = 0;
  87. if (argc < 2) {
  88. printf("Usage: %s [--fix] <file.aof>\n", argv[0]);
  89. exit(1);
  90. } else if (argc == 2) {
  91. filename = argv[1];
  92. } else if (argc == 3) {
  93. if (strcmp(argv[1],"--fix") != 0) {
  94. printf("Invalid argument: %s\n", argv[1]);
  95. exit(1);
  96. }
  97. filename = argv[2];
  98. fix = 1;
  99. } else {
  100. printf("Invalid arguments\n");
  101. exit(1);
  102. }
  103. FILE *fp = fopen(filename,"r+");
  104. if (fp == NULL) {
  105. printf("Cannot open file: %s\n", filename);
  106. exit(1);
  107. }
  108. struct redis_stat sb;
  109. if (redis_fstat(fileno(fp),&sb) == -1) {
  110. printf("Cannot stat file: %s\n", filename);
  111. exit(1);
  112. }
  113. off_t size = sb.st_size;
  114. if (size == 0) {
  115. printf("Empty file: %s\n", filename);
  116. exit(1);
  117. }
  118. /* This AOF file may have an RDB preamble. Check this to start, and if this
  119. * is the case, start processing the RDB part. */
  120. if (size >= 8) { /* There must be at least room for the RDB header. */
  121. char sig[5];
  122. int has_preamble = fread(sig,sizeof(sig),1,fp) == 1 &&
  123. memcmp(sig,"REDIS",sizeof(sig)) == 0;
  124. rewind(fp);
  125. if (has_preamble) {
  126. printf("The AOF appears to start with an RDB preamble.\n"
  127. "Checking the RDB preamble to start:\n");
  128. if (redis_check_rdb_main(argc,argv,fp) == C_ERR) {
  129. printf("RDB preamble of AOF file is not sane, aborting.\n");
  130. exit(1);
  131. } else {
  132. printf("RDB preamble is OK, proceeding with AOF tail...\n");
  133. }
  134. }
  135. }
  136. off_t pos = process(fp);
  137. off_t diff = size-pos;
  138. printf("AOF analyzed: size=%lld, ok_up_to=%lld, ok_up_to_line=%lld, diff=%lld\n",
  139. (long long) size, (long long) pos, line, (long long) diff);
  140. if (diff > 0) {
  141. if (fix) {
  142. char buf[2];
  143. 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);
  144. printf("Continue? [y/N]: ");
  145. if (fgets(buf,sizeof(buf),stdin) == NULL ||
  146. strncasecmp(buf,"y",1) != 0) {
  147. printf("Aborting...\n");
  148. exit(1);
  149. }
  150. if (ftruncate(fileno(fp), pos) == -1) {
  151. printf("Failed to truncate AOF\n");
  152. exit(1);
  153. } else {
  154. printf("Successfully truncated AOF\n");
  155. }
  156. } else {
  157. printf("AOF is not valid. "
  158. "Use the --fix option to try fixing it.\n");
  159. exit(1);
  160. }
  161. } else {
  162. printf("AOF is valid\n");
  163. }
  164. fclose(fp);
  165. exit(0);
  166. }

相关技术文章

点击QQ咨询
开通会员
返回顶部
×
微信扫码支付
微信扫码支付
确定支付下载
请使用微信描二维码支付
×

提示信息

×

选择支付方式

  • 微信支付
  • 支付宝付款
确定支付下载