]>
git.saurik.com Git - redis.git/blob - src/redis-check-aof.c
2 * Copyright (c) 2009-2012, Pieter Noordhuis <pcnoordhuis at gmail dot com>
3 * Copyright (c) 2009-2012, Salvatore Sanfilippo <antirez at gmail dot com>
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions are met:
9 * * Redistributions of source code must retain the above copyright notice,
10 * this list of conditions and the following disclaimer.
11 * * Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * * Neither the name of Redis nor the names of its contributors may be used
15 * to endorse or promote products derived from this software without
16 * specific prior written permission.
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
22 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
23 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
24 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
25 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
26 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28 * POSSIBILITY OF SUCH DAMAGE.
39 #define ERROR(...) { \
41 sprintf(__buf, __VA_ARGS__); \
42 sprintf(error, "0x%16llx: %s", (long long)epos, __buf); \
45 static char error
[1024];
48 int consumeNewline(char *buf
) {
49 if (strncmp(buf
,"\r\n",2) != 0) {
50 ERROR("Expected \\r\\n, got: %02x%02x",buf
[0],buf
[1]);
56 int readLong(FILE *fp
, char prefix
, long *target
) {
59 if (fgets(buf
,sizeof(buf
),fp
) == NULL
) {
62 if (buf
[0] != prefix
) {
63 ERROR("Expected prefix '%c', got: '%c'",buf
[0],prefix
);
66 *target
= strtol(buf
+1,&eptr
,10);
67 return consumeNewline(eptr
);
70 int readBytes(FILE *fp
, char *target
, long length
) {
73 real
= fread(target
,1,length
,fp
);
75 ERROR("Expected to read %ld bytes, got %ld bytes",length
,real
);
81 int readString(FILE *fp
, char** target
) {
84 if (!readLong(fp
,'$',&len
)) {
88 /* Increase length to also consume \r\n */
90 *target
= (char*)malloc(len
);
91 if (!readBytes(fp
,*target
,len
)) {
94 if (!consumeNewline(*target
+len
-2)) {
97 (*target
)[len
-2] = '\0';
101 int readArgc(FILE *fp
, long *target
) {
102 return readLong(fp
,'*',target
);
105 off_t
process(FILE *fp
) {
112 if (!multi
) pos
= ftello(fp
);
113 if (!readArgc(fp
, &argc
)) break;
115 for (i
= 0; i
< argc
; i
++) {
116 if (!readString(fp
,&str
)) break;
118 if (strcasecmp(str
, "multi") == 0) {
120 ERROR("Unexpected MULTI");
123 } else if (strcasecmp(str
, "exec") == 0) {
125 ERROR("Unexpected EXEC");
133 /* Stop if the loop did not finish */
140 if (feof(fp
) && multi
&& strlen(error
) == 0) {
141 ERROR("Reached EOF before reading EXEC for MULTI");
143 if (strlen(error
) > 0) {
144 printf("%s\n", error
);
149 int main(int argc
, char **argv
) {
154 printf("Usage: %s [--fix] <file.aof>\n", argv
[0]);
156 } else if (argc
== 2) {
158 } else if (argc
== 3) {
159 if (strcmp(argv
[1],"--fix") != 0) {
160 printf("Invalid argument: %s\n", argv
[1]);
166 printf("Invalid arguments\n");
170 FILE *fp
= fopen(filename
,"r+");
172 printf("Cannot open file: %s\n", filename
);
176 struct redis_stat sb
;
177 if (redis_fstat(fileno(fp
),&sb
) == -1) {
178 printf("Cannot stat file: %s\n", filename
);
182 off_t size
= sb
.st_size
;
184 printf("Empty file: %s\n", filename
);
188 off_t pos
= process(fp
);
189 off_t diff
= size
-pos
;
190 printf("AOF analyzed: size=%lld, ok_up_to=%lld, diff=%lld\n",
191 (long long) size
, (long long) pos
, (long long) diff
);
195 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
);
196 printf("Continue? [y/N]: ");
197 if (fgets(buf
,sizeof(buf
),stdin
) == NULL
||
198 strncasecmp(buf
,"y",1) != 0) {
199 printf("Aborting...\n");
202 if (ftruncate(fileno(fp
), pos
) == -1) {
203 printf("Failed to truncate AOF\n");
206 printf("Successfully truncated AOF\n");
209 printf("AOF is not valid\n");
213 printf("AOF is valid\n");