reverting back the changes. causes core dump
[csql.git] / src / tools / redo.cxx
blob1d12c218139379343ccdf180d2728e430723e79a
1 /***************************************************************************
2 * Copyright (C) 2007 by www.databasecache.com *
3 * Contact: praba_tuty@databasecache.com *
4 * *
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. *
9 * *
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. *
14 * *
15 ***************************************************************************/
16 #include <os.h>
17 #include <Statement.h>
18 #include <SqlFactory.h>
19 #include <SqlStatement.h>
21 AbsSqlConnection *conn;
22 void *stmtBuckets = NULL;
23 bool list = false;
24 bool interactive=false;
25 char fileName[MAX_FILE_LEN];
27 int main(int argc, char **argv)
29 struct stat st;
30 strcpy(fileName, "");
31 int c = 0, opt=0;
32 while ((c = getopt(argc, argv, "f:ail?")) != EOF) {
33 switch (c) {
34 case '?' : { opt = 1; break; } //print help
35 case 'a' : { opt = 2; break; }
36 case 'i' : { interactive = true; break; }
37 case 'l' : { list = true; break; }
38 case 'f' : {strcpy(fileName , argv[optind - 1]); break;}
39 default: printf("Wrong args\n"); exit(1);
42 }//while options
43 if (2 !=opt) {
44 printf("This is an internal csql command with i and f <filename> options.");
45 exit(1);
47 char *verbose = os::getenv("CSQL_INTERACTIVE");
48 if (verbose !=NULL && strcmp(verbose, "true") == 0)
50 printf("VERBOSE ON %s\n", verbose);
51 interactive=true;
54 conn = SqlFactory::createConnection(CSqlDirect);
55 DbRetVal rv = conn->connect(I_USER, I_PASS);
56 if (rv != OK) {
57 printError(ErrNoConnection, "REDO: could not connect to DB.");
58 delete conn;
59 return 2;
62 if (strcmp(fileName, "") ==0) {
63 sprintf(fileName, "%s/csql.db.cur", Conf::config.getDbFile());
65 int fd = open(fileName, O_RDONLY);
66 if (-1 == fd) { conn->disconnect(); delete conn; return OK; }
67 if (fstat(fd, &st) == -1) {
68 printError(ErrSysInternal, "Unable to retrieve undo log file size");
69 close(fd);
70 conn->disconnect();
71 delete conn;
72 return 3;
74 if (st.st_size ==0) {
75 printError(ErrNote, "No Redo logs found during recovery");
76 SqlStatement::readAndPopulateStmts(conn, stmtBuckets, list, interactive);
77 close(fd);
78 conn->disconnect();
79 delete conn;
80 return 0;
82 SqlConnection *sCon = (SqlConnection*) conn;
83 if(!list) rv = sCon->getExclusiveLock();
84 //during connection close, this exclusive lock will be automatically released
85 if (rv != OK) {
86 close(fd);
87 conn->disconnect();
88 delete conn;
89 return 4;
91 void *startAddr = mmap(NULL, st.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
92 if (MAP_FAILED == startAddr) {
93 printf("Unable to read undo log file:mmap failed.\n");
94 conn->disconnect();
95 delete conn;
96 return 5;
98 rv = SqlStatement::readAndPopulateStmts(conn, stmtBuckets, list, interactive);
99 if (OK != rv)
101 printf("Unable to read stmt log file\n");
102 conn->disconnect();
103 delete conn;
104 return 6;
107 printf("Redo log filename is :%s\n", fileName);
108 char *iter = (char*)startAddr;
109 void *value = NULL;
110 int logType, eType;
111 int stmtID;
112 int txnID;
113 int len, ret, retVal =0;
114 int loglen;
115 char stmtString[SQL_STMT_LEN];
116 //printf("size of file %d\n", st.st_size);
117 while(true) {
118 //printf("OFFSET HERE %d\n", iter - (char*)startAddr);
119 if (iter - (char*)startAddr >= st.st_size) break;
120 logType = *(int*)iter;
121 if (logType == -1) { //prepare
122 iter = iter + sizeof(int);
123 txnID = *(int*) iter; iter += sizeof(int);
124 loglen = *(int*) iter; iter += sizeof(int);
125 stmtID = *(int*)iter;
126 iter = iter + sizeof(int);
127 len = *(int*)iter;
128 iter = iter + sizeof(int);
129 strncpy(stmtString, iter, len);
130 iter = iter + len;
131 if (list) {
132 printf("PREPARE: SID:%d %s\n", stmtID, stmtString);
133 continue;
135 AbsSqlStatement *stmt = SqlFactory::createStatement(CSqlDirect);
136 stmt->setConnection(conn);
137 if (interactive) printf("PREPARE %d : %s\n", stmtID, stmtString);
138 rv = stmt->prepare(stmtString);
139 if (rv != OK) {
140 printError(ErrSysInternal, "unable to prepare stmt:%s", stmtString);
141 retVal=1;
142 break;
144 SqlStatement *sqlStmt = (SqlStatement*)stmt;
145 sqlStmt->setLoading(true);
146 SqlStatement::addToHashTable(stmtID, stmt,stmtBuckets, stmtString);
148 else if(logType == -2) { //commit
149 conn->beginTrans();
150 iter = iter + sizeof(int);
151 txnID = *(int*) iter; iter += sizeof(int);
152 loglen = *(int*) iter; iter += sizeof(int);
153 char *curPtr = iter;
154 while(true) {
155 //printf("Iter length %d\n", iter - curPtr);
156 if (iter - (char*)startAddr >= st.st_size) {
157 //file end reached
158 //printf("Redo log file end\n");
159 retVal=0;
160 break;
162 stmtID = *(int*)iter;
163 //printf("stmtid %d\n", stmtID);
164 if (interactive) printf("EXEC %d :\n", stmtID);
165 iter = iter + sizeof(int);
166 eType = *(int*)iter;
167 //printf("eType is %d\n", eType);
168 AbsSqlStatement *stmt = NULL;
169 if (!list) {
170 stmt = SqlStatement::getStmtFromHashTable(stmtID,stmtBuckets);
171 if (NULL == stmt) {
172 printError(ErrSysInternal, "Unable to find in stmt hashtable");
173 retVal=2;
174 break;
177 if (0 == eType) { //execute type
178 iter = iter + sizeof(int);
179 if (list) {
180 printf("EXEC SID:%d TID:%d\n", stmtID, txnID);
181 if (*(int*)iter <0) break;
182 continue;
184 if (stmt) {
185 rv = stmt->execute(ret);
186 if (rv != OK) {
187 printError(ErrSysInternal, "unable to execute");
188 retVal=2;
189 break;
191 } else {
192 printError(ErrSysInternal, "statement not found for %d\n",stmtID);
194 if (*(int*)iter <0) break;
195 } else if ( 1 == eType) { //set type
196 iter=iter+sizeof(int);
197 int pos = *(int*) iter;
198 iter=iter+sizeof(int);
199 int isNull = *(int *) iter;
200 iter=iter+sizeof(int);
201 if (isNull == 0) {
202 DataType type = (DataType)(*(int*)iter);
203 iter=iter+sizeof(int);
204 int len = *(int*) iter;
205 iter=iter+sizeof(int);
206 value = iter;
207 iter=iter+len;
208 if (list) {
209 printf("SET SID:%d POS:%d ISNULL:FALSE TYPE:%d LEN:%d Value:", stmtID, pos, type, len);
210 AllDataType::printVal(value, type, len);
211 printf("\n");
212 if (*(int*)iter <0) break;
213 continue;
215 SqlStatement::setParamValues(stmt, pos, type, len, value);
216 } else {
217 if (list) {
218 printf("SET SID:%d POS:%d ISNULL:TRUE\n", stmtID, pos);
219 continue;
221 stmt->setNull(pos);
223 if (*(int*)iter <0) break;
226 conn->commit();
228 else if(logType == -3) { //free
229 iter = iter + sizeof(int);
230 txnID = *(int*) iter; iter += sizeof(int);
231 loglen = *(int*) iter; iter += sizeof(int);
232 stmtID = *(int*)iter;
233 iter = iter + sizeof(int);
234 if (list) {
235 printf("FREE SID:%d \n", stmtID);
236 continue;
238 if (interactive) printf("FREE %d:\n", stmtID);
239 AbsSqlStatement *stmt = SqlStatement::getStmtFromHashTable(stmtID,
240 stmtBuckets);
241 if (stmt) {
242 stmt->free();
243 delete stmt;
244 SqlStatement::removeFromHashTable(stmtID,stmtBuckets);
245 } else { printError(ErrSysInternal, "statement not found for %d\n",stmtID);}
247 else if(logType == -4) { //prepare and execute
248 iter = iter + sizeof(int);
249 txnID = *(int*) iter; iter += sizeof(int);
250 loglen = *(int*) iter; iter += sizeof(int);
251 stmtID = *(int*)iter;
252 iter = iter + sizeof(int);
253 len = *(int*)iter;
254 iter = iter + sizeof(int);
255 strncpy(stmtString, iter, len);
256 iter = iter + len;
257 if (list) {
258 printf("EXECDIRECT SID:%d TID:%d STMT:%s\n", stmtID, txnID, stmtString);
259 continue;
261 AbsSqlStatement *stmt = SqlFactory::createStatement(CSqlDirect);
262 if ( NULL == stmt) {
263 printError(ErrSysInternal, "unable to prepare:%s", stmtString);
264 retVal=3;
265 break;
267 stmt->setConnection(conn);
268 if (interactive) printf("EXECDIRECT %d : %s\n", stmtID, stmtString);
269 rv = stmt->prepare(stmtString);
270 if (rv != OK) {
271 printError(ErrSysInternal, "unable to prepare:%s", stmtString);
272 stmt->free();
273 delete stmt;
274 retVal=4;
275 break;
277 rv = stmt->execute(ret);
278 if (rv != OK) {
279 if (strlen(stmtString) > 6 &&
280 ( (strncasecmp(stmtString,"CREATE", 6) == 0) ||
281 (strncasecmp(stmtString,"DROP", 4) == 0) ||
282 (strncasecmp(stmtString,"RENAME", 6) == 0) ||
283 (strncasecmp(stmtString,"ALTER", 5) == 0)) ) {
285 // conn->disconnect();
286 // return OK;
287 continue;
289 printError(ErrSysInternal, "unable to execute %s", stmtString);
290 stmt->free();
291 retVal=5;
292 break;
294 stmt->free();
295 delete stmt;
296 }else{
297 printError(ErrSysInternal, "Redo log file corrupted: logType:%d", logType);
298 retVal=6;
299 break;
302 munmap((char*)startAddr, st.st_size);
303 close(fd);
304 if (!list) {
305 SqlStatement::filterAndWriteStmtLogs(stmtBuckets);
306 SqlStatement::freeAllStmtHandles(stmtBuckets);
308 conn->disconnect();
309 delete conn;
310 return retVal;