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>
22 AbsSqlConnection
*conn
;
25 int applyOfflinelogs(char *fileName
, bool interactive
);
27 int main(int argc
, char **argv
)
30 char fileName
[MAX_FILE_LEN
];
33 while ((c
= getopt(argc
, argv
, "ai?")) != EOF
) {
35 case '?' : { opt
= 1; break; } //print help
36 case 'a' : { opt
= 2; break; }
37 case 'i' : { interactive
= 1; break; }
38 default: printf("Wrong args\n"); exit(1);
43 printf("This is an internal csql command.");
46 Conf::config
.readAllValues(os::getenv("CSQL_CONFIG_FILE"));
47 conn
= SqlFactory::createConnection(CSqlAdapter
);
48 DbRetVal rv
= conn
->connect(I_USER
, I_PASS
);
49 stmtBuckets
= malloc (STMT_BUCKET_SIZE
* sizeof(StmtBucket
));
50 memset(stmtBuckets
, 0, STMT_BUCKET_SIZE
* sizeof(StmtBucket
));
53 sprintf(fileName
, "%s/offlineLogFile.%d", Conf::config
.getDbFile(),
55 if (::access(fileName
, F_OK
) != 0) break;
56 int retval
= applyOfflinelogs(fileName
, interactive
);
57 if (retval
) { return retval
; }
58 printf("Applied logs from file: %s\n", fileName
);
61 printf("All the offline log files have been successfully applied.\n");
65 sprintf(fileName
,"%s/offlineLogFile.%d",Conf::config
.getDbFile(),
67 if (::access(fileName
, F_OK
) != 0) break;
68 sprintf(cmd
, "rm -f %s", fileName
);
69 int retval
= system(cmd
);
70 if (retval
) return retval
;
73 printf("All the applied log files have been successfully removed.\n");
74 SqlStatement::freeAllStmtHandles(stmtBuckets
);
80 int applyOfflinelogs(char *fileName
, bool interactive
)
83 printf("offline log filename is :%s\n", fileName
);
84 int fd
= open(fileName
, O_RDONLY
);
85 if (-1 == fd
) { return 0; }
86 if (fstat(fd
, &st
) == -1) {
87 printError(ErrSysInternal
, "Unable to retrieve undo log file size");
92 printError(ErrNote
, "No Redo logs found during recovery");
96 void *startAddr
= mmap(NULL
, st
.st_size
, PROT_READ
, MAP_PRIVATE
, fd
, 0);
97 if (MAP_FAILED
== startAddr
) {
98 printf("Unable to read undo log file:mmap failed.\n");
104 char *iter
= (char*)startAddr
;
109 int len
, ret
, retVal
=0;
111 char stmtString
[SQL_STMT_LEN
];
112 //printf("size of file %d\n", st.st_size);
114 //printf("OFFSET HERE %d\n", iter - (char*)startAddr);
115 if (iter
- (char*)startAddr
>= st
.st_size
) break;
116 logType
= *(int*)iter
;
117 if (logType
== -1) { //prepare
118 iter
= iter
+ sizeof(int);
119 txnID
= *(int*) iter
; iter
+= sizeof(int);
120 loglen
= *(int*) iter
; iter
+= sizeof(int);
121 stmtID
= *(int*)iter
;
122 iter
= iter
+ sizeof(int);
124 iter
= iter
+ sizeof(int);
125 strncpy(stmtString
, iter
, len
);
127 //printf("PREPARE:%d %d %s\n", stmtID, len, stmtString);
128 AbsSqlStatement
*stmt
= SqlFactory::createStatement(CSqlAdapter
);
129 stmt
->setConnection(conn
);
130 if (interactive
) printf("PREPARE %d : %s\n", stmtID
, stmtString
);
131 rv
= stmt
->prepare(stmtString
);
133 printError(ErrSysInternal
, "unable to prepare stmt:%s", stmtString
);
137 SqlStatement::addToHashTable(stmtID
, stmt
, stmtBuckets
, stmtString
);
139 else if(logType
== -2) { //commit
141 iter
= iter
+ sizeof(int);
142 txnID
= *(int*) iter
; iter
+= sizeof(int);
143 loglen
= *(int*) iter
; iter
+= sizeof(int);
146 //printf("Iter length %d\n", iter - curPtr);
147 if (iter
- (char*)startAddr
>= st
.st_size
) {
149 //printf("Redo log file end\n");
153 stmtID
= *(int*)iter
;
154 //printf("stmtid %d\n", stmtID);
155 if (interactive
) printf("EXEC %d :\n", stmtID
);
156 iter
= iter
+ sizeof(int);
158 //printf("eType is %d\n", eType);
159 AbsSqlStatement
*stmt
=
160 SqlStatement::getStmtFromHashTable(stmtID
, stmtBuckets
);
161 if (0 == eType
) { //execute type
162 iter
= iter
+ sizeof(int);
163 //printf("EXEC: %d\n", stmtID);
165 rv
= stmt
->execute(ret
);
167 printError(ErrSysInternal
, "unable to execute");
172 printError(ErrSysInternal
, "statement not found for %d\n",stmtID
);
174 if (*(int*)iter
<0) break;
175 } else if ( 1 == eType
) { //set type
176 iter
=iter
+sizeof(int);
177 int pos
= *(int*) iter
;
178 iter
=iter
+sizeof(int);
179 DataType type
= (DataType
)(*(int*)iter
);
180 iter
=iter
+sizeof(int);
181 int len
= *(int*) iter
;
182 iter
=iter
+sizeof(int);
184 //AllDataType::printVal(value, type, len);
186 //printf("SET: %d %d %d %d\n", stmtID, pos, type, len);
187 SqlStatement::setParamValues(stmt
, pos
, type
, len
, value
);
188 if (*(int*)iter
<0) break;
193 else if(logType
== -3) { //free
194 iter
= iter
+ sizeof(int);
195 txnID
= *(int*) iter
; iter
+= sizeof(int);
196 loglen
= *(int*) iter
; iter
+= sizeof(int);
197 stmtID
= *(int*)iter
;
198 iter
= iter
+ sizeof(int);
199 if (interactive
) printf("FREE %d:\n", stmtID
);
200 AbsSqlStatement
*stmt
= SqlStatement::getStmtFromHashTable(stmtID
,
204 SqlStatement::removeFromHashTable(stmtID
, stmtBuckets
);
205 } else { printError(ErrSysInternal
, "statement not found for %d\n",stmtID
);}
207 else if(logType
== -4) { //prepare and execute
208 iter
= iter
+ sizeof(int);
209 txnID
= *(int*) iter
; iter
+= sizeof(int);
210 loglen
= *(int*) iter
; iter
+= sizeof(int);
211 stmtID
= *(int*)iter
;
212 iter
= iter
+ sizeof(int);
214 iter
= iter
+ sizeof(int);
215 strncpy(stmtString
, iter
, len
);
216 stmtString
[len
+1] ='\0';
218 //printf("CREATE:%d %d %s\n", stmtID, len, stmtString);
219 AbsSqlStatement
*stmt
= SqlFactory::createStatement(CSqlAdapter
);
221 printError(ErrSysInternal
, "unable to prepare:%s", stmtString
);
225 stmt
->setConnection(conn
);
226 if (interactive
) printf("EXECDIRECT %d : %s\n", stmtID
, stmtString
);
227 rv
= stmt
->prepare(stmtString
);
229 printError(ErrSysInternal
, "unable to prepare:%s", stmtString
);
233 rv
= stmt
->execute(ret
);
235 if (strlen(stmtString
) > 6 &&
236 ( (strncasecmp(stmtString
,"CREATE", 6) == 0) ||
237 (strncasecmp(stmtString
,"DROP", 4) == 0)) ) {
238 // conn->disconnect();
242 printError(ErrSysInternal
, "unable to execute %s", stmtString
);
248 printError(ErrSysInternal
, "Redo log file corrupted: logType:%d", logType
);
253 munmap((char*)startAddr
, st
.st_size
);