@@ -31,9 +31,11 @@ using namespace std;
3131namespace isc {
3232namespace dhcp {
3333
34- boost::scoped_ptr<TrackingLeaseMgr>&
34+ map<string, LeaseMgrFactory::Factory> LeaseMgrFactory::map_;
35+
36+ TrackingLeaseMgrPtr&
3537LeaseMgrFactory::getLeaseMgrPtr () {
36- static boost::scoped_ptr<TrackingLeaseMgr> lease_mgr_ptr;
38+ static TrackingLeaseMgrPtr lease_mgr_ptr;
3739 return (lease_mgr_ptr);
3840}
3941
@@ -45,47 +47,70 @@ LeaseMgrFactory::create(const std::string& dbaccess) {
4547 DatabaseConnection::ParameterMap parameters = DatabaseConnection::parse (dbaccess);
4648 std::string redacted = DatabaseConnection::redactedAccessString (parameters);
4749
48- // Is "type" present?
49- if (parameters.find (type) == parameters.end ()) {
50+ // Get the database type and open the corresponding database
51+ DatabaseConnection::ParameterMap::iterator it = parameters.find (type);
52+ if (it == parameters.end ()) {
5053 LOG_ERROR (dhcpsrv_logger, DHCPSRV_NOTYPE_DB).arg (dbaccess);
5154 isc_throw (InvalidParameter, " Database configuration parameters do not "
5255 " contain the 'type' keyword" );
5356 }
5457
55- // Yes, check what it is.
56- if (parameters[type] == string (" mysql" )) {
58+ // Code will be moved to appropriate hook library.
5759#ifdef HAVE_MYSQL
58- LOG_INFO (dhcpsrv_logger, DHCPSRV_MYSQL_DB). arg (redacted);
59- getLeaseMgrPtr (). reset ( new MySqlLeaseMgr ( parameters));
60- return ;
61- # else
62- LOG_ERROR (dhcpsrv_logger, DHCPSRV_UNKNOWN_DB). arg ( " mysql " );
63- isc_throw (InvalidType, " The Kea server has not been compiled with "
64- " support for database type: mysql" );
60+ // Factory method
61+ auto mysql_factory = []( const DatabaseConnection::ParameterMap& parameters) -> TrackingLeaseMgrPtr {
62+ LOG_INFO (dhcpsrv_logger, DHCPSRV_MYSQL_DB)
63+ . arg ( DatabaseConnection::redactedAccessString (parameters));
64+ return ( TrackingLeaseMgrPtr ( new MySqlLeaseMgr (parameters)) );
65+ };
66+ LeaseMgrFactory::registerFactory ( " mysql" , mysql_factory, true );
6567#endif
66- }
6768
68- if (parameters[type] == string ( " postgresql " )) {
69+ // Code will be moved to appropriate hook library.
6970#ifdef HAVE_PGSQL
70- LOG_INFO (dhcpsrv_logger, DHCPSRV_PGSQL_DB). arg (redacted);
71- getLeaseMgrPtr (). reset ( new PgSqlLeaseMgr ( parameters));
72- return ;
73- # else
74- LOG_ERROR (dhcpsrv_logger, DHCPSRV_UNKNOWN_DB). arg ( " postgresql " );
75- isc_throw (InvalidType, " The Kea server has not been compiled with "
76- " support for database type: postgresql" );
71+ // Factory method
72+ auto pgsql_factory = []( const DatabaseConnection::ParameterMap& parameters) -> TrackingLeaseMgrPtr {
73+ LOG_INFO (dhcpsrv_logger, DHCPSRV_PGSQL_DB)
74+ . arg ( DatabaseConnection::redactedAccessString (parameters));
75+ return ( TrackingLeaseMgrPtr ( new PgSqlLeaseMgr (parameters)) );
76+ };
77+ LeaseMgrFactory::registerFactory ( " postgresql" , pgsql_factory, true );
7778#endif
78- }
79+
7980 if (parameters[type] == string (" memfile" )) {
8081 LOG_INFO (dhcpsrv_logger, DHCPSRV_MEMFILE_DB).arg (redacted);
8182 getLeaseMgrPtr ().reset (new Memfile_LeaseMgr (parameters));
8283 return ;
8384 }
8485
85- // Get here on no match
86- LOG_ERROR (dhcpsrv_logger, DHCPSRV_UNKNOWN_DB).arg (parameters[type]);
87- isc_throw (InvalidType, " Database access parameter 'type' does "
88- " not specify a supported database backend: " << parameters[type]);
86+ string db_type = it->second ;
87+ auto index = map_.find (db_type);
88+
89+ // No match?
90+ if (index == map_.end ()) {
91+ if ((db_type == " mysql" ) ||
92+ (db_type == " postgresql" )) {
93+ LOG_ERROR (dhcpsrv_logger, DHCPSRV_UNKNOWN_DB).arg (db_type);
94+ string with = (db_type == " postgresql" ? " pgsql" : db_type);
95+ isc_throw (InvalidType, " The Kea server has not been compiled with "
96+ " support for database type: " << db_type
97+ << " . Did you forget to use --with-"
98+ << with << " during compilation?" );
99+ }
100+ // Get here on no match
101+ LOG_ERROR (dhcpsrv_logger, DHCPSRV_UNKNOWN_DB).arg (parameters[type]);
102+ isc_throw (InvalidType, " Database access parameter 'type' does "
103+ " not specify a supported database backend: " << parameters[type]);
104+ }
105+
106+ // Call the factory.
107+ getLeaseMgrPtr () = index->second (parameters);
108+
109+ // Check the factory did not return NULL.
110+ if (!getLeaseMgrPtr ()) {
111+ isc_throw (Unexpected, " Lease database " << db_type <<
112+ " factory returned NULL" );
113+ }
89114}
90115
91116void
@@ -97,6 +122,14 @@ LeaseMgrFactory::destroy() {
97122 .arg (getLeaseMgrPtr ()->getType ());
98123 }
99124 getLeaseMgrPtr ().reset ();
125+ // Code will be moved to appropriate hook library.
126+ #ifdef HAVE_MYSQL
127+ LeaseMgrFactory::deregisterFactory (" mysql" , true );
128+ #endif
129+ // Code will be moved to appropriate hook library.
130+ #ifdef HAVE_PGSQL
131+ LeaseMgrFactory::deregisterFactory (" postgresql" , true );
132+ #endif
100133}
101134
102135void
@@ -132,5 +165,58 @@ LeaseMgrFactory::instance() {
132165 return (*lmptr);
133166}
134167
168+ bool
169+ LeaseMgrFactory::registerFactory (const string& db_type,
170+ const Factory& factory,
171+ bool no_log) {
172+ if (map_.count (db_type)) {
173+ return (false );
174+ }
175+ map_.insert (pair<string, Factory>(db_type, factory));
176+
177+ // We are dealing here with static logger initialization fiasco.
178+ // registerFactory may be called from constructors of static global
179+ // objects for built in backends. The logging is not initialized yet,
180+ // so the LOG_DEBUG would throw.
181+ if (!no_log) {
182+ LOG_DEBUG (dhcpsrv_logger, DHCPSRV_DBG_TRACE, DHCPSRV_LEASE_MGR_BACKEND_REGISTER)
183+ .arg (db_type);
184+ }
185+ return (true );
186+ }
187+
188+ bool
189+ LeaseMgrFactory::deregisterFactory (const string& db_type, bool no_log) {
190+ auto index = map_.find (db_type);
191+ if (index != map_.end ()) {
192+ map_.erase (index);
193+ if (!no_log) {
194+ LOG_DEBUG (dhcpsrv_logger, DHCPSRV_DBG_TRACE,
195+ DHCPSRV_LEASE_MGR_BACKEND_DEREGISTER)
196+ .arg (db_type);
197+ }
198+ return (true );
199+ } else {
200+ return (false );
201+ }
202+ }
203+
204+ bool
205+ LeaseMgrFactory::registeredFactory (const std::string& db_type) {
206+ auto index = map_.find (db_type);
207+ return (index != map_.end ());
208+ }
209+
210+ void
211+ LeaseMgrFactory::printRegistered () {
212+ std::stringstream txt;
213+
214+ for (auto const & x : map_) {
215+ txt << x.first << " " ;
216+ }
217+
218+ LOG_INFO (dhcpsrv_logger, DHCPSRV_LEASE_MGR_BACKENDS_REGISTERED).arg (txt.str ());
219+ }
220+
135221} // namespace dhcp
136222} // namespace isc
0 commit comments