1 /***************************************************************************
2 * Copyright (C) 2007 by www.databasecache.com *
3 * Contact: praba_tuty@databasecache.com *
5 * This program is free software; you can redistribute it and/or modify *
6 * it under the terms of the GNU General Public License as published by *
7 * the Free Software Foundation; either version 2 of the License, or *
8 * (at your option) any later version. *
10 * This program is distributed in the hope that it will be useful, *
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
13 * GNU General Public License for more details. *
15 ***************************************************************************/
17 #include <Statement.h>
18 #include <SqlFactory.h>
19 #include <SqlStatement.h>
21 AbsSqlConnection
*conn
;
24 int applyOfflinelogs(char *fileName
, bool interactive
);
26 int main(int argc
, char **argv
)
29 char fileName
[MAX_FILE_LEN
];
32 while ((c
= getopt(argc
, argv
, "ai?")) != EOF
) {
34 case '?' : { opt
= 1; break; } //print help
35 case 'a' : { opt
= 2; break; }
36 case 'i' : { interactive
= 1; break; }
37 default: printf("Wrong args\n"); exit(1);
42 printf("This is an internal csql command.");
45 Conf::config
.readAllValues(os::getenv("CSQL_CONFIG_FILE"));
46 conn
= SqlFactory::createConnection(CSqlAdapter
);
47 DbRetVal rv
= conn
->connect(I_USER
, I_PASS
);
48 stmtBuckets
= malloc (STMT_BUCKET_SIZE
* sizeof(StmtBucket
));
49 memset(stmtBuckets
, 0, STMT_BUCKET_SIZE
* sizeof(StmtBucket
));
52 sprintf(fileName
, "%s/offlineLogFile.%d", Conf::config
.getDbFile(),
54 if (::access(fileName
, F_OK
) != 0) break;
55 int retval
= applyOfflinelogs(fileName
, interactive
);
56 if (retval
) { return retval
; }
57 printf("Applied logs from file: %s\n", fileName
);
60 printf("All the offline log files have been successfully applied.\n");
64 sprintf(fileName
,"%s/offlineLogFile.%d",Conf::config
.getDbFile(),
66 if (::access(fileName
, F_OK
) != 0) break;
67 sprintf(cmd
, "rm -f %s", fileName
);
68 int retval
= system(cmd
);
69 if (retval
) return retval
;
72 printf("All the applied log files have been successfully removed.\n");
74 recovery
.setStmtBucket(stmtBuckets
);
75 recovery
.freeAllStmtHandles();
81 int applyOfflinelogs(char *fileName
, bool interactive
)
84 printf("offline log filename is :%s\n", fileName
);
85 int fd
= open(fileName
, O_RDONLY
);
86 if (-1 == fd
) { return 0; }
87 if (fstat(fd
, &st
) == -1) {
88 printError(ErrSysInternal
, "Unable to retrieve undo log file size");
93 printError(ErrNote
, "No Redo logs found during recovery");
97 void *startAddr
= mmap(NULL
, st
.st_size
, PROT_READ
, MAP_PRIVATE
, fd
, 0);
98 if (MAP_FAILED
== startAddr
) {
99 printf("Unable to read undo log file:mmap failed.\n");
105 char *iter
= (char*)startAddr
;
110 int len
, ret
, retVal
=0;
112 char stmtString
[SQL_STMT_LEN
];
113 //printf("size of file %d\n", st.st_size);
115 recovery
.setStmtBucket(stmtBuckets
);
117 //printf("OFFSET HERE %d\n", iter - (char*)startAddr);
118 if (iter
- (char*)startAddr
>= st
.st_size
) break;
119 logType
= *(int*)iter
;
120 if (logType
== -1) { //prepare
121 iter
= iter
+ sizeof(int);
122 txnID
= *(int*) iter
; iter
+= sizeof(int);
123 loglen
= *(int*) iter
; iter
+= sizeof(int);
124 stmtID
= *(int*)iter
;
125 iter
= iter
+ sizeof(int);
127 iter
= iter
+ sizeof(int);
128 strncpy(stmtString
, iter
, len
);
130 //printf("PREPARE:%d %d %s\n", stmtID, len, stmtString);
131 AbsSqlStatement
*stmt
= SqlFactory::createStatement(CSqlAdapter
);
132 stmt
->setConnection(conn
);
133 if (interactive
) printf("PREPARE %d : %s\n", stmtID
, stmtString
);
134 rv
= stmt
->prepare(stmtString
);
136 printError(ErrSysInternal
, "unable to prepare stmt:%s", stmtString
);
140 recovery
.addToHashTable(stmtID
, stmt
, stmtString
);
142 else if(logType
== -2) { //commit
144 iter
= iter
+ sizeof(int);
145 txnID
= *(int*) iter
; iter
+= sizeof(int);
146 loglen
= *(int*) iter
; iter
+= sizeof(int);
149 //printf("Iter length %d\n", iter - curPtr);
150 if (iter
- (char*)startAddr
>= st
.st_size
) {
152 //printf("Redo log file end\n");
156 stmtID
= *(int*)iter
;
157 //printf("stmtid %d\n", stmtID);
158 if (interactive
) printf("EXEC %d :\n", stmtID
);
159 iter
= iter
+ sizeof(int);
161 //printf("eType is %d\n", eType);
162 AbsSqlStatement
*stmt
=
163 recovery
.getStmtFromHashTable(stmtID
);
164 if (0 == eType
) { //execute type
165 iter
= iter
+ sizeof(int);
166 //printf("EXEC: %d\n", stmtID);
168 rv
= stmt
->execute(ret
);
170 printError(ErrSysInternal
, "unable to execute");
175 printError(ErrSysInternal
, "statement not found for %d\n",stmtID
);
177 if (*(int*)iter
<0) break;
178 } else if ( 1 == eType
) { //set type
179 iter
=iter
+sizeof(int);
180 int pos
= *(int*) iter
;
181 iter
=iter
+sizeof(int);
182 DataType type
= (DataType
)(*(int*)iter
);
183 iter
=iter
+sizeof(int);
184 int len
= *(int*) iter
;
185 iter
=iter
+sizeof(int);
187 //AllDataType::printVal(value, type, len);
189 //printf("SET: %d %d %d %d\n", stmtID, pos, type, len);
190 SqlStatement::setParamValues(stmt
, pos
, type
, len
, value
);
191 if (*(int*)iter
<0) break;
196 else if(logType
== -3) { //free
197 iter
= iter
+ sizeof(int);
198 txnID
= *(int*) iter
; iter
+= sizeof(int);
199 loglen
= *(int*) iter
; iter
+= sizeof(int);
200 stmtID
= *(int*)iter
;
201 iter
= iter
+ sizeof(int);
202 if (interactive
) printf("FREE %d:\n", stmtID
);
203 AbsSqlStatement
*stmt
= recovery
.getStmtFromHashTable(stmtID
);
206 recovery
.removeFromHashTable(stmtID
);
207 } else { printError(ErrSysInternal
, "statement not found for %d\n",stmtID
);}
209 else if(logType
== -4) { //prepare and execute
210 iter
= iter
+ sizeof(int);
211 txnID
= *(int*) iter
; iter
+= sizeof(int);
212 loglen
= *(int*) iter
; iter
+= sizeof(int);
213 stmtID
= *(int*)iter
;
214 iter
= iter
+ sizeof(int);
216 iter
= iter
+ sizeof(int);
217 strncpy(stmtString
, iter
, len
);
218 stmtString
[len
+1] ='\0';
220 //printf("CREATE:%d %d %s\n", stmtID, len, stmtString);
221 AbsSqlStatement
*stmt
= SqlFactory::createStatement(CSqlAdapter
);
223 printError(ErrSysInternal
, "unable to prepare:%s", stmtString
);
227 stmt
->setConnection(conn
);
228 if (interactive
) printf("EXECDIRECT %d : %s\n", stmtID
, stmtString
);
229 rv
= stmt
->prepare(stmtString
);
231 printError(ErrSysInternal
, "unable to prepare:%s", stmtString
);
235 rv
= stmt
->execute(ret
);
237 if (strlen(stmtString
) > 6 &&
238 ( (strncasecmp(stmtString
,"CREATE", 6) == 0) ||
239 (strncasecmp(stmtString
,"DROP", 4) == 0)) ) {
240 // conn->disconnect();
244 printError(ErrSysInternal
, "unable to execute %s", stmtString
);
250 printError(ErrSysInternal
, "Redo log file corrupted: logType:%d", logType
);
255 munmap((char*)startAddr
, st
.st_size
);