adding support for mutex from D flag
[csql.git] / src / tools / applyofflinelogs.cxx
blobbbbdf2ca5a834f47f72bb391fe0755fc4fbde86b
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>
20 #include <Recover.h>
21 AbsSqlConnection *conn;
22 void *stmtBuckets;
24 int applyOfflinelogs(char *fileName, bool interactive);
26 int main(int argc, char **argv)
28 struct stat st;
29 char fileName[MAX_FILE_LEN];
30 int c = 0, opt=0;
31 bool interactive=0;
32 while ((c = getopt(argc, argv, "ai?")) != EOF) {
33 switch (c) {
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);
40 }//while options
41 if (2 !=opt) {
42 printf("This is an internal csql command.");
43 exit(1);
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));
50 int counter=0;
51 while (true) {
52 sprintf(fileName, "%s/offlineLogFile.%d", Conf::config.getDbFile(),
53 counter);
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);
58 counter++;
60 printf("All the offline log files have been successfully applied.\n");
61 counter = 0;
62 char cmd[128];
63 while (true) {
64 sprintf(fileName,"%s/offlineLogFile.%d",Conf::config.getDbFile(),
65 counter);
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;
70 counter++;
72 printf("All the applied log files have been successfully removed.\n");
73 Recovery recovery;
74 recovery.setStmtBucket(stmtBuckets);
75 recovery.freeAllStmtHandles();
76 conn->disconnect();
77 delete conn;
78 return 0;
81 int applyOfflinelogs(char *fileName, bool interactive)
83 struct stat st;
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");
89 close(fd);
90 return 1;
92 if (st.st_size ==0) {
93 printError(ErrNote, "No Redo logs found during recovery");
94 close(fd);
95 return 0;
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");
100 conn->disconnect();
101 delete conn;
102 return 2;
104 DbRetVal rv=OK;
105 char *iter = (char*)startAddr;
106 void *value = NULL;
107 int logType, eType;
108 int stmtID;
109 int txnID;
110 int len, ret, retVal =0;
111 int loglen;
112 char stmtString[SQL_STMT_LEN];
113 //printf("size of file %d\n", st.st_size);
114 Recovery recovery;
115 recovery.setStmtBucket(stmtBuckets);
116 while(true) {
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);
126 len = *(int*)iter;
127 iter = iter + sizeof(int);
128 strncpy(stmtString, iter, len);
129 iter = 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);
135 if (rv != OK) {
136 printError(ErrSysInternal, "unable to prepare stmt:%s", stmtString);
137 retVal=1;
138 break;
140 recovery.addToHashTable(stmtID, stmt, stmtString);
142 else if(logType == -2) { //commit
143 conn->beginTrans();
144 iter = iter + sizeof(int);
145 txnID = *(int*) iter; iter += sizeof(int);
146 loglen = *(int*) iter; iter += sizeof(int);
147 char *curPtr = iter;
148 while(true) {
149 //printf("Iter length %d\n", iter - curPtr);
150 if (iter - (char*)startAddr >= st.st_size) {
151 //file end reached
152 //printf("Redo log file end\n");
153 retVal=0;
154 break;
156 stmtID = *(int*)iter;
157 //printf("stmtid %d\n", stmtID);
158 if (interactive) printf("EXEC %d :\n", stmtID);
159 iter = iter + sizeof(int);
160 eType = *(int*)iter;
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);
167 if (stmt) {
168 rv = stmt->execute(ret);
169 if (rv != OK) {
170 printError(ErrSysInternal, "unable to execute");
171 retVal=2;
172 break;
174 } else {
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);
186 value = iter;
187 //AllDataType::printVal(value, type, len);
188 iter=iter+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;
194 conn->commit();
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);
204 if (stmt) {
205 stmt->free();
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);
215 len = *(int*)iter;
216 iter = iter + sizeof(int);
217 strncpy(stmtString, iter, len);
218 stmtString[len+1] ='\0';
219 iter = iter + len;
220 //printf("CREATE:%d %d %s\n", stmtID, len, stmtString);
221 AbsSqlStatement *stmt = SqlFactory::createStatement(CSqlAdapter);
222 if ( NULL == stmt) {
223 printError(ErrSysInternal, "unable to prepare:%s", stmtString);
224 retVal=3;
225 break;
227 stmt->setConnection(conn);
228 if (interactive) printf("EXECDIRECT %d : %s\n", stmtID, stmtString);
229 rv = stmt->prepare(stmtString);
230 if (rv != OK) {
231 printError(ErrSysInternal, "unable to prepare:%s", stmtString);
232 retVal=4;
233 break;
235 rv = stmt->execute(ret);
236 if (rv != OK) {
237 if (strlen(stmtString) > 6 &&
238 ( (strncasecmp(stmtString,"CREATE", 6) == 0) ||
239 (strncasecmp(stmtString,"DROP", 4) == 0)) ) {
240 // conn->disconnect();
241 // return OK;
242 continue;
244 printError(ErrSysInternal, "unable to execute %s", stmtString);
245 retVal=5;
246 break;
248 stmt->free();
249 }else{
250 printError(ErrSysInternal, "Redo log file corrupted: logType:%d", logType);
251 retVal=6;
252 break;
255 munmap((char*)startAddr, st.st_size);
256 close(fd);
257 return retVal;