From 19001d27ac74f4580da12553910d9814d1c562ac Mon Sep 17 00:00:00 2001 From: prabatuty Date: Sat, 9 Apr 2011 07:37:50 +0000 Subject: [PATCH] code reorg for redo.cxx --- include/Debug.h | 6 +- include/ErrorType.h | 3 +- include/Recover.h | 69 ++++ include/os.h | 2 +- src/sql/SqlStatement.cxx | 250 -------------- src/sqllog/Makefile.am | 2 +- src/sqllog/Recover.cxx | 672 +++++++++++++++++++++++++++++++++++++ src/storage/Debug.cxx | 5 +- src/tools/applyofflinelogs.cxx | 18 +- src/tools/csqlasyncserver.cxx | 19 +- src/tools/csqlcheckpointserver.cxx | 10 +- src/tools/redo.cxx | 387 +++++---------------- 12 files changed, 860 insertions(+), 583 deletions(-) create mode 100644 include/Recover.h create mode 100644 src/sqllog/Recover.cxx rewrite src/tools/redo.cxx (76%) diff --git a/include/Debug.h b/include/Debug.h index 0797d2bf..f397289d 100644 --- a/include/Debug.h +++ b/include/Debug.h @@ -9,13 +9,14 @@ #include #include #include -//#define DEBUG 1 +#define DEBUG 1 extern int DebugDM_Alloc; extern int DebugDM_VarAlloc; extern int DebugDM_Lock; extern int DebugDM_Transaction; extern int DebugDM_UndoLog; extern int DebugDM_RedoLog; +extern int DebugDM_Recovery; extern int DebugDM_Index; extern int DebugDM_HashIndex; extern int DebugDM_TreeIndex; @@ -50,6 +51,7 @@ enum DebugModule DM_Transaction, DM_UndoLog, DM_RedoLog, + DM_Recovery, DM_Index, DM_HashIndex, DM_TreeIndex, @@ -70,7 +72,7 @@ enum DebugModule }; static char moduleNames[][20] = { - "Alloc", "VariableAlloc", "Lock", "Trans", "UndoLog", "RedoLog", "Index", + "Alloc", "VariableAlloc", "Lock", "Trans", "UndoLog", "RedoLog", "Recovery", "Index", "HashIndex", "TreeIndex", "TrieIndex", "SysDb", "Db", "Table", "Predicate", "Iter", "Procmgmt", "Network", "Gateway", "Adapter", "SqlLog", "CacheServer", "TEST", "Warning" diff --git a/include/ErrorType.h b/include/ErrorType.h index 32fbfcff..07206522 100644 --- a/include/ErrorType.h +++ b/include/ErrorType.h @@ -54,7 +54,8 @@ enum DbRetVal ErrForeignKeyDelete=-35, ErrNullValues =-36, //used in evaluate on null values ErrDefaultValue =-37, //Added here to check Default value - ErrLoadingOn = -38, + ErrLoadingOn = -38, + ErrEndReached = -39, ErrNote = -97, // add new error type here ErrUnknown = -98, ErrWarning = -99, diff --git a/include/Recover.h b/include/Recover.h new file mode 100644 index 00000000..46d37763 --- /dev/null +++ b/include/Recover.h @@ -0,0 +1,69 @@ +/*************************************************************************** + * Copyright (C) 2007 by Prabakaran Thirumalai * + * praba_tuty@yahoo.com * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ +#ifndef RECOVER_H +#define RECOVER_H +#include +#include +#include + +class DllExport Recovery +{ + void *stmtBuckets; + + //contains pointer to start address of the mapped redo log file + //used to traverse till the end of the mapping during redo log processing + public: + char *iter; + Recovery(){ + stmtBuckets = NULL; + iter = NULL; + } + void setStmtBucket(void *ptr) { stmtBuckets = ptr; } + ~Recovery() { + //do not free stmtBuckets + } + + void addToHashTable(int stmtID, AbsSqlStatement* sHdl, char *stmtstr); + void removeFromHashTable(int stmtID); + AbsSqlStatement *getStmtFromHashTable(int stmtId); + bool isStmtInHashTable(int stmtID); + void freeAllStmtHandles(); + DbRetVal filterAndWriteStmtLogs(); + DbRetVal readAndPopulateStmts(AbsSqlConnection *conn, bool list = false, bool interactive = false); + DbRetVal iterateStmtLogs(AbsSqlConnection *conn, void *startAddr, int size, bool list=false, bool interactive = false); + + int applyRedoLogs(char *redoFile, AbsSqlConnection *conn, bool list = false, bool interactive = false); + +#if (defined MMDB && defined EMBED) + DbRetVal recoverCsqlDB(); + DbRetVal recoverSystemAndUserDB(); + DbRetVal applySchemaFile(FILE *fp); + char getQueryFromSchemaFile(FILE *fp, char *buf); +#endif + +private: + //before calling below 4 handleXXX methods, iter should be set + DbRetVal handlePrepare( AbsSqlConnection *conn, bool list=false, bool interactive = false); + DbRetVal handleCommit(AbsSqlConnection *conn, void *startAddr, long size, bool list=false, bool interactive = false); + DbRetVal handleFree(bool list=false, bool interactive = false); + DbRetVal handlePrepareAndExecute(AbsSqlConnection *conn, bool list=false, bool interactive = false); +}; + +#endif diff --git a/include/os.h b/include/os.h index c2c3d294..177396c3 100644 --- a/include/os.h +++ b/include/os.h @@ -230,7 +230,7 @@ class DllExport os static int munmap(caddr_t addr, size_t len); static int open(const char *name, FileOpenMode flags, size_t size); static int close(int fd); - static file_desc openFile(const char *name, FileOpenMode flags, size_t size); + static file_desc openFile(const char *name, FileOpenMode flags, size_t size=0); static int closeFile(file_desc fd); static int closeSocket(int fd); static int lockFile(int fd); diff --git a/src/sql/SqlStatement.cxx b/src/sql/SqlStatement.cxx index 7d3d41c1..7b2afb58 100644 --- a/src/sql/SqlStatement.cxx +++ b/src/sql/SqlStatement.cxx @@ -164,96 +164,6 @@ void *SqlStatement::fillBindBuffer(TDBInfo tdbName, DataType type, void *&valBuf return bBuf; } -void SqlStatement::addToHashTable(int stmtID, AbsSqlStatement* sHdl, - void *stmtBuckets, char *stmtstr) -{ - int bucketNo = stmtID % STMT_BUCKET_SIZE; - StmtBucket *buck = (StmtBucket *) stmtBuckets; - StmtBucket *stmtBucket = &buck[bucketNo]; - StmtNode *node = new StmtNode(); - node->stmtId = stmtID; - node->stmt = sHdl; - strcpy(node->stmtstr, stmtstr); - stmtBucket->bucketList.append(node); - return; -} - -void SqlStatement::removeFromHashTable(int stmtID, void *stmtBuckets) -{ - int bucketNo = stmtID % STMT_BUCKET_SIZE; - StmtBucket *buck = (StmtBucket *) stmtBuckets; - StmtBucket *stmtBucket = &buck[bucketNo]; - StmtNode *node = NULL, *delNode = NULL; - ListIterator it = stmtBucket->bucketList.getIterator(); - while(it.hasElement()) { - node = (StmtNode *) it.nextElement(); - if(stmtID == node->stmtId) { delNode = node; break; } - } - it.reset(); - if (delNode != NULL) { - stmtBucket->bucketList.remove(delNode); - delete delNode; - } - return; -} - -AbsSqlStatement *SqlStatement::getStmtFromHashTable(int stmtId, - void *stmtBuckets) -{ - int bucketNo = stmtId % STMT_BUCKET_SIZE; - StmtBucket *buck = (StmtBucket *) stmtBuckets; - StmtBucket *stmtBucket = &buck[bucketNo]; - if (stmtBucket == NULL) return NULL; - StmtNode *node = NULL; - ListIterator it = stmtBucket->bucketList.getIterator(); - while(it.hasElement()) { - node = (StmtNode *) it.nextElement(); - if(stmtId == node->stmtId) { - SqlStatement *sqlStmt = (SqlStatement*)node->stmt; - if (!sqlStmt->isPrepared()) sqlStmt->prepare(node->stmtstr); - return node->stmt; - } - } - return NULL; -} - -bool SqlStatement::isStmtInHashTable(int stmtId, void *stmtBuckets) -{ - int bucketNo = stmtId % STMT_BUCKET_SIZE; - StmtBucket *buck = (StmtBucket *) stmtBuckets; - StmtBucket *stmtBucket = &buck[bucketNo]; - if (stmtBucket == NULL) return false; - StmtNode *node = NULL; - ListIterator it = stmtBucket->bucketList.getIterator(); - while(it.hasElement()) { - node = (StmtNode *) it.nextElement(); - if(stmtId == node->stmtId) { - SqlStatement *sqlStmt = (SqlStatement*)node->stmt; - if (sqlStmt->isPrepared()) return true; - else break; - } - } - return false; -} - -void SqlStatement::freeAllStmtHandles(void *stmtBuckets) -{ - if (NULL == stmtBuckets) return; - StmtBucket *buck = (StmtBucket *) stmtBuckets; - StmtNode *node = NULL; - for (int i=0; i bucketList.getIterator(); - while(it.hasElement()) { - node = (StmtNode *) it.nextElement(); - node->stmt->free(); - delete node->stmt; - } - } - ::free(stmtBuckets); -} List SqlStatement::getTableNameList() { @@ -1061,166 +971,6 @@ void SqlConnection::initialize() isInit = true; } -DbRetVal SqlStatement::filterAndWriteStmtLogs(void *stmtBuckets) -{ - struct stat st; - char fName[MAX_FILE_LEN]; - sprintf(fName, "%s/csql.db.stmt", Conf::config.getDbFile()); - file_desc fdRead = os::openFile(fName, fileOpenReadOnly,0); - if ((file_desc)-1 == fdRead) { return OK; } - if (::stat(fName, &st) == -1) { - printError(ErrSysInternal, "Unable to retrieve stmt log file size"); - os::closeFile(fdRead); - return ErrSysInternal; - } - if (st.st_size ==0) { - os::closeFile(fdRead); - return OK; - } - void *startAddr = os::mmap(NULL, st.st_size, mapProtRead, mapPrivate, fdRead, 0); - if ((void*)MAP_FAILED == startAddr) { - printError(ErrSysInternal, "Unable to mmap stmt log file\n"); - return ErrSysInternal; - } - sprintf(fName, "%s/csql.db.stmt1", Conf::config.getDbFile()); - int fd = os::openFileForAppend(fName, O_CREAT|O_TRUNC); - char *iter = (char*)startAddr; - char *logStart = NULL, *logEnd = NULL; - int logType; - int stmtID; - int len =0, ret =0; - DbRetVal rv = OK; - while(true) { - if (iter - (char*)startAddr >= st.st_size) break; - logType = *(int*)iter; - logStart = iter; - if (logType == -1) { //prepare - iter = iter + sizeof(int); - len = *(int*) iter; - iter = iter + 2 * sizeof(int); - stmtID = *(int*)iter; - iter = logStart+ len; - ret =0; - if (isStmtInHashTable(stmtID,stmtBuckets)) - ret = os::write(fd, logStart, len); - if (-1 == ret) { - printError(ErrSysInternal, "Unable to write statement logs"); - } - } - else if(logType == -3) { //free - iter = logStart + 4 *sizeof(int); - }else{ - printError(ErrSysInternal, "Stmt Redo log file corrupted: logType:%d", logType); - rv = ErrSysInternal; - break; - } - } - os::close(fd); - os::munmap((char*)startAddr, st.st_size); - os::closeFile(fdRead); - char cmd[MAX_FILE_LEN *2]; - sprintf(cmd, "mv %s/csql.db.stmt1 %s/csql.db.stmt", - Conf::config.getDbFile(), Conf::config.getDbFile()); - ret = ::system(cmd); - return rv; -} - -DbRetVal SqlStatement::readAndPopulateStmts(AbsSqlConnection *conn, void *&stmtBuckets, bool list, bool interactive) -{ - struct stat st; - char fName[MAX_FILE_LEN]; - sprintf(fName, "%s/csql.db.stmt", Conf::config.getDbFile()); - printf("Statement Redo log filename is :%s\n", fName); - file_desc fd = os::openFile(fName, fileOpenReadOnly, 0); - if ((file_desc)-1 == fd) { return OK; } - if (::stat(fName, &st) == -1) { - printError(ErrSysInternal, "Unable to retrieve stmt log file size"); - os::closeFile(fd); - return ErrSysInternal; - } - if (NULL != stmtBuckets) - { - printError(ErrSysInternal, "stmtBuckets already populated"); - os::closeFile(fd); - return ErrSysInternal; - } - stmtBuckets = malloc (STMT_BUCKET_SIZE * sizeof(StmtBucket)); - memset(stmtBuckets, 0, STMT_BUCKET_SIZE * sizeof(StmtBucket)); - if (st.st_size ==0) { - printError(ErrNote, "No Statement logs found during recovery"); - ::free(stmtBuckets); - stmtBuckets = NULL; - os::closeFile(fd); - return OK; - } - void *startAddr = os::mmap(NULL, st.st_size, mapProtRead, mapPrivate, fd, 0); - if ((void*)MAP_FAILED == startAddr) { - printError(ErrSysInternal, "Unable to mmap stmt log file\n"); - ::free(stmtBuckets); - stmtBuckets = NULL; - os::closeFile(fd); - return ErrSysInternal; - } - DbRetVal rv = iterateStmtLogs(conn, startAddr, st.st_size, stmtBuckets, list, interactive); - os::munmap((char*)startAddr, st.st_size); - os::closeFile(fd); - return rv; -} - -DbRetVal SqlStatement::iterateStmtLogs(AbsSqlConnection *conn, void *startAddr, int size, void *stmtBuckets, bool list, bool interactive) -{ - char *iter = (char*)startAddr; - void *value = NULL; - int logType, eType; - int stmtID; - int txnID; - int len, ret, retVal =0; - int loglen; - char stmtString[SQL_STMT_LEN]; - DbRetVal rv = OK; - while(true) { - if (iter - (char*)startAddr >= size) break; - logType = *(int*)iter; - if (logType == -1) { //prepare - iter = iter + sizeof(int); - txnID = *(int*) iter; iter += sizeof(int); - loglen = *(int*) iter; iter += sizeof(int); - stmtID = *(int*)iter; - iter = iter + sizeof(int); - len = *(int*)iter; - iter = iter + sizeof(int); - strncpy(stmtString, iter, len); - iter = iter + len; - if (list) { - printf("PREPARE: SID:%d %s\n", stmtID, stmtString); - continue; - } - if (interactive) printf("STMTLOG PREPARE SID:%d %s\n", stmtID, stmtString); - AbsSqlStatement *csqlStmt = SqlFactory::createStatement(CSqlDirect); - csqlStmt->setConnection(conn); - SqlStatement *sqlStmt = (SqlStatement*)csqlStmt; - sqlStmt->setStmtString(stmtString); - addToHashTable(stmtID, csqlStmt, stmtBuckets, stmtString); - } - else if(logType == -3) { //free - iter = iter + sizeof(int); - txnID = *(int*) iter; iter += sizeof(int); - loglen = *(int*) iter; iter += sizeof(int); - stmtID = *(int*)iter; - iter = iter + sizeof(int); - if (list) { - printf("FREE: SID:%d TID:%d \n", stmtID, txnID); - continue; - } - }else{ - printError(ErrSysInternal, "Stmt Redo log file corrupted: logType:%d", logType); - rv = ErrSysInternal; - break; - } - } - return rv; -} - #if (defined MMDB && defined EMBED) DbRetVal SqlConnection::recoverCsqlDB() diff --git a/src/sqllog/Makefile.am b/src/sqllog/Makefile.am index fe161f69..dcae5416 100644 --- a/src/sqllog/Makefile.am +++ b/src/sqllog/Makefile.am @@ -2,6 +2,6 @@ INCLUDES = -I$(top_srcdir)/include $(all_includes) METASOURCES = AUTO lib_LTLIBRARIES = libcsqlsqllog.la libcsqlsqllog_la_LDFLAGS = -avoid-version -module -libcsqlsqllog_la_SOURCES = SqlLogConnection.cxx SqlLogStatement.cxx FileSend.cxx +libcsqlsqllog_la_SOURCES = SqlLogConnection.cxx SqlLogStatement.cxx FileSend.cxx Recover.cxx libcsqlsqllog_a_LIBADD = $(top_builddir)/src/sql/libcsqlsql.la $(top_builddir)/src/network/libcsqlnw.la diff --git a/src/sqllog/Recover.cxx b/src/sqllog/Recover.cxx new file mode 100644 index 00000000..2b1f1c96 --- /dev/null +++ b/src/sqllog/Recover.cxx @@ -0,0 +1,672 @@ +/************************************************************************** + * Copyright (C) 2007 by Prabakaran Thirumalai * + * praba_tuty@yahoo.com * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ +#include +#include + +void Recovery::addToHashTable(int stmtID, AbsSqlStatement* sHdl, + char *stmtstr) +{ + int bucketNo = stmtID % STMT_BUCKET_SIZE; + printDebug(DM_Recovery, "Inside addToHashTable %x", stmtBuckets); + StmtBucket *buck = (StmtBucket *) stmtBuckets; + StmtBucket *stmtBucket = &buck[bucketNo]; + StmtNode *node = new StmtNode(); + node->stmtId = stmtID; + node->stmt = sHdl; + strcpy(node->stmtstr, stmtstr); + stmtBucket->bucketList.append(node); + return; +} + +void Recovery::removeFromHashTable(int stmtID) +{ + int bucketNo = stmtID % STMT_BUCKET_SIZE; + StmtBucket *buck = (StmtBucket *) stmtBuckets; + StmtBucket *stmtBucket = &buck[bucketNo]; + StmtNode *node = NULL, *delNode = NULL; + ListIterator it = stmtBucket->bucketList.getIterator(); + while(it.hasElement()) { + node = (StmtNode *) it.nextElement(); + if(stmtID == node->stmtId) { delNode = node; break; } + } + it.reset(); + if (delNode != NULL) { + stmtBucket->bucketList.remove(delNode); + delete delNode; + } + return; +} + +AbsSqlStatement* Recovery::getStmtFromHashTable(int stmtId) +{ + int bucketNo = stmtId % STMT_BUCKET_SIZE; + StmtBucket *buck = (StmtBucket *) stmtBuckets; + StmtBucket *stmtBucket = &buck[bucketNo]; + if (stmtBucket == NULL) return NULL; + StmtNode *node = NULL; + ListIterator it = stmtBucket->bucketList.getIterator(); + while(it.hasElement()) { + node = (StmtNode *) it.nextElement(); + if(stmtId == node->stmtId) { + SqlStatement *sqlStmt = (SqlStatement*)node->stmt; + if (!sqlStmt->isPrepared()) sqlStmt->prepare(node->stmtstr); + return node->stmt; + } + } + return NULL; +} + +bool Recovery::isStmtInHashTable(int stmtId) +{ + int bucketNo = stmtId % STMT_BUCKET_SIZE; + StmtBucket *buck = (StmtBucket *) stmtBuckets; + StmtBucket *stmtBucket = &buck[bucketNo]; + if (stmtBucket == NULL) return false; + StmtNode *node = NULL; + ListIterator it = stmtBucket->bucketList.getIterator(); + while(it.hasElement()) { + node = (StmtNode *) it.nextElement(); + if(stmtId == node->stmtId) { + SqlStatement *sqlStmt = (SqlStatement*)node->stmt; + if (sqlStmt->isPrepared()) return true; + else break; + } + } + return false; +} + +void Recovery::freeAllStmtHandles() +{ + if (NULL == stmtBuckets) return; + StmtBucket *buck = (StmtBucket *) stmtBuckets; + StmtNode *node = NULL; + for (int i=0; i bucketList.getIterator(); + while(it.hasElement()) { + node = (StmtNode *) it.nextElement(); + node->stmt->free(); + delete node->stmt; + } + } + ::free(stmtBuckets); + stmtBuckets = NULL; +} + +DbRetVal Recovery::filterAndWriteStmtLogs() +{ + struct stat st; + char fName[MAX_FILE_LEN]; + sprintf(fName, "%s/csql.db.stmt", Conf::config.getDbFile()); + file_desc fdRead = os::openFile(fName, fileOpenReadOnly,0); + if ((file_desc)-1 == fdRead) { return OK; } + if (::stat(fName, &st) == -1) { + printError(ErrSysInternal, "Unable to retrieve stmt log file size"); + os::closeFile(fdRead); + return ErrSysInternal; + } + if (st.st_size ==0) { + os::closeFile(fdRead); + return OK; + } + void *startAddr = os::mmap(NULL, st.st_size, mapProtRead, mapPrivate, fdRead, 0); + if ((void*)MAP_FAILED == startAddr) { + printError(ErrSysInternal, "Unable to mmap stmt log file\n"); + return ErrSysInternal; + } + sprintf(fName, "%s/csql.db.stmt1", Conf::config.getDbFile()); + int fd = os::openFileForAppend(fName, O_CREAT|O_TRUNC); + char *iter = (char*)startAddr; + char *logStart = NULL, *logEnd = NULL; + int logType; + int stmtID; + int len =0, ret =0; + DbRetVal rv = OK; + while(true) { + if (iter - (char*)startAddr >= st.st_size) break; + logType = *(int*)iter; + logStart = iter; + if (logType == -1) { //prepare + iter = iter + sizeof(int); + len = *(int*) iter; + iter = iter + 2 * sizeof(int); + stmtID = *(int*)iter; + iter = logStart+ len; + ret =0; + if (isStmtInHashTable(stmtID)) + ret = os::write(fd, logStart, len); + if (-1 == ret) { + printError(ErrSysInternal, "Unable to write statement logs"); + } + } + else if(logType == -3) { //free + iter = logStart + 4 *sizeof(int); + }else{ + printError(ErrSysInternal, "Stmt Redo log file corrupted: logType:%d", logType); + rv = ErrSysInternal; + break; + } + } + os::close(fd); + os::munmap((char*)startAddr, st.st_size); + os::closeFile(fdRead); + char cmd[MAX_FILE_LEN *2]; + sprintf(cmd, "mv %s/csql.db.stmt1 %s/csql.db.stmt", + Conf::config.getDbFile(), Conf::config.getDbFile()); + ret = ::system(cmd); + return rv; +} + +DbRetVal Recovery::readAndPopulateStmts(AbsSqlConnection *conn, bool list, bool interactive) +{ + struct stat st; + char fName[MAX_FILE_LEN]; + sprintf(fName, "%s/csql.db.stmt", Conf::config.getDbFile()); + printDebug(DM_Recovery,"Statement Redo log filename is :%s\n", fName); + file_desc fd = os::openFile(fName, fileOpenReadOnly, 0); + if ((file_desc)-1 == fd) { + printDebug(DM_Recovery, "No redo log file found"); + return OK; + } + if (::stat(fName, &st) == -1) { + printError(ErrSysInternal, "Unable to retrieve stmt log file size"); + os::closeFile(fd); + return ErrSysInternal; + } + if (NULL != stmtBuckets) + { + printError(ErrSysInternal, "stmtBuckets already populated"); + os::closeFile(fd); + return ErrSysInternal; + } + stmtBuckets = (void*) ::malloc (STMT_BUCKET_SIZE * sizeof(StmtBucket)); + printDebug(DM_Recovery, "stmtBuckets allocated %x", stmtBuckets); + memset(stmtBuckets, 0, STMT_BUCKET_SIZE * sizeof(StmtBucket)); + if (st.st_size ==0) { + printError(ErrNote, "No Statement logs found during recovery"); + os::closeFile(fd); + return OK; + } + void *startAddr = os::mmap(NULL, st.st_size, mapProtRead, mapPrivate, fd, 0); + if ((void*)MAP_FAILED == startAddr) { + printError(ErrSysInternal, "Unable to mmap stmt log file\n"); + ::free(stmtBuckets); + stmtBuckets = NULL; + os::closeFile(fd); + return ErrSysInternal; + } + DbRetVal rv = iterateStmtLogs(conn, startAddr, st.st_size, list, interactive); + os::munmap((char*)startAddr, st.st_size); + os::closeFile(fd); + return rv; +} + +DbRetVal Recovery::iterateStmtLogs(AbsSqlConnection *conn, void *startAddr, int size, bool list, bool interactive) +{ + char *iter = (char*)startAddr; + void *value = NULL; + int logType, eType; + int stmtID; + int txnID; + int len, ret, retVal =0; + int loglen; + char stmtString[SQL_STMT_LEN]; + DbRetVal rv = OK; + while(true) { + if (iter - (char*)startAddr >= size) break; + logType = *(int*)iter; + if (logType == -1) { //prepare + iter = iter + sizeof(int); + txnID = *(int*) iter; iter += sizeof(int); + loglen = *(int*) iter; iter += sizeof(int); + stmtID = *(int*)iter; + iter = iter + sizeof(int); + len = *(int*)iter; + iter = iter + sizeof(int); + strncpy(stmtString, iter, len); + iter = iter + len; + if (list) { + printf("PREPARE: SID:%d %s\n", stmtID, stmtString); + continue; + } + if (interactive) printf("STMTLOG PREPARE SID:%d %s\n", stmtID, stmtString); + AbsSqlStatement *csqlStmt = SqlFactory::createStatement(CSqlDirect); + csqlStmt->setConnection(conn); + SqlStatement *sqlStmt = (SqlStatement*)csqlStmt; + sqlStmt->setStmtString(stmtString); + addToHashTable(stmtID, csqlStmt, stmtString); + } + else if(logType == -3) { //free + iter = iter + sizeof(int); + txnID = *(int*) iter; iter += sizeof(int); + loglen = *(int*) iter; iter += sizeof(int); + stmtID = *(int*)iter; + iter = iter + sizeof(int); + if (list) { + printf("FREE: SID:%d TID:%d \n", stmtID, txnID); + continue; + } + }else{ + printError(ErrSysInternal, "Stmt Redo log file corrupted: logType:%d", logType); + rv = ErrSysInternal; + break; + } + } + return rv; +} + +#if (defined MMDB && defined EMBED) + +DbRetVal Recovery::recoverCsqlDB() +{ + DbRetVal rv = OK; + char dbRedoFileName[MAX_FILE_LEN]; + char dbChkptSchema[MAX_FILE_LEN]; + char dbChkptMap[MAX_FILE_LEN]; + char dbChkptData[MAX_FILE_LEN]; + char dbBackupFile[MAX_FILE_LEN]; + char cmd[IDENTIFIER_LENGTH]; + //check for check point file if present recover + sprintf(dbChkptSchema, "%s/db.chkpt.schema1", Conf::config.getDbFile()); + if (FILE *file = fopen(dbChkptSchema, "r")) { + fclose(file); + sprintf(cmd, "cp -f %s %s/db.chkpt.schema", dbChkptSchema, + Conf::config.getDbFile()); + int ret = system(cmd); + if (ret != 0) return ErrOS; + } + sprintf(dbChkptMap, "%s/db.chkpt.map1", Conf::config.getDbFile()); + if (FILE *file = fopen(dbChkptMap, "r")) { + fclose(file); + sprintf(cmd, "cp -f %s %s/db.chkpt.map", dbChkptMap, + Conf::config.getDbFile()); + int ret = system(cmd); + if (ret != 0) return ErrOS; + } + int chkptID= Database::getCheckpointID(); + sprintf(dbChkptData, "%s/db.chkpt.data%d", Conf::config.getDbFile(), + chkptID); + sprintf(dbBackupFile, "%s/db.chkpt.data1", Conf::config.getDbFile()); + FILE *fl = NULL; + if (!Conf::config.useMmap() && (fl = fopen(dbBackupFile, "r"))) { + fclose(fl); + sprintf(cmd, "cp %s/db.chkpt.data1 %s", Conf::config.getDbFile(), + dbChkptData); + int ret = system(cmd); + if (ret != 0) return ErrOS; + } + if (FILE *file = fopen(dbChkptData, "r")) { + fclose(file); + rv = recoverSystemAndUserDB(); + if (rv != OK) return rv; + } + + //check for redo log file if present apply redo logs + sprintf(dbRedoFileName, "%s/csql.db.cur", Conf::config.getDbFile()); + if (FILE *file = fopen(dbRedoFileName, "r")) + { + fclose(file); + rv = (DbRetVal) applyRedoLogs(dbRedoFileName); + if (rv != OK) return rv; + DatabaseManager *dbMgr = getConnObject().getDatabaseManager(); + rv = dbMgr->checkPoint(); + if (rv != OK) + { + printError(ErrSysInternal, "checkpoint failed after redo log apply"); + return ErrOS; + } + } + return OK; +} + +DbRetVal Recovery::recoverSystemAndUserDB() +{ + DbRetVal rv = OK; + char schFile[1024]; + sprintf(schFile, "%s/db.chkpt.schema", Conf::config.getDbFile()); + if (FILE *file = fopen(schFile, "r")) { + rv = applySchemaFile(file); + if (rv != OK) { fclose(file); return rv; } + } + DatabaseManager *dbMgr = getConnObject().getDatabaseManager(); + rv = dbMgr->recover(); + return rv; +} + +DbRetVal Recovery::applySchemaFile(FILE *fp) +{ + char buf[8192]; + char eof; + DbRetVal rv = OK; + SqlStatement *stmt = new SqlStatement(); + while ((eof = getQueryFromSchemaFile(fp,buf)) != EOF) { + stmt->setConnection(this); + rv = stmt->prepare(buf); + if (rv != OK) { delete stmt; return rv; } + int rows = 0; + stmt->execute(rows); + if (rv != OK) { stmt->free(); delete stmt; return rv; } + } + delete stmt; + return OK; +} + +char Recovery::getQueryFromSchemaFile(FILE *fp, char *buf) +{ + char c, *bufBegin=buf; + int charCnt=0; + while( (c=(char ) fgetc(fp)) != EOF && c != ';') + { + *buf++ = c; charCnt++; + if( charCnt == SQL_STMT_LEN ) { + printf("SQL Statement length is greater than %d. " + "Ignoring the statement.\n", SQL_STMT_LEN ); + *bufBegin++ =';'; + *bufBegin ='\0'; + return 0; + } + } + *buf++ = ';'; + *buf = '\0'; + return c; +} +#endif +int Recovery::applyRedoLogs(char *redoFile, AbsSqlConnection *conn, bool list, bool interactive ) +{ + struct stat st; + DbRetVal rv = OK; + file_desc fd = os::openFile(redoFile, fileOpenReadOnly, 0); + if ((file_desc)-1 == fd) { return OK; } + if (fstat(fd, &st) == -1) { + printError(ErrSysInternal, "Unable to retrieve undo log file size"); + os::closeFile(fd); + return 1; + } + if (st.st_size ==0) { + printError(ErrNote, "No Redo logs found during recovery"); + readAndPopulateStmts(conn, list, interactive); + os::closeFile(fd); + return 0; + } + void *startAddr = os::mmap(NULL, st.st_size, mapProtRead, mapPrivate, fd, 0); + if (MAP_FAILED == startAddr) { + printf("Unable to read undo log file:mmap failed.\n"); + return 3; + } + + rv = readAndPopulateStmts(conn, list, interactive); + if (OK != rv) + { + printf("Unable to read stmt log file\n"); + return 4; + } + + iter = (char*)startAddr; + void *value = NULL; + int logType, eType; + int stmtID; + int txnID; + int len, ret, retVal =0; + int loglen; + char stmtString[SQL_STMT_LEN]; + printDebug(DM_Recovery,"Redo log filename is :%s\n", redoFile); + while(true) { + if (iter - (char*)startAddr >= st.st_size) break; + logType = *(int*)iter; + if (logType == -1) { //prepare + rv = handlePrepare(conn, list, interactive); + if (rv != OK) { + printError(ErrSysInternal, "unable to handle prepare stmt"); + retVal=1; + break; + } + } + else if(logType == -2) { //commit + rv = handleCommit(conn, startAddr, st.st_size, list, interactive); + if (ErrEndReached == rv) + { + printDebug(DM_Recovery, "During Commit processing, end redo log reached"); + retVal=0; + break; + }else if (OK != rv) { + printError(ErrSysInternal, "unable to handle prepare stmt"); + retVal=1; + break; + } + } + else if(logType == -3) { //free + handleFree(list, interactive); + } + else if(logType == -4) { //prepare and execute + handlePrepareAndExecute(conn, list, interactive); + } else { + printError(ErrSysInternal, "Redo log file corrupted: logType:%d", logType); + retVal=6; + break; + } + } + printDebug(DM_Recovery, "Before munmap"); + os::munmap((char*)startAddr, st.st_size); + os::closeFile(fd); + if (!list) { + //when redo log list option is specified do not write statement logs + //it will block debugging and change the state at which problem + //occurred + printDebug(DM_Recovery, "Before filter and writestmt logs"); + filterAndWriteStmtLogs(); + printDebug(DM_Recovery, "Before freeallstmthandles"); + freeAllStmtHandles(); + } + return retVal; +} +DbRetVal Recovery::handlePrepare( AbsSqlConnection *conn, bool list, bool interactive) +{ + char stmtString[SQL_STMT_LEN]; + iter = iter + sizeof(int); + int txnID = *(int*) iter; + iter += sizeof(int); + int loglen = *(int*) iter; + iter += sizeof(int); + int stmtID = *(int*)iter; + iter = iter + sizeof(int); + int len = *(int*)iter; + iter = iter + sizeof(int); + strncpy(stmtString, iter, len); + iter = iter + len; + printDebug(DM_Recovery,"PREPARE: SID:%d %s\n", stmtID, stmtString); + if (list) { + printf("PREPARE: SID:%d %s\n", stmtID, stmtString); + return OK; + } + AbsSqlStatement *stmt = SqlFactory::createStatement(CSqlDirect); + stmt->setConnection(conn); + if (interactive) printf("PREPARE %d : %s\n", stmtID, stmtString); + DbRetVal rv = stmt->prepare(stmtString); + if (rv != OK) { + printError(ErrSysInternal, "unable to prepare stmt:%s", stmtString); + return ErrSysInternal; + } + SqlStatement *sqlStmt = (SqlStatement*)stmt; + sqlStmt->setLoading(true); + addToHashTable(stmtID, stmt, stmtString); + printDebug(DM_Recovery,"Added to hashtable SID:%d ", stmtID); + return OK; +} +DbRetVal Recovery::handleCommit(AbsSqlConnection *conn, void *startAddr, long size, bool list, bool interactive) +{ + conn->beginTrans(); + iter = iter + sizeof(int); + int txnID = *(int*) iter; iter += sizeof(int); + int loglen = *(int*) iter; iter += sizeof(int); + char *curPtr = iter; + DbRetVal rv = OK; + int ret =0; + void *value = NULL; + while(true) { + printDebug(DM_Recovery, "Iter length %d\n", iter - curPtr); + if (iter - (char*)startAddr >= size) { + //file end reached + printDebug(DM_Recovery, "Redo log file end\n"); + return ErrEndReached; + } + int stmtID = *(int*)iter; + printDebug(DM_Recovery, "stmtid %d\n", stmtID); + if (interactive) printf("EXEC %d :\n", stmtID); + iter = iter + sizeof(int); + int eType = *(int*)iter; + printDebug(DM_Recovery,"eType is %d\n", eType); + AbsSqlStatement *stmt = NULL; + if (!list) { + stmt = getStmtFromHashTable(stmtID); + if (NULL == stmt) { + printError(ErrSysInternal, "Unable to find in stmt hashtable"); + return ErrSysInternal; + } + } + if (0 == eType) { //execute type + iter = iter + sizeof(int); + printDebug(DM_Recovery, "EXEC SID:%d TID:%d\n", stmtID, txnID); + if (list) { + printf("EXEC SID:%d TID:%d\n", stmtID, txnID); + if (*(int*)iter <0) break; + continue; + } + if (stmt) { + rv = stmt->execute(ret); + if (rv != OK) { + printError(ErrSysInternal, "unable to execute"); + return ErrSysInternal; + } + } else { + printError(ErrSysInternal, "statement not found for %d\n",stmtID); + } + printDebug(DM_Recovery, "iter:%x value:%d", iter, *(int*)iter); + if (*(int*)iter <0) break; + } else if ( 1 == eType) { //set type + iter=iter+sizeof(int); + int pos = *(int*) iter; + iter=iter+sizeof(int); + int isNull = *(int *) iter; + iter=iter+sizeof(int); + if (isNull == 0) { + DataType type = (DataType)(*(int*)iter); + iter=iter+sizeof(int); + int len = *(int*) iter; + iter=iter+sizeof(int); + value = iter; + iter=iter+len; + printDebug(DM_Recovery, "SET SID:%d POS:%d ISNULL:FALSE TYPE:%d LEN:%d Value:", stmtID, pos, type, len); + if (list) { + printf("SET SID:%d POS:%d ISNULL:FALSE TYPE:%d LEN:%d Value:", stmtID, pos, type, len); + AllDataType::printVal(value, type, len); + printf("\n"); + if (*(int*)iter <0) break; + continue; + } + SqlStatement::setParamValues(stmt, pos, type, len, value); + } else { + printDebug(DM_Recovery, "SET SID:%d POS:%d ISNULL:TRUE\n", stmtID, pos); + if (list) { + printf("SET SID:%d POS:%d ISNULL:TRUE\n", stmtID, pos); + continue; + } + stmt->setNull(pos); + } + if (*(int*)iter <0) break; + } + } + conn->commit(); + return OK; +} +DbRetVal Recovery::handleFree(bool list, bool interactive) +{ + iter = iter + sizeof(int); + int txnID = *(int*) iter; iter += sizeof(int); + int loglen = *(int*) iter; iter += sizeof(int); + int stmtID = *(int*)iter; + iter = iter + sizeof(int); + printDebug(DM_Recovery, "FREE SID:%d \n", stmtID); + if (list) { + printf("FREE SID:%d \n", stmtID); + return OK; + } + if (interactive) printf("FREE %d:\n", stmtID); + AbsSqlStatement *stmt = getStmtFromHashTable(stmtID); + if (stmt) { + stmt->free(); + delete stmt; + removeFromHashTable(stmtID); + } else { + printError(ErrSysInternal, "statement not found for %d\n",stmtID); + } + return OK; +} +DbRetVal Recovery::handlePrepareAndExecute(AbsSqlConnection *conn, bool list, bool interactive) +{ + int ret = 0; + DbRetVal rv = OK; + char stmtString[SQL_STMT_LEN]; + iter = iter + sizeof(int); + int txnID = *(int*) iter; iter += sizeof(int); + int loglen = *(int*) iter; iter += sizeof(int); + int stmtID = *(int*)iter; + iter = iter + sizeof(int); + int len = *(int*)iter; + iter = iter + sizeof(int); + strncpy(stmtString, iter, len); + iter = iter + len; + printDebug(DM_Recovery, "EXECDIRECT SID:%d TID:%d STMT:%s\n", stmtID, txnID, stmtString); + if (list) { + printf("EXECDIRECT SID:%d TID:%d STMT:%s\n", stmtID, txnID, stmtString); + return OK; + } + AbsSqlStatement *stmt = SqlFactory::createStatement(CSqlDirect); + if ( NULL == stmt) { + printError(ErrSysInternal, "unable to prepare:%s", stmtString); + return ErrSysInternal; + } + stmt->setConnection(conn); + if (interactive) printf("EXECDIRECT %d : %s\n", stmtID, stmtString); + rv = stmt->prepare(stmtString); + if (rv != OK) { + printError(ErrSysInternal, "unable to prepare:%s", stmtString); + stmt->free(); + delete stmt; + return ErrSysInternal; + } + rv = stmt->execute(ret); + if(rv != OK) { + if (strlen(stmtString) > 6 && + ( (strncasecmp(stmtString,"CREATE", 6) == 0) || + (strncasecmp(stmtString,"DROP", 4) == 0) || + (strncasecmp(stmtString,"RENAME", 6) == 0) || + (strncasecmp(stmtString,"ALTER", 5) == 0)) ) { + return OK; + } + printError(ErrSysInternal, "unable to execute %s", stmtString); + stmt->free(); + return ErrSysInternal; + } + stmt->free(); + delete stmt; + return OK; +} diff --git a/src/storage/Debug.cxx b/src/storage/Debug.cxx index 93880355..e2737d39 100644 --- a/src/storage/Debug.cxx +++ b/src/storage/Debug.cxx @@ -22,10 +22,11 @@ int DebugDM_Lock = 0; int DebugDM_Transaction = 0; int DebugDM_UndoLog = 0; int DebugDM_RedoLog = 0; +int DebugDM_Recovery = 0; int DebugDM_Index = 0; int DebugDM_HashIndex = 0; int DebugDM_TreeIndex = 0; -int DebugDM_TrieIndex = 1; +int DebugDM_TrieIndex = 0; int DebugDM_SystemDatabase = 0; int DebugDM_Database = 0; int DebugDM_Table = 0; @@ -96,7 +97,9 @@ int printDebug1(int module, char *fname, int lno, const char *format, ...) case DM_Transaction: { if (!DebugDM_Transaction) return 1; break; } case DM_UndoLog: { if (!DebugDM_UndoLog) return 1; break; } case DM_RedoLog: { if (!DebugDM_RedoLog) return 1; break; } + case DM_Recovery: { if (!DebugDM_Recovery) return 1; break; } case DM_HashIndex: { if (!DebugDM_HashIndex) return 1; break; } + case DM_TrieIndex: { if (!DebugDM_TrieIndex) return 1; break; } case DM_TreeIndex: { if (!DebugDM_TreeIndex) return 1; break; } case DM_SystemDatabase: { if (!DebugDM_SystemDatabase) return 1; break; } case DM_Database: { if (!DebugDM_Database) return 1; break; } diff --git a/src/tools/applyofflinelogs.cxx b/src/tools/applyofflinelogs.cxx index eda4e8ff..bbbdf2ca 100644 --- a/src/tools/applyofflinelogs.cxx +++ b/src/tools/applyofflinelogs.cxx @@ -17,8 +17,7 @@ #include #include #include -#define DEBUG 1 - +#include AbsSqlConnection *conn; void *stmtBuckets; @@ -71,7 +70,9 @@ int main(int argc, char **argv) counter++; } printf("All the applied log files have been successfully removed.\n"); - SqlStatement::freeAllStmtHandles(stmtBuckets); + Recovery recovery; + recovery.setStmtBucket(stmtBuckets); + recovery.freeAllStmtHandles(); conn->disconnect(); delete conn; return 0; @@ -110,6 +111,8 @@ int applyOfflinelogs(char *fileName, bool interactive) int loglen; char stmtString[SQL_STMT_LEN]; //printf("size of file %d\n", st.st_size); + Recovery recovery; + recovery.setStmtBucket(stmtBuckets); while(true) { //printf("OFFSET HERE %d\n", iter - (char*)startAddr); if (iter - (char*)startAddr >= st.st_size) break; @@ -134,7 +137,7 @@ int applyOfflinelogs(char *fileName, bool interactive) retVal=1; break; } - SqlStatement::addToHashTable(stmtID, stmt, stmtBuckets, stmtString); + recovery.addToHashTable(stmtID, stmt, stmtString); } else if(logType == -2) { //commit conn->beginTrans(); @@ -157,7 +160,7 @@ int applyOfflinelogs(char *fileName, bool interactive) eType = *(int*)iter; //printf("eType is %d\n", eType); AbsSqlStatement *stmt = - SqlStatement::getStmtFromHashTable(stmtID, stmtBuckets); + recovery.getStmtFromHashTable(stmtID); if (0 == eType) { //execute type iter = iter + sizeof(int); //printf("EXEC: %d\n", stmtID); @@ -197,11 +200,10 @@ int applyOfflinelogs(char *fileName, bool interactive) stmtID = *(int*)iter; iter = iter + sizeof(int); if (interactive) printf("FREE %d:\n", stmtID); - AbsSqlStatement *stmt = SqlStatement::getStmtFromHashTable(stmtID, - stmtBuckets); + AbsSqlStatement *stmt = recovery.getStmtFromHashTable(stmtID); if (stmt) { stmt->free(); - SqlStatement::removeFromHashTable(stmtID, stmtBuckets); + recovery.removeFromHashTable(stmtID); } else { printError(ErrSysInternal, "statement not found for %d\n",stmtID);} } else if(logType == -4) { //prepare and execute diff --git a/src/tools/csqlasyncserver.cxx b/src/tools/csqlasyncserver.cxx index 834bf7c9..12314004 100644 --- a/src/tools/csqlasyncserver.cxx +++ b/src/tools/csqlasyncserver.cxx @@ -29,6 +29,7 @@ #include #include //for BindSqlField #include +#include typedef struct FailedStmtObject { int stmtId; @@ -395,10 +396,12 @@ DbRetVal handlePrepare(void *data, void *conn, void *stmtBuckets, prepareFailList->append(fst); return rv; } - SqlStatement::addToHashTable(stmtId, stmt, stmtBuckets, stmtstr); + Recovery recovery; + recovery.setStmtBucket(stmtBuckets); + recovery.addToHashTable(stmtId, stmt, stmtstr); printDebug(DM_CacheServer, "returning from prepare"); return rv; -}; +} DbRetVal handleCommit(void *data, int len, void *conn, void *stmtBuckets, List *prepareFailList) @@ -418,11 +421,12 @@ DbRetVal handleCommit(void *data, int len, void *conn, void *stmtBuckets, printError(rv, "Begin trans failed"); return rv; } + Recovery recovery; + recovery.setStmtBucket(stmtBuckets); while ((ptr - (char *)data) < len) { int stmtId = *(int *)ptr; ptr += sizeof(int); - AbsSqlStatement *stmt = SqlStatement::getStmtFromHashTable(stmtId, - stmtBuckets); + AbsSqlStatement *stmt = recovery.getStmtFromHashTable(stmtId); printDebug(DM_CacheServer, "commit: stmtId: %d", stmtId); printDebug(DM_CacheServer, "commit: stmtbuckets: %x", stmtBuckets); printDebug(DM_CacheServer, "commit: stmt: %x", stmt); @@ -490,8 +494,9 @@ DbRetVal handleFree(void *data, void *stmtBuckets, List *prepareFailList) int len = *(int *) ptr; ptr += sizeof(int); int txnId = *(int *) ptr; ptr += sizeof(int); int stmtId = *(int *)ptr; - AbsSqlStatement *stmt = SqlStatement::getStmtFromHashTable(stmtId, - stmtBuckets); + Recovery recovery; + recovery.setStmtBucket(stmtBuckets); + AbsSqlStatement *stmt = recovery.getStmtFromHashTable(stmtId); FailStmt *elem = NULL; if (stmt == NULL) { ListIterator failListIter = prepareFailList->getIterator(); @@ -508,7 +513,7 @@ DbRetVal handleFree(void *data, void *stmtBuckets, List *prepareFailList) printError(rv, "HandleFree failed with return vlaue %d", rv); return rv; } - SqlStatement::removeFromHashTable(stmtId, stmtBuckets); + recovery.removeFromHashTable(stmtId); printDebug(DM_CacheServer, "Freed the statement from hashTable"); return OK; } diff --git a/src/tools/csqlcheckpointserver.cxx b/src/tools/csqlcheckpointserver.cxx index abd21005..40510356 100644 --- a/src/tools/csqlcheckpointserver.cxx +++ b/src/tools/csqlcheckpointserver.cxx @@ -28,6 +28,14 @@ static void sigTermHandler(int sig) printf("Received signal %d\nStopping the server\n", sig); srvStop = 1; } +static void sigChildHandler(int sig) +{ + os::signal(SIGCHLD, sigChildHandler); + int stat; + waitpid(-1, &stat, WNOHANG); + //TODO::move waitpid to os wrapper +} + void printUsage() { @@ -105,7 +113,7 @@ int main(int argc, char **argv) } os::signal(SIGINT, sigTermHandler); os::signal(SIGTERM, sigTermHandler); - os::signal(SIGCHLD, SIG_IGN); + os::signal(SIGCHLD, sigChildHandler); if (!Conf::config.useDurability()) { diff --git a/src/tools/redo.cxx b/src/tools/redo.cxx dissimilarity index 76% index 1d12c218..31ae1331 100644 --- a/src/tools/redo.cxx +++ b/src/tools/redo.cxx @@ -1,311 +1,76 @@ -/*************************************************************************** - * Copyright (C) 2007 by www.databasecache.com * - * Contact: praba_tuty@databasecache.com * - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License for more details. * - * * - ***************************************************************************/ -#include -#include -#include -#include - -AbsSqlConnection *conn; -void *stmtBuckets = NULL; -bool list = false; -bool interactive=false; -char fileName[MAX_FILE_LEN]; - -int main(int argc, char **argv) -{ - struct stat st; - strcpy(fileName, ""); - int c = 0, opt=0; - while ((c = getopt(argc, argv, "f:ail?")) != EOF) { - switch (c) { - case '?' : { opt = 1; break; } //print help - case 'a' : { opt = 2; break; } - case 'i' : { interactive = true; break; } - case 'l' : { list = true; break; } - case 'f' : {strcpy(fileName , argv[optind - 1]); break;} - default: printf("Wrong args\n"); exit(1); - - } - }//while options - if (2 !=opt) { - printf("This is an internal csql command with i and f options."); - exit(1); - } - char *verbose = os::getenv("CSQL_INTERACTIVE"); - if (verbose !=NULL && strcmp(verbose, "true") == 0) - { - printf("VERBOSE ON %s\n", verbose); - interactive=true; - } - - conn = SqlFactory::createConnection(CSqlDirect); - DbRetVal rv = conn->connect(I_USER, I_PASS); - if (rv != OK) { - printError(ErrNoConnection, "REDO: could not connect to DB."); - delete conn; - return 2; - } - - if (strcmp(fileName, "") ==0) { - sprintf(fileName, "%s/csql.db.cur", Conf::config.getDbFile()); - } - int fd = open(fileName, O_RDONLY); - if (-1 == fd) { conn->disconnect(); delete conn; return OK; } - if (fstat(fd, &st) == -1) { - printError(ErrSysInternal, "Unable to retrieve undo log file size"); - close(fd); - conn->disconnect(); - delete conn; - return 3; - } - if (st.st_size ==0) { - printError(ErrNote, "No Redo logs found during recovery"); - SqlStatement::readAndPopulateStmts(conn, stmtBuckets, list, interactive); - close(fd); - conn->disconnect(); - delete conn; - return 0; - } - SqlConnection *sCon = (SqlConnection*) conn; - if(!list) rv = sCon->getExclusiveLock(); - //during connection close, this exclusive lock will be automatically released - if (rv != OK) { - close(fd); - conn->disconnect(); - delete conn; - return 4; - } - void *startAddr = mmap(NULL, st.st_size, PROT_READ, MAP_PRIVATE, fd, 0); - if (MAP_FAILED == startAddr) { - printf("Unable to read undo log file:mmap failed.\n"); - conn->disconnect(); - delete conn; - return 5; - } - rv = SqlStatement::readAndPopulateStmts(conn, stmtBuckets, list, interactive); - if (OK != rv) - { - printf("Unable to read stmt log file\n"); - conn->disconnect(); - delete conn; - return 6; - } - - printf("Redo log filename is :%s\n", fileName); - char *iter = (char*)startAddr; - void *value = NULL; - int logType, eType; - int stmtID; - int txnID; - int len, ret, retVal =0; - int loglen; - char stmtString[SQL_STMT_LEN]; - //printf("size of file %d\n", st.st_size); - while(true) { - //printf("OFFSET HERE %d\n", iter - (char*)startAddr); - if (iter - (char*)startAddr >= st.st_size) break; - logType = *(int*)iter; - if (logType == -1) { //prepare - iter = iter + sizeof(int); - txnID = *(int*) iter; iter += sizeof(int); - loglen = *(int*) iter; iter += sizeof(int); - stmtID = *(int*)iter; - iter = iter + sizeof(int); - len = *(int*)iter; - iter = iter + sizeof(int); - strncpy(stmtString, iter, len); - iter = iter + len; - if (list) { - printf("PREPARE: SID:%d %s\n", stmtID, stmtString); - continue; - } - AbsSqlStatement *stmt = SqlFactory::createStatement(CSqlDirect); - stmt->setConnection(conn); - if (interactive) printf("PREPARE %d : %s\n", stmtID, stmtString); - rv = stmt->prepare(stmtString); - if (rv != OK) { - printError(ErrSysInternal, "unable to prepare stmt:%s", stmtString); - retVal=1; - break; - } - SqlStatement *sqlStmt = (SqlStatement*)stmt; - sqlStmt->setLoading(true); - SqlStatement::addToHashTable(stmtID, stmt,stmtBuckets, stmtString); - } - else if(logType == -2) { //commit - conn->beginTrans(); - iter = iter + sizeof(int); - txnID = *(int*) iter; iter += sizeof(int); - loglen = *(int*) iter; iter += sizeof(int); - char *curPtr = iter; - while(true) { - //printf("Iter length %d\n", iter - curPtr); - if (iter - (char*)startAddr >= st.st_size) { - //file end reached - //printf("Redo log file end\n"); - retVal=0; - break; - } - stmtID = *(int*)iter; - //printf("stmtid %d\n", stmtID); - if (interactive) printf("EXEC %d :\n", stmtID); - iter = iter + sizeof(int); - eType = *(int*)iter; - //printf("eType is %d\n", eType); - AbsSqlStatement *stmt = NULL; - if (!list) { - stmt = SqlStatement::getStmtFromHashTable(stmtID,stmtBuckets); - if (NULL == stmt) { - printError(ErrSysInternal, "Unable to find in stmt hashtable"); - retVal=2; - break; - } - } - if (0 == eType) { //execute type - iter = iter + sizeof(int); - if (list) { - printf("EXEC SID:%d TID:%d\n", stmtID, txnID); - if (*(int*)iter <0) break; - continue; - } - if (stmt) { - rv = stmt->execute(ret); - if (rv != OK) { - printError(ErrSysInternal, "unable to execute"); - retVal=2; - break; - } - } else { - printError(ErrSysInternal, "statement not found for %d\n",stmtID); - } - if (*(int*)iter <0) break; - } else if ( 1 == eType) { //set type - iter=iter+sizeof(int); - int pos = *(int*) iter; - iter=iter+sizeof(int); - int isNull = *(int *) iter; - iter=iter+sizeof(int); - if (isNull == 0) { - DataType type = (DataType)(*(int*)iter); - iter=iter+sizeof(int); - int len = *(int*) iter; - iter=iter+sizeof(int); - value = iter; - iter=iter+len; - if (list) { - printf("SET SID:%d POS:%d ISNULL:FALSE TYPE:%d LEN:%d Value:", stmtID, pos, type, len); - AllDataType::printVal(value, type, len); - printf("\n"); - if (*(int*)iter <0) break; - continue; - } - SqlStatement::setParamValues(stmt, pos, type, len, value); - } else { - if (list) { - printf("SET SID:%d POS:%d ISNULL:TRUE\n", stmtID, pos); - continue; - } - stmt->setNull(pos); - } - if (*(int*)iter <0) break; - } - } - conn->commit(); - } - else if(logType == -3) { //free - iter = iter + sizeof(int); - txnID = *(int*) iter; iter += sizeof(int); - loglen = *(int*) iter; iter += sizeof(int); - stmtID = *(int*)iter; - iter = iter + sizeof(int); - if (list) { - printf("FREE SID:%d \n", stmtID); - continue; - } - if (interactive) printf("FREE %d:\n", stmtID); - AbsSqlStatement *stmt = SqlStatement::getStmtFromHashTable(stmtID, - stmtBuckets); - if (stmt) { - stmt->free(); - delete stmt; - SqlStatement::removeFromHashTable(stmtID,stmtBuckets); - } else { printError(ErrSysInternal, "statement not found for %d\n",stmtID);} - } - else if(logType == -4) { //prepare and execute - iter = iter + sizeof(int); - txnID = *(int*) iter; iter += sizeof(int); - loglen = *(int*) iter; iter += sizeof(int); - stmtID = *(int*)iter; - iter = iter + sizeof(int); - len = *(int*)iter; - iter = iter + sizeof(int); - strncpy(stmtString, iter, len); - iter = iter + len; - if (list) { - printf("EXECDIRECT SID:%d TID:%d STMT:%s\n", stmtID, txnID, stmtString); - continue; - } - AbsSqlStatement *stmt = SqlFactory::createStatement(CSqlDirect); - if ( NULL == stmt) { - printError(ErrSysInternal, "unable to prepare:%s", stmtString); - retVal=3; - break; - } - stmt->setConnection(conn); - if (interactive) printf("EXECDIRECT %d : %s\n", stmtID, stmtString); - rv = stmt->prepare(stmtString); - if (rv != OK) { - printError(ErrSysInternal, "unable to prepare:%s", stmtString); - stmt->free(); - delete stmt; - retVal=4; - break; - } - rv = stmt->execute(ret); - if (rv != OK) { - if (strlen(stmtString) > 6 && - ( (strncasecmp(stmtString,"CREATE", 6) == 0) || - (strncasecmp(stmtString,"DROP", 4) == 0) || - (strncasecmp(stmtString,"RENAME", 6) == 0) || - (strncasecmp(stmtString,"ALTER", 5) == 0)) ) { - - // conn->disconnect(); - // return OK; - continue; - } - printError(ErrSysInternal, "unable to execute %s", stmtString); - stmt->free(); - retVal=5; - break; - } - stmt->free(); - delete stmt; - }else{ - printError(ErrSysInternal, "Redo log file corrupted: logType:%d", logType); - retVal=6; - break; - } - } - munmap((char*)startAddr, st.st_size); - close(fd); - if (!list) { - SqlStatement::filterAndWriteStmtLogs(stmtBuckets); - SqlStatement::freeAllStmtHandles(stmtBuckets); - } - conn->disconnect(); - delete conn; - return retVal; -} +/*************************************************************************** + * Copyright (C) 2007 by www.databasecache.com * + * Contact: praba_tuty@databasecache.com * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + ***************************************************************************/ +#include +#include +#include +#include +#include + +AbsSqlConnection *conn; +bool list = false; +bool interactive=false; +char fileName[MAX_FILE_LEN]; + +int main(int argc, char **argv) +{ + strcpy(fileName, ""); + int c = 0, opt=0; + while ((c = getopt(argc, argv, "f:ail?")) != EOF) { + switch (c) { + case '?' : { opt = 1; break; } //print help + case 'a' : { opt = 2; break; } + case 'i' : { interactive = true; break; } + case 'l' : { list = true; break; } + case 'f' : {strcpy(fileName , argv[optind - 1]); break;} + default: printf("Wrong args\n"); exit(1); + + } + }//while options + if (2 !=opt) { + printf("This is an internal csql command with i and f options."); + exit(1); + } + char *verbose = os::getenv("CSQL_INTERACTIVE"); + if (verbose !=NULL && strcmp(verbose, "true") == 0) + { + printf("VERBOSE ON %s\n", verbose); + interactive=true; + } + conn = SqlFactory::createConnection(CSqlDirect); + DbRetVal rv = conn->connect(I_USER, I_PASS); + if (rv != OK) { + printError(ErrNoConnection, "REDO: could not connect to DB."); + delete conn; + return 2; + } + + if (strcmp(fileName, "") ==0) { + sprintf(fileName, "%s/csql.db.cur", Conf::config.getDbFile()); + } + SqlConnection *sCon = (SqlConnection*) conn; + if(!list) rv = sCon->getExclusiveLock(); + //during connection close, this exclusive lock will be automatically released + if (rv != OK) { + conn->disconnect(); + delete conn; + return 4; + } + Recovery recovery; + int retVal = recovery.applyRedoLogs(fileName, conn, list, interactive); + conn->disconnect(); + delete conn; + return retVal; +} -- 2.11.4.GIT