/* Copyright (C) 2014 InfiniDB, Inc. 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; version 2 of the License. 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ /****************************************************************************** * $Id$ * *****************************************************************************/ // WWW - Check on header. /** @file * class ReplayTxnLog interface */ #include #include #include #include "calpontsystemcatalog.h" /** @brief Replays remaining transactions after a backup is restored. * * * This class replays transactions after a full backup has been restored. The class re-issues statements * from the DML/DDL log files allowing the database to be a state from a point in time after the backup * occurred. * * The user provides an Oracle user id and password as well as a stop date and time. Transactions that were * committed after the time of the backup through before the stop date and time will be replayed in the order * that they were committed. * * This program only works under the following conditions: * 1) A backup was restored including the Calpont database files, the file containing the last txnId, and the * corresponding Oracle files. * 2) The DML/DDL log files include the log entry for the backup and all of the transactions from the backup * time through the stop date and time provided by the user. 3) All of the transaction ids being replayed have * higher numbers than the transaction id from the backup. The procedure for resetting the txnId had not been * defined when this utility was written. We need to take this utility into account when defining the * procedure. * */ class ReplayTxnLog { public: /** @brief Constructor * user - The database user id. User will be prompted if passed blank. Program will * abort if invalid user / password combination. * * password - The database user's password. User will be prompted if passed blank. * * stopDate - The stopdate formatted as "mm/dd/yy@hh:mm:ss" or "Now". User will be * prompted if passed blank or the format is incorrect. * * ignoreBulkLoad - True if bulk load log entries are to be ignored. If false, the user * will be prompted with each bulk load entry. Bulk loads are not included * in the log, so the user would have to know that the bulk load will not * cause any sql errors because of dependent data if bulk load entries * are skipped. Otherwise, the user would have to re-apply bulk loads * each time this utility pauses. */ ReplayTxnLog(const std::string& user, const std::string& password, const std::string& stopDate, const bool& ignoreBulkLoad, const bool& reportMode); /** @brief processes the transaction replay. */ void process(); private: /* Passed in constructor. */ std::string fUser; std::string fPassword; std::string fStopDateStr; bool fIgnoreBulkLoad; /* Other private members. */ execplan::CalpontSystemCatalog::SCN fStartVersionID; execplan::CalpontSystemCatalog::SCN fDDLCount; execplan::CalpontSystemCatalog::SCN fCommitCount; execplan::CalpontSystemCatalog::SCN fRollbackCount; time_t fProgramStarted; time_t fStopDate; std::string fCurrentYearStr; std::string fLastSchemaOwner; enum LogEntryType { DML, DDL, ROLLBACK, XCOMMIT, BULKLOAD, BACKUP_START, BACKUP_END, REPLAY_TXN_START, REPLAY_TXN_END }; // WWW - COMMIT reserved? struct LogEntry { execplan::CalpontSystemCatalog::SCN fVersionID; std::string fSqlStatement; time_t fLogTime; std::string fSchemaOwner; LogEntryType type; LogEntry() : fVersionID(0), fSqlStatement(""), fLogTime(0), fSchemaOwner("") { } }; LogEntry fLogEntryFirstCommit; LogEntry fLogEntryLastCommit; struct ActiveTxn { execplan::CalpontSystemCatalog::SCN fVersionID; std::vector fStatements; }; std::vector fActiveTxns; /* Private functions */ void validateInput(); std::list getLogFileNames(); void replayTransactions(std::list& files); void processStatement(const LogEntry& logEntry); int split(vector& v, const std::string& str, const char& c); bool getNextCalpontLogEntry(ifstream& dataFile, LogEntry& logEntry); bool displaySummaryAndConfirm(const LogEntry& logEntry); void displayProgress(const std::string& fileName); void displayFinalSummary(); time_t convertLogDateStr(const std::string& mth, const std::string& day, const std::string& time); void checkDefinitions(); ReplayTxnLog(const ReplayTxnLog& rhs); // no copies ReplayTxnLog& operator=(const ReplayTxnLog& rhs); // no assignments }; namespace replaytxnlog { /** @brief wraps an Oracle session * This class provides an Oracle session interface allowing a session to be started, DML statements * to be executed, and closing the session. */ class DBSession { public: /** @brief starts the session. */ void startSession(const std::string& connectAsUser); /** @brief issues a DML or DDL statement. */ void issueStatement(const std::string& stmt); /** @brief issues a commit. */ void commit(); /** @brief issues a rollback. */ void rollback(); /** @brief ends the session. */ void endSession(); /** @brief returns the connected user or empty string if a session is not active. */ std::string getConnectedUser(); /** @brief constructor */ DBSession(); private: DBSession(const DBSession& rhs); // private ctor DBSession& operator=(const DBSession& rhs); std::string fConnectedUser; }; } // namespace replaytxnlog