/* 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: sessionmonitor.h 9210 2013-01-21 14:10:42Z rdempsey $ * *****************************************************************************/ /** @file * class SessionMonitor interface */ #pragma once #include #include #include #include #include "calpontsystemcatalog.h" #include "sessionmanager.h" #include "shmkeys.h" #include "brmtypes.h" // #define SM_DEBUG namespace execplan { /** @brief Identifies stale and orphaned transaction IDs. * * * This class uses 2 parameters from the Columnstore.xml file: * SessionManager/MaxConcurrentTransactions: defines how many active transactions the * system should support. When a new request comes in and there are already * MaxConcurrentTransactions active, the new request blocks by default. The * default value is 1000. * * SessionMonitor/SharedMemoryTmpFile: the file to store the shared memory segment * data in. This needs to be a different file than * file used for the SessionManager/SharedMemoryTmpFile. */ /* * NOTE: It seems that valgrind doesn't work well with shared memory segments. * Specifically, when the code executes shmctl(IPC_RMID), which normally means * "destroy the segment when refcount == 0", the segment is destroyed * immediately, causing all subsequent references to fail. This only affects * 'leakcheck'. * This comment is originally from SessionManager.h. I am assuming we will see * the same behavior here. */ class SessionMonitor { public: /** @brief A type describing a single transaction ID */ struct MonTxnID { /// The TransactionID number CalpontSystemCatalog::SCN id; /// True if the id is valid. bool valid; /// timestamp of firstrecord of this TID time_t firstrecord; MonTxnID() { id = 0; valid = false; firstrecord = 0; }; }; /** @brief A type describing a single transaction ID */ typedef struct MonTxnID MonTxnID; /** @brief A type associating a session with a transaction */ struct MonSIDTIDEntry { /// The Transaction ID. txnid.valid determines whether or not this SIDTIDEntry is valid MonTxnID txnid; /// The session doing the transaction SessionManager::SID sessionid; MonSIDTIDEntry() { txnid = MonTxnID(); sessionid = 0; }; }; /** @brief A type associating a session with a transaction */ typedef struct MonSIDTIDEntry MonSIDTIDEntry_t; /** @brief Vector of MonSIDTIDEntry structures */ typedef std::vector MonSIDTIDEntryVector_t; /** @brief needed to sort txns list in find timedOutTnxs()*/ struct lessMonSIDTIDEntry { bool operator()(MonSIDTIDEntry const* p1, MonSIDTIDEntry const* p2) { if (!p1) return true; if (!p2) return false; return p1->txnid.firstrecord < p2->txnid.firstrecord; } }; /** @brief monitor version of the SessionManagerData */ struct SessionMonitorData_struct { int txnCount; CalpontSystemCatalog::SCN verID; MonSIDTIDEntry_t* activeTxns; SessionMonitorData_struct() { txnCount = 0; verID = 0; activeTxns = nullptr; }; }; typedef struct SessionMonitorData_struct SessionMonitorData_t; /** @brief typedef if SessionManager struct SIDTIDEntry. For convenience.*/ typedef BRM::SIDTIDEntry SIDTIDEntry_t; /** @brief This struct describes the layout of the shared memory segment copied from SessionManager.h */ struct SessionManagerData_struct { int txnCount; CalpontSystemCatalog::SCN verID; CalpontSystemCatalog::SCN syscatVerID; int systemstate; boost::interprocess::interprocess_semaphore sems[2]; SIDTIDEntry_t activeTxns[]; }; typedef SessionManagerData_struct SessionManagerData_t; /** @brief Constructor * * This attaches to existing shared memory segments. * @note throws ios_base::failure on file IO error, runtime_error for * other types of errors. It might be worthwhile to define additional * exceptions for all the different types of failures that can happen * here. */ SessionMonitor(); /** @brief Destructor * * This detaches the shared memory segment then saves it * to disk and destroyed. It does not destroy the semaphores * or the shared memory segment. Deletes the local copies * of the SessionManager data and SessionMonitor data. */ virtual ~SessionMonitor(); const int maxTxns() const { return fMaxTxns; } const int txnCount() const; /** * @brief identifies timed out SessionManager structures * @param * @return */ MonSIDTIDEntryVector_t timedOutTxns(); const SessionMonitorData_t* previousManagerData() { return &fPrevSegment; } SessionManagerData_t* currentManagerData() { return fCurrentSegment; } const SessionManagerData_t* sessionManagerData() { return fSessionManagerData; } void printTxns(const MonSIDTIDEntry_t& txn) const; #ifdef SM_DEBUG void printSegment(const SessionManagerData_t* seg, const int l = 1000) const; void printMonitorData(const int l = 1000) const; void printTxns(const SIDTIDEntry_t& txn) const; #endif const int AgeLimit() const { return fAgeLimit; // to speed up testing } void AgeLimit(const int& age) { fAgeLimit = age; } const char* segmentFilename() const { return fSegmentFilename.c_str(); } bool haveSemaphores() const { return fHaveSemaphores; } bool haveSharedMemory() const { return fIsAttached; } private: int fMaxTxns; // the maximum number of concurrent transactions static const int fMaxRetries = 10; // the max number of retries on file IO std::string fSegmentFilename; // filename used to store the image of the SessionManager data time_t fDefaultAgeLimit; time_t fAgeLimit; // age limit in seconds used to timeout/orpan a transaction SessionMonitorData_t fSessionMonitorData; // pointer to in memory copy of the Monitor data SessionMonitorData_t fPrevSegment; // in memory copy of SessionManager data from backup file SessionManagerData_t* fCurrentSegment; // in memory of SessionManager data SessionManagerData_t* fSessionManagerData; // current shared memory SessionManager data // refers to 2 semaphores; the first is a mutex that guards the shmseg // the second is used to block processes when there are too many concurrent txns int fsems; int fshmid; // shared memory segment id uint32_t fuid; // user id used to create the shared memory key SessionManager sm; bool isStaleSIDTID(const SIDTIDEntry_t& src, const MonSIDTIDEntry_t& dest) const; bool isEqualSIDTID(const SIDTIDEntry_t& src, const MonSIDTIDEntry_t& dest) const; bool isUsedSIDTID(const SIDTIDEntry_t& e) const; bool isUsed(const MonSIDTIDEntry_t& e) const; /** * @brief attached to SessionManagerData shared memory * @param * @return void */ void getSharedData(void); bool fIsAttached; /** * @brief unattached from SessionManagerData shared memory * @param * @return void */ void detachSegment(void); /** * @brief initialize SessionMonitorData * @param * @return void */ void initSegment(SessionMonitorData_t* seg); /** * @brief initialize SessionManagerData * @param * @return void */ void initSegment(SessionManagerData_t* seg); const key_t IPCKey() const { return fShmKeys.SESSIONMANAGER_SYSVKEY; }; /** * @brief copies the SessionMonitor data from a file into memory * @param * @return void */ void copyPreviousSegment(); /** * @brief copies the SessionManager data from shared memory into an SessionMonitor memory * @param * @return void */ void copyCurrentSegment(); /** * @brief Reads the SM data from file into memory. Used by copyPreviousSegment(). * @param * @return bool */ bool readMonitorDataFromFile(const std::string); /** * @brief write the current SessionManagerData as SessionMonitorData to a file. * @param * @return void */ void saveAsMonitorData(const std::string); bool fHaveSemaphores; /** * @brief get the SessionManager semaphores * @param * @return void */ int getSems(void); void lock(void); void unlock(void); /** * @brief do not use the copy constructor. * @param * @return */ SessionMonitor(const SessionMonitor&); private: BRM::ShmKeys fShmKeys; }; } // namespace execplan