1 //
2 // SessionPool.h
3 //
4 // Library: Data
5 // Package: SessionPooling
6 // Module: SessionPool
7 //
8 // Definition of the SessionPool class.
9 //
10 // Copyright (c) 2006, Applied Informatics Software Engineering GmbH.
11 // and Contributors.
12 //
13 // SPDX-License-Identifier: BSL-1.0
14 //
15
16
17 #ifndef Data_SessionPool_INCLUDED
18 #define Data_SessionPool_INCLUDED
19
20
21 #include "Poco/Data/Data.h"
22 #include "Poco/Data/PooledSessionHolder.h"
23 #include "Poco/Data/PooledSessionImpl.h"
24 #include "Poco/Data/Session.h"
25 #include "Poco/HashMap.h"
26 #include "Poco/Any.h"
27 #include "Poco/Timer.h"
28 #include "Poco/Mutex.h"
29 #include <list>
30
31
32 namespace Poco {
33 namespace Data {
34
35
36 class Data_API SessionPool: public RefCountedObject
37 /// This class implements session pooling for POCO Data.
38 ///
39 /// Creating a connection to a database is often a time consuming
40 /// operation. Therefore it makes sense to reuse a session object
41 /// once it is no longer needed.
42 ///
43 /// A SessionPool manages a collection of SessionImpl objects
44 /// (decorated with a PooledSessionImpl).
45 ///
46 /// When a SessionImpl object is requested, the SessionPool first
47 /// looks in its set of already initialized SessionImpl for an
48 /// available object. If one is found, it is returned to the
49 /// client and marked as "in-use". If no SessionImpl is available,
50 /// the SessionPool attempts to create a new one for the client.
51 /// To avoid excessive creation of SessionImpl objects, a limit
52 /// can be set on the maximum number of objects.
53 /// Sessions found not to be connected to the database are purged
54 /// from the pool whenever one of the following events occurs:
55 ///
56 /// - JanitorTimer event
57 /// - get() request
58 /// - putBack() request
59 ///
60 /// Not connected idle sessions can not exist.
61 ///
62 /// Usage example:
63 ///
64 /// SessionPool pool("ODBC", "...");
65 /// ...
66 /// Session sess(pool.get());
67 /// ...
68 {
69 public:
70 SessionPool(const std::string& connector,
71 const std::string& connectionString,
72 int minSessions = 1,
73 int maxSessions = 32,
74 int idleTime = 60);
75 /// Creates the SessionPool for sessions with the given connector
76 /// and connectionString.
77 ///
78 /// The pool allows for at most maxSessions sessions to be created.
79 /// If a session has been idle for more than idleTime seconds, and more than
80 /// minSessions sessions are in the pool, the session is automatically destroyed.
81
82 ~SessionPool();
83 /// Destroys the SessionPool.
84
85 Session get();
86 /// Returns a Session.
87 ///
88 /// If there are unused sessions available, one of the
89 /// unused sessions is recycled. Otherwise, a new session
90 /// is created.
91 ///
92 /// If the maximum number of sessions for this pool has
93 /// already been created, a SessionPoolExhaustedException
94 /// is thrown.
95
96 template <typename T>
get(const std::string & name,const T & value)97 Session get(const std::string& name, const T& value)
98 /// Returns a Session with requested property set.
99 /// The property can be different from the default pool
100 /// value, in which case it is reset back to the pool
101 /// value when the session is reclaimed by the pool.
102 {
103 Session s = get();
104 _addPropertyMap.insert(AddPropertyMap::value_type(s.impl(),
105 std::make_pair(name, s.getProperty(name))));
106 s.setProperty(name, value);
107
108 return s;
109 }
110
111 Session get(const std::string& name, bool value);
112 /// Returns a Session with requested feature set.
113 /// The feature can be different from the default pool
114 /// value, in which case it is reset back to the pool
115 /// value when the session is reclaimed by the pool.
116
117 int capacity() const;
118 /// Returns the maximum number of sessions the SessionPool will manage.
119
120 int used() const;
121 /// Returns the number of sessions currently in use.
122
123 int idle() const;
124 /// Returns the number of idle sessions.
125
126 int dead();
127 /// Returns the number of not connected active sessions.
128
129 int allocated() const;
130 /// Returns the number of allocated sessions.
131
132 int available() const;
133 /// Returns the number of available (idle + remaining capacity) sessions.
134
135 std::string name() const;
136 /// Returns the name for this pool.
137
138 static std::string name(const std::string& connector,
139 const std::string& connectionString);
140 /// Returns the name formatted from supplied arguments as "connector:///connectionString".
141
142 void setFeature(const std::string& name, bool state);
143 /// Sets feature for all the sessions.
144
145 bool getFeature(const std::string& name);
146 /// Returns the requested feature.
147
148 void setProperty(const std::string& name, const Poco::Any& value);
149 /// Sets property for all sessions.
150
151 Poco::Any getProperty(const std::string& name);
152 /// Returns the requested property.
153
154 void shutdown();
155 /// Shuts down the session pool.
156
157 bool isActive() const;
158 /// Returns true if session pool is active (not shut down).
159
160 protected:
161 virtual void customizeSession(Session& session);
162 /// Can be overridden by subclass to perform custom initialization
163 /// of a newly created database session.
164 ///
165 /// The default implementation does nothing.
166
167 typedef Poco::AutoPtr<PooledSessionHolder> PooledSessionHolderPtr;
168 typedef Poco::AutoPtr<PooledSessionImpl> PooledSessionImplPtr;
169 typedef std::list<PooledSessionHolderPtr> SessionList;
170 typedef Poco::HashMap<std::string, bool> FeatureMap;
171 typedef Poco::HashMap<std::string, Poco::Any> PropertyMap;
172
173 void purgeDeadSessions();
174 int deadImpl(SessionList& rSessions);
175 void applySettings(SessionImpl* pImpl);
176 void putBack(PooledSessionHolderPtr pHolder);
177 void onJanitorTimer(Poco::Timer&);
178
179 private:
180 typedef std::pair<std::string, Poco::Any> PropertyPair;
181 typedef std::pair<std::string, bool> FeaturePair;
182 typedef std::map<SessionImpl*, PropertyPair> AddPropertyMap;
183 typedef std::map<SessionImpl*, FeaturePair> AddFeatureMap;
184
185 SessionPool(const SessionPool&);
186 SessionPool& operator = (const SessionPool&);
187
188 void closeAll(SessionList& sessionList);
189
190 std::string _connector;
191 std::string _connectionString;
192 int _minSessions;
193 int _maxSessions;
194 int _idleTime;
195 int _nSessions;
196 SessionList _idleSessions;
197 SessionList _activeSessions;
198 Poco::Timer _janitorTimer;
199 FeatureMap _featureMap;
200 PropertyMap _propertyMap;
201 bool _shutdown;
202 AddPropertyMap _addPropertyMap;
203 AddFeatureMap _addFeatureMap;
204 mutable
205 Poco::Mutex _mutex;
206
207 friend class PooledSessionImpl;
208 };
209
210
name(const std::string & connector,const std::string & connectionString)211 inline std::string SessionPool::name(const std::string& connector,
212 const std::string& connectionString)
213 {
214 return Session::uri(connector, connectionString);
215 }
216
217
name()218 inline std::string SessionPool::name() const
219 {
220 return name(_connector, _connectionString);
221 }
222
223
isActive()224 inline bool SessionPool::isActive() const
225 {
226 return !_shutdown;
227 }
228
229
230 } } // namespace Poco::Data
231
232
233 #endif // Data_SessionPool_INCLUDED
234