1 /* Copyright (C) 2014 InfiniDB, Inc. 2 3 This program is free software; you can redistribute it and/or 4 modify it under the terms of the GNU General Public License 5 as published by the Free Software Foundation; version 2 of 6 the License. 7 8 This program is distributed in the hope that it will be useful, 9 but WITHOUT ANY WARRANTY; without even the implied warranty of 10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 GNU General Public License for more details. 12 13 You should have received a copy of the GNU General Public License 14 along with this program; if not, write to the Free Software 15 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 16 MA 02110-1301, USA. */ 17 18 /****************************************************************************** 19 * $Id: sessionmonitor.h 9210 2013-01-21 14:10:42Z rdempsey $ 20 * 21 *****************************************************************************/ 22 23 /** @file 24 * class SessionMonitor interface 25 */ 26 27 #ifndef _SESSIONMONITOR_H 28 #define _SESSIONMONITOR_H 29 30 #include <vector> 31 #include <exception> 32 #include <sys/types.h> 33 #include <unistd.h> 34 35 #include "calpontsystemcatalog.h" 36 #include "sessionmanager.h" 37 #include "shmkeys.h" 38 #include "brmtypes.h" 39 40 //#define SM_DEBUG 41 42 namespace execplan 43 { 44 45 /** @brief Identifies stale and orphaned transaction IDs. 46 * 47 * 48 * This class uses 2 parameters from the Columnstore.xml file: 49 * SessionManager/MaxConcurrentTransactions: defines how many active transactions the 50 * system should support. When a new request comes in and there are already 51 * MaxConcurrentTransactions active, the new request blocks by default. The 52 * default value is 1000. 53 * 54 * SessionMonitor/SharedMemoryTmpFile: the file to store the shared memory segment 55 * data in. This needs to be a different file than 56 * file used for the SessionManager/SharedMemoryTmpFile. 57 */ 58 59 /* 60 * NOTE: It seems that valgrind doesn't work well with shared memory segments. 61 * Specifically, when the code executes shmctl(IPC_RMID), which normally means 62 * "destroy the segment when refcount == 0", the segment is destroyed 63 * immediately, causing all subsequent references to fail. This only affects 64 * 'leakcheck'. 65 * This comment is originally from SessionManager.h. I am assuming we will see 66 * the same behavior here. 67 */ 68 69 class SessionMonitor 70 { 71 public: 72 73 /** @brief A type describing a single transaction ID */ 74 struct MonTxnID 75 { 76 /// The TransactionID number 77 CalpontSystemCatalog::SCN id; 78 /// True if the id is valid. 79 bool valid; 80 /// timestamp of firstrecord of this TID 81 time_t firstrecord; MonTxnIDMonTxnID82 MonTxnID() 83 { 84 id = 0; 85 valid = false; 86 firstrecord = 0; 87 }; 88 }; 89 90 /** @brief A type describing a single transaction ID */ 91 typedef struct MonTxnID MonTxnID; 92 93 /** @brief A type associating a session with a transaction */ 94 struct MonSIDTIDEntry 95 { 96 /// The Transaction ID. txnid.valid determines whether or not this SIDTIDEntry is valid 97 MonTxnID txnid; 98 /// The session doing the transaction 99 SessionManager::SID sessionid; MonSIDTIDEntryMonSIDTIDEntry100 MonSIDTIDEntry() 101 { 102 txnid = MonTxnID(); 103 sessionid = 0; 104 }; 105 }; 106 107 /** @brief A type associating a session with a transaction */ 108 typedef struct MonSIDTIDEntry MonSIDTIDEntry_t; 109 110 /** @brief Vector of MonSIDTIDEntry structures */ 111 typedef std::vector<MonSIDTIDEntry_t*> MonSIDTIDEntryVector_t; 112 113 /** @brief needed to sort txns list in find timedOutTnxs()*/ 114 struct lessMonSIDTIDEntry 115 { operatorlessMonSIDTIDEntry116 bool operator()(MonSIDTIDEntry const* p1, MonSIDTIDEntry const* p2) 117 { 118 if (!p1) 119 return true; 120 121 if (!p2) 122 return false; 123 124 return p1->txnid.firstrecord < p2->txnid.firstrecord; 125 } 126 }; 127 128 /** @brief monitor version of the SessionManagerData */ 129 struct SessionMonitorData_struct 130 { 131 int txnCount; 132 CalpontSystemCatalog::SCN verID; 133 MonSIDTIDEntry_t* activeTxns; SessionMonitorData_structSessionMonitorData_struct134 SessionMonitorData_struct() 135 { 136 txnCount = 0; 137 verID = 0; 138 activeTxns = NULL; 139 }; 140 }; 141 typedef struct SessionMonitorData_struct SessionMonitorData_t; 142 143 /** @brief typedef if SessionManager struct SIDTIDEntry. For convenience.*/ 144 typedef BRM::SIDTIDEntry SIDTIDEntry_t; 145 /** @brief This struct describes the layout of the shared memory segment copied from SessionManager.h */ 146 struct SessionManagerData_struct 147 { 148 int txnCount; 149 CalpontSystemCatalog::SCN verID; 150 CalpontSystemCatalog::SCN syscatVerID; 151 int systemstate; 152 boost::interprocess::interprocess_semaphore sems[2]; 153 SIDTIDEntry_t activeTxns[]; 154 }; 155 typedef SessionManagerData_struct SessionManagerData_t; 156 157 /** @brief Constructor 158 * 159 * This attaches to existing shared memory segments. 160 * @note throws ios_base::failure on file IO error, runtime_error for 161 * other types of errors. It might be worthwhile to define additional 162 * exceptions for all the different types of failures that can happen 163 * here. 164 */ 165 SessionMonitor(); 166 167 /** @brief Destructor 168 * 169 * This detaches the shared memory segment then saves it 170 * to disk and destroyed. It does not destroy the semaphores 171 * or the shared memory segment. Deletes the local copies 172 * of the SessionManager data and SessionMonitor data. 173 */ 174 virtual ~SessionMonitor(); 175 maxTxns()176 const int maxTxns() const 177 { 178 return fMaxTxns; 179 } 180 const int txnCount() const; 181 182 /** 183 * @brief identifies timed out SessionManager structures 184 * @param 185 * @return 186 */ 187 MonSIDTIDEntryVector_t timedOutTxns(); 188 previousManagerData()189 const SessionMonitorData_t* previousManagerData() 190 { 191 return &fPrevSegment; 192 } currentManagerData()193 SessionManagerData_t* currentManagerData() 194 { 195 return fCurrentSegment; 196 } sessionManagerData()197 const SessionManagerData_t* sessionManagerData() 198 { 199 return fSessionManagerData; 200 } 201 202 void printTxns(const MonSIDTIDEntry_t& txn) const; 203 #ifdef SM_DEBUG 204 void printSegment(const SessionManagerData_t* seg, const int l = 1000) const; 205 void printMonitorData(const int l = 1000) const; 206 void printTxns(const SIDTIDEntry_t& txn) const; 207 #endif AgeLimit()208 const int AgeLimit() const 209 { 210 return fAgeLimit; // to speed up testing 211 } AgeLimit(const int & age)212 void AgeLimit(const int& age) 213 { 214 fAgeLimit = age; 215 } segmentFilename()216 const char* segmentFilename() const 217 { 218 return fSegmentFilename.c_str(); 219 } haveSemaphores()220 bool haveSemaphores() const 221 { 222 return fHaveSemaphores; 223 } haveSharedMemory()224 bool haveSharedMemory() const 225 { 226 return fIsAttached; 227 } 228 229 private: 230 231 int fMaxTxns; // the maximum number of concurrent transactions 232 static const int fMaxRetries = 10; // the max number of retries on file IO 233 std::string fSegmentFilename; // filename used to store the image of the SessionManager data 234 time_t fDefaultAgeLimit; 235 time_t fAgeLimit; // age limit in seconds used to timeout/orpan a transaction 236 237 SessionMonitorData_t fSessionMonitorData; // pointer to in memory copy of the Monitor data 238 SessionMonitorData_t fPrevSegment; // in memory copy of SessionManager data from backup file 239 SessionManagerData_t* fCurrentSegment; // in memory of SessionManager data 240 SessionManagerData_t* fSessionManagerData; // current shared memory SessionManager data 241 242 // refers to 2 semaphores; the first is a mutex that guards the shmseg 243 // the second is used to block processes when there are too many concurrent txns 244 int fsems; 245 int fshmid; // shared memory segment id 246 uint32_t fuid; // user id used to create the shared memory key 247 248 SessionManager sm; 249 250 bool isStaleSIDTID(const SIDTIDEntry_t& src, const MonSIDTIDEntry_t& dest) const; 251 bool isEqualSIDTID(const SIDTIDEntry_t& src, const MonSIDTIDEntry_t& dest) const; 252 bool isUsedSIDTID(const SIDTIDEntry_t& e) const; 253 bool isUsed(const MonSIDTIDEntry_t& e) const; 254 255 /** 256 * @brief attached to SessionManagerData shared memory 257 * @param 258 * @return void 259 */ 260 void getSharedData(void); 261 262 bool fIsAttached; 263 264 /** 265 * @brief unattached from SessionManagerData shared memory 266 * @param 267 * @return void 268 */ 269 void detachSegment(void); 270 271 /** 272 * @brief initialize SessionMonitorData 273 * @param 274 * @return void 275 */ 276 void initSegment(SessionMonitorData_t* seg); 277 278 /** 279 * @brief initialize SessionManagerData 280 * @param 281 * @return void 282 */ 283 void initSegment(SessionManagerData_t* seg); 284 IPCKey()285 const key_t IPCKey() const 286 { 287 return fShmKeys.SESSIONMANAGER_SYSVKEY; 288 }; 289 290 /** 291 * @brief copies the SessionMonitor data from a file into memory 292 * @param 293 * @return void 294 */ 295 void copyPreviousSegment(); 296 297 /** 298 * @brief copies the SessionManager data from shared memory into an SessionMonitor memory 299 * @param 300 * @return void 301 */ 302 void copyCurrentSegment(); 303 304 /** 305 * @brief Reads the SM data from file into memory. Used by copyPreviousSegment(). 306 * @param 307 * @return bool 308 */ 309 bool readMonitorDataFromFile(const std::string); 310 311 /** 312 * @brief write the current SessionManagerData as SessionMonitorData to a file. 313 * @param 314 * @return void 315 */ 316 void saveAsMonitorData(const std::string); 317 318 bool fHaveSemaphores; 319 320 /** 321 * @brief get the SessionManager semaphores 322 * @param 323 * @return void 324 */ 325 int getSems(void); 326 327 void lock(void); 328 329 void unlock(void); 330 331 /** 332 * @brief do not use the copy constructor. 333 * @param 334 * @return 335 */ 336 SessionMonitor(const SessionMonitor&); 337 338 private: 339 BRM::ShmKeys fShmKeys; 340 }; 341 342 } //namespace 343 344 #endif 345