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: sessionmanagerserver.h 1906 2013-06-14 19:15:32Z rdempsey $
20  *
21  *****************************************************************************/
22 
23 /** @file
24  * class SessionManagerServer interface
25  */
26 
27 #ifndef _SESSIONMANAGERSERVER_H
28 #define _SESSIONMANAGERSERVER_H
29 
30 #include <map>
31 
32 #include <boost/shared_array.hpp>
33 #include <boost/thread/mutex.hpp>
34 #include <boost/thread/condition_variable.hpp>
35 
36 #include "calpontsystemcatalog.h"
37 #include "brmtypes.h"
38 
39 #include "atomicops.h"
40 
41 #if defined(_MSC_VER) && defined(xxxSESSIONMANAGERSERVER_DLLEXPORT)
42 #define EXPORT __declspec(dllexport)
43 #else
44 #define EXPORT
45 #endif
46 
47 #ifdef _MSC_VER
48 #pragma warning (push)
49 #pragma warning (disable : 4200)
50 #endif
51 
52 namespace BRM
53 {
54 
55 /** @brief Issues transaction IDs and keeps track of the current system-wide version ID.
56  *
57  * This class's primary purpose is to keep track of the current system-wide version ID and issue transaction IDs.
58  * It can be used simultaneously by multiple threads and processes.
59  *
60  * It uses system-wide semaphores and shared memory segments for IPC.
61  * It allocates both if they don't already exist, but it only deallocates
62  * the shmseg (saves it to a file so state isn't lost).  It may be a waste of
63  * CPU time to deallocate either while the system is running.  It may be more
64  * appropriate to do that in the DB shut down script.
65  *
66  * Note: Added a macro 'DESTROYSHMSEG' which enables/disables the code to load/save
67  * and deallocate the shared memory segment.
68  *
69  * This class uses 3 parameters from the Columnstore.xml file:
70  * SessionManager/MaxConcurrentTransactions: defines how many active transactions the
71  * 		system should support.  When a new request comes in and there are already
72  * 		MaxConcurrentTransactions active, the new request blocks by default.  The
73  * 		default value is 1000.
74  * SessionManager/SharedMemoryTmpFile: the file to store the shared memory segment
75  * 		data in between invocations if DESTROYSHMSEG is defined below.  The
76  * 		default is /tmp/ColumnstoreShm.
77  * SessionManager/TxnIDFile: the file to store the last transaction ID issued
78  */
79 
80 /*
81  * Define DESTROYSHMSEG if the SM should deallocate the shared memory segment
82  * after the last reference has died.  This also enables the load/save
83  * operations.  If it is undefined, the segment is never deallocated
84  * by SM, and is therefore more efficient between instances.
85  * NOTE: It seems that valgrind doesn't work well with shared memory segments.
86  * Specifically, when the code executes shmctl(IPC_RMID), which normally means
87  * "destroy the segment when refcount == 0", the segment is destroyed
88  * immediately, causing all subsequent references to fail.  This only affects
89  * 'leakcheck'.
90  */
91 //#define DESTROYSHMSEG
92 
93 class SessionManagerServer
94 {
95 public:
96     /** @brief SID = Session ID */
97     typedef uint32_t SID;
98 
99     // State flags. These bit values are stored in Overlay::state and reflect the current state of the system
100     static const uint32_t SS_READY;				/// bit 0 => Set by dmlProc one time when dmlProc is ready
101     static const uint32_t SS_SUSPENDED;			/// bit 1 => Set by console when the system has been suspended by user.
102     static const uint32_t SS_SUSPEND_PENDING;	/// bit 2 => Set by console when user wants to suspend, but writing is occuring.
103     static const uint32_t SS_SHUTDOWN_PENDING;	/// bit 3 => Set by console when user wants to shutdown, but writing is occuring.
104     static const uint32_t SS_ROLLBACK;			/// bit 4 => In combination with a PENDING flag, force a rollback as soom as possible.
105     static const uint32_t SS_FORCE;				/// bit 5 => In combination with a PENDING flag, force a shutdown without rollback.
106     static const uint32_t SS_QUERY_READY;		/// bit 6 => Set by ProcManager when system is ready for queries
107 
108     /** @brief Constructor
109      *
110      * This sets up the shared memory segment & semaphores used by this
111      * instance.  No additional set-up calls are necessary.
112      * @note throws ios_base::failure on file IO error, runtime_error for
113      * other types of errors.  It might be worthwhile to define additional
114      * exceptions for all the different types of failures that can happen
115      * here.
116      */
117     EXPORT SessionManagerServer();
118 
119     /** @brief Destructor
120      *
121      * This detaches the shared memory segment.  If DESTROYSHMSEG is defined and this
122      * is the last reference to it, it will be saved to disk and destroyed.
123      * It does not destroy the semaphores.  Those persist until the system
124      * is shut down.
125      */
126     virtual ~SessionManagerServer();
127 
128     /** @brief Gets the current version ID
129      *
130      * Gets the current version ID.
131      */
132     EXPORT const QueryContext verID();
133 
134     /** @brief Gets the current version ID
135      *
136      * Gets the current version ID.
137      */
138     EXPORT const QueryContext sysCatVerID();
139 
140     /** @brief Gets a new Transaction ID
141      *
142      * Makes a new Transaction ID, associates it with the given session
143      * and increments the system-wide version ID
144      * @note This blocks until (# active transactions) \< MaxTxns unless block == false
145      * @note Throws runtime_error on semaphore-related error
146      * @note This will always return a valid TxnID unless block == false, in which case
147      * it will return a valid TxnID iff it doesn't have to block.
148      * @param session The session ID to associate with the transaction ID
149      * @param block If true, this will block until there is an available slot, otherwise
150      * it will return a TxnID marked invalid, signifying that it could not start a new transaction
151      * @return The new transaction ID.
152      */
153     EXPORT const TxnID newTxnID(const SID session, bool block = true, bool isDDL = false);
154 
155     /** @brief Record that a transaction has been committed
156      *
157      * Record that a transaction has been committed.
158      * @note Throws runtime_error on a semaphore-related error, invalid_argument
159      * when txnid can't be found
160      * @param txnid The committed transaction ID.  This is marked invalid
161      * on return.
162      */
committed(TxnID & txn)163     void committed(TxnID& txn)
164     {
165         finishTransaction(txn);
166     }
167 
168     /** @brief Record that a transaction has been rolled back
169      *
170      * Record that a transaction has been rolled back.
171      * @note Throws runtime_error on a semaphore-related error, invalid_argument
172      * when txnid can't be found
173      * @param txnid The rolled back transaction ID.  This is marked invalid
174      * on return.
175      */
rolledback(TxnID & txn)176     void rolledback(TxnID& txn)
177     {
178         finishTransaction(txn);
179     }
180 
181     /** @brief Gets the transaction ID associated with a given session ID
182      *
183      * Gets the transaction ID associated with a given session ID.
184      * @note Throws runtime_error on a semaphore-related error
185      * @param session The session ID
186      * @return A valid transaction ID if there's an association; an invalid
187      * one if there isn't.
188      */
189     EXPORT const TxnID getTxnID(const SID session);
190 
191     /** @brief Gets an array containing all active SID-TID associations
192      *
193      * Gets an array containing the SID-TID associations of all active
194      * transactions.  This is intended to be used by another object
195      * that can determine which sessions are still live and which
196      * transactions need to go away.
197      * @note Throws runtime_error on a semaphore-related error
198      * @param len (out) the length of the array
199      * @return A pointer to the array.  Note: The caller is responsible for
200      * deallocating it.  Use delete[].
201      */
202     EXPORT boost::shared_array<SIDTIDEntry> SIDTIDMap(int& len);
203 
204     /**
205      * get a unique 32-bit number
206      */
getUnique32()207     uint32_t getUnique32()
208     {
209         return atomicops::atomicInc(&unique32);
210     }
211 
212     /**
213      * get a unique 64-bit number
214      */
getUnique64()215     uint64_t getUnique64()
216     {
217         return atomicops::atomicInc(&unique64);
218     }
219 
220     /** @brief Resets the semaphores to their original state.  For testing only.
221      *
222      * Resets the semaphores to their original state.  For testing only.
223      */
224     EXPORT void reset();
225 
226     /**
227      * get the Txn ID filename
228      */
getTxnIDFilename()229     std::string getTxnIDFilename() const
230     {
231         return txnidFilename;
232     }
233 
234     /** @brief set system state info
235      *
236      * Sets the bits on in Overlay::systemState that are found on in
237      * state. That is Overlay::systemState | state.
238      */
239     EXPORT void setSystemState(uint32_t state);
240 
241     /** @brief set system state info
242      *
243      * Clears the bits on in Overlay::systemState that are found on
244      * in state. That is Overlay::systemState & ~state.
245      */
246     EXPORT void clearSystemState(uint32_t state);
247 
248     /** @brief get system state info
249      *
250      * Returns the Overlay::systemState flags
251      */
getSystemState(uint32_t & state)252     void getSystemState(uint32_t& state)
253     {
254         state = systemState;
255     }
256 
257     /**
258      * get the number of active txn's
259      */
260     EXPORT uint32_t getTxnCount();
261 
262 private:
263     SessionManagerServer(const SessionManagerServer&);
264     SessionManagerServer& operator=(const SessionManagerServer&);
265 
266     void loadState();
267     void saveSystemState();
268     void finishTransaction(TxnID& txn);
269     void saveSMTxnIDAndState();
270 
271     volatile uint32_t unique32;
272     volatile uint64_t unique64;
273 
274     int maxTxns;  // the maximum number of concurrent transactions
275     std::string txnidFilename;
276     execplan::CalpontSystemCatalog::SCN _verID;
277     execplan::CalpontSystemCatalog::SCN _sysCatVerID;
278     uint32_t systemState;
279 
280     std::map<SID, execplan::CalpontSystemCatalog::SCN> activeTxns;
281     typedef std::map<SID, execplan::CalpontSystemCatalog::SCN>::iterator iterator;
282 
283     boost::mutex mutex;
284     boost::condition_variable condvar;		// used to synthesize a semaphore
285     uint32_t semValue;
286 };
287 
288 }   //namespace
289 
290 #ifdef _MSC_VER
291 #pragma warning (pop)
292 #endif
293 
294 #undef EXPORT
295 
296 #endif
297