1 ///////////////////////////////////////////////////////////////////////////////
\r
3 // File : $Id: service.cpp,v 1.1 2007/05/05 17:00:43 faust Exp $
\r
4 // Subject : IBPP, Service class implementation
\r
6 ///////////////////////////////////////////////////////////////////////////////
\r
8 // (C) Copyright 2000-2006 T.I.P. Group S.A. and the IBPP Team (www.ibpp.org)
\r
10 // The contents of this file are subject to the IBPP License (the "License");
\r
11 // you may not use this file except in compliance with the License. You may
\r
12 // obtain a copy of the License at http://www.ibpp.org or in the 'license.txt'
\r
13 // file which must have been distributed along with this file.
\r
15 // This software, distributed under the License, is distributed on an "AS IS"
\r
16 // basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
\r
17 // License for the specific language governing rights and limitations
\r
18 // under the License.
\r
20 ///////////////////////////////////////////////////////////////////////////////
\r
23 // * Tabulations should be set every four characters when editing this file.
\r
25 ///////////////////////////////////////////////////////////////////////////////
\r
28 #pragma warning(disable: 4786 4996)
\r
30 #pragma warning(disable: 4702)
\r
40 using namespace ibpp_internals;
\r
44 #define Sleep(x) usleep(x)
\r
47 // (((((((( OBJECT INTERFACE IMPLEMENTATION ))))))))
\r
49 void ServiceImpl::Connect()
\r
51 if (mHandle != 0) return; // Already connected
\r
53 if (gds.Call()->mGDSVersion < 60)
\r
54 throw LogicExceptionImpl("Service", _("Requires the version 6 of GDS32.DLL"));
\r
55 if (mUserName.empty())
\r
56 throw LogicExceptionImpl("Service::Connect", _("Unspecified user name."));
\r
57 if (mUserPassword.empty())
\r
58 throw LogicExceptionImpl("Service::Connect", _("Unspecified user password."));
\r
60 // Attach to the Service Manager
\r
63 std::string connect;
\r
65 // Build a SPB based on the properties
\r
66 spb.Insert(isc_spb_version);
\r
67 spb.Insert(isc_spb_current_version);
\r
68 spb.InsertString(isc_spb_user_name, 1, mUserName.c_str());
\r
69 spb.InsertString(isc_spb_password, 1, mUserPassword.c_str());
\r
71 if (! mServerName.empty())
\r
73 connect = mServerName;
\r
77 connect += "service_mgr";
\r
79 (*gds.Call()->m_service_attach)(status.Self(), (short)connect.size(), (char*)connect.c_str(),
\r
80 &mHandle, spb.Size(), spb.Self());
\r
81 if (status.Errors())
\r
83 mHandle = 0; // Should be, but better be sure...
\r
84 throw SQLExceptionImpl(status, "Service::Connect", _("isc_service_attach failed"));
\r
88 void ServiceImpl::Disconnect()
\r
90 if (mHandle == 0) return; // Already disconnected
\r
92 if (gds.Call()->mGDSVersion < 60)
\r
93 throw LogicExceptionImpl("Service", _("Requires the version 6 of GDS32.DLL"));
\r
97 // Detach from the service manager
\r
98 (*gds.Call()->m_service_detach)(status.Self(), &mHandle);
\r
100 // Set mHandle to 0 now, just in case we need to throw, because Disconnect()
\r
101 // is called from Service destructor and we want to maintain a coherent state.
\r
103 if (status.Errors())
\r
104 throw SQLExceptionImpl(status, "Service::Disconnect", _("isc_service_detach failed"));
\r
107 void ServiceImpl::GetVersion(std::string& version)
\r
109 // Based on a patch provided by Torsten Martinsen (SourceForge 'bullestock')
\r
111 if (gds.Call()->mGDSVersion < 60)
\r
112 throw LogicExceptionImpl("Service", _("Requires the version 6 of GDS32.DLL"));
\r
114 throw LogicExceptionImpl("Service::GetVersion", _("Service is not connected."));
\r
120 spb.Insert(isc_info_svc_server_version);
\r
122 (*gds.Call()->m_service_query)(status.Self(), &mHandle, 0, 0, 0, spb.Size(), spb.Self(),
\r
123 result.Size(), result.Self());
\r
124 if (status.Errors())
\r
125 throw SQLExceptionImpl(status, "Service::GetVersion", _("isc_service_query failed"));
\r
127 result.GetString(isc_info_svc_server_version, version);
\r
130 void ServiceImpl::AddUser(const IBPP::User& user)
\r
132 if (gds.Call()->mGDSVersion >= 60 && mHandle == 0)
\r
133 throw LogicExceptionImpl("Service::AddUser", _("Service is not connected."));
\r
134 if (user.username.empty())
\r
135 throw LogicExceptionImpl("Service::AddUser", _("Username required."));
\r
136 if (user.password.empty())
\r
137 throw LogicExceptionImpl("Service::AddUser", _("Password required."));
\r
141 spb.Insert(isc_action_svc_add_user);
\r
142 spb.InsertString(isc_spb_sec_username, 2, user.username.c_str());
\r
143 spb.InsertString(isc_spb_sec_password, 2, user.password.c_str());
\r
144 if (! user.firstname.empty())
\r
145 spb.InsertString(isc_spb_sec_firstname, 2, user.firstname.c_str());
\r
146 if (! user.middlename.empty())
\r
147 spb.InsertString(isc_spb_sec_middlename, 2, user.middlename.c_str());
\r
148 if (! user.lastname.empty())
\r
149 spb.InsertString(isc_spb_sec_lastname, 2, user.lastname.c_str());
\r
150 if (user.userid != 0)
\r
151 spb.InsertQuad(isc_spb_sec_userid, (int32_t)user.userid);
\r
152 if (user.groupid != 0)
\r
153 spb.InsertQuad(isc_spb_sec_groupid, (int32_t)user.groupid);
\r
155 (*gds.Call()->m_service_start)(status.Self(), &mHandle, 0, spb.Size(), spb.Self());
\r
156 if (status.Errors())
\r
157 throw SQLExceptionImpl(status, "Service::AddUser", _("isc_service_start failed"));
\r
162 void ServiceImpl::ModifyUser(const IBPP::User& user)
\r
164 if (gds.Call()->mGDSVersion >= 60 && mHandle == 0)
\r
165 throw LogicExceptionImpl("Service::ModifyUser", _("Service is not connected."));
\r
166 if (user.username.empty())
\r
167 throw LogicExceptionImpl("Service::ModifyUser", _("Username required."));
\r
172 spb.Insert(isc_action_svc_modify_user);
\r
173 spb.InsertString(isc_spb_sec_username, 2, user.username.c_str());
\r
174 if (! user.password.empty())
\r
175 spb.InsertString(isc_spb_sec_password, 2, user.password.c_str());
\r
176 if (! user.firstname.empty())
\r
177 spb.InsertString(isc_spb_sec_firstname, 2, user.firstname.c_str());
\r
178 if (! user.middlename.empty())
\r
179 spb.InsertString(isc_spb_sec_middlename, 2, user.middlename.c_str());
\r
180 if (! user.lastname.empty())
\r
181 spb.InsertString(isc_spb_sec_lastname, 2, user.lastname.c_str());
\r
182 if (user.userid != 0)
\r
183 spb.InsertQuad(isc_spb_sec_userid, (int32_t)user.userid);
\r
184 if (user.groupid != 0)
\r
185 spb.InsertQuad(isc_spb_sec_groupid, (int32_t)user.groupid);
\r
187 (*gds.Call()->m_service_start)(status.Self(), &mHandle, 0, spb.Size(), spb.Self());
\r
188 if (status.Errors())
\r
189 throw SQLExceptionImpl(status, "Service::ModifyUser", _("isc_service_start failed"));
\r
194 void ServiceImpl::RemoveUser(const std::string& username)
\r
197 if (gds.Call()->mGDSVersion >= 60 && mHandle == 0)
\r
198 throw LogicExceptionImpl("Service::RemoveUser", _("Service is not connected."));
\r
199 if (username.empty())
\r
200 throw LogicExceptionImpl("Service::RemoveUser", _("Username required."));
\r
205 spb.Insert(isc_action_svc_delete_user);
\r
206 spb.InsertString(isc_spb_sec_username, 2, username.c_str());
\r
208 (*gds.Call()->m_service_start)(status.Self(), &mHandle, 0, spb.Size(), spb.Self());
\r
209 if (status.Errors())
\r
210 throw SQLExceptionImpl(status, "Service::RemoveUser", _("isc_service_start failed"));
\r
215 void ServiceImpl::GetUser(IBPP::User& user)
\r
217 if (gds.Call()->mGDSVersion < 60)
\r
218 throw LogicExceptionImpl("Service", _("Requires the version 6 of GDS32.DLL"));
\r
220 throw LogicExceptionImpl("Service::GetUser", _("Service is not connected."));
\r
221 if (user.username.empty())
\r
222 throw LogicExceptionImpl("Service::GetUser", _("Username required."));
\r
225 spb.Insert(isc_action_svc_display_user);
\r
226 spb.InsertString(isc_spb_sec_username, 2, user.username.c_str());
\r
229 (*gds.Call()->m_service_start)(status.Self(), &mHandle, 0, spb.Size(), spb.Self());
\r
230 if (status.Errors())
\r
231 throw SQLExceptionImpl(status, "Service::GetUser", _("isc_service_start failed"));
\r
234 char request[] = {isc_info_svc_get_users};
\r
236 (*gds.Call()->m_service_query)(status.Self(), &mHandle, 0, 0, 0,
\r
237 sizeof(request), request, result.Size(), result.Self());
\r
238 if (status.Errors())
\r
239 throw SQLExceptionImpl(status, "Service::GetUser", _("isc_service_query failed"));
\r
241 char* p = result.Self();
\r
242 if (*p != isc_info_svc_get_users)
\r
243 throw SQLExceptionImpl(status, "Service::GetUser", _("isc_service_query returned unexpected answer"));
\r
245 p += 3; // Skips the 'isc_info_svc_get_users' and its total length
\r
247 while (*p != isc_info_end)
\r
249 if (*p == isc_spb_sec_userid)
\r
251 user.userid = (uint32_t)(*gds.Call()->m_vax_integer)(p+1, 4);
\r
254 else if (*p == isc_spb_sec_groupid)
\r
256 user.groupid = (uint32_t)(*gds.Call()->m_vax_integer)(p+1, 4);
\r
261 unsigned short len = (unsigned short)(*gds.Call()->m_vax_integer)(p+1, 2);
\r
264 case isc_spb_sec_username :
\r
265 // For each user, this is the first element returned
\r
266 if (len != 0) user.username.assign(p+3, len);
\r
268 case isc_spb_sec_password :
\r
269 if (len != 0) user.password.assign(p+3, len);
\r
271 case isc_spb_sec_firstname :
\r
272 if (len != 0) user.firstname.assign(p+3, len);
\r
274 case isc_spb_sec_middlename :
\r
275 if (len != 0) user.middlename.assign(p+3, len);
\r
277 case isc_spb_sec_lastname :
\r
278 if (len != 0) user.lastname.assign(p+3, len);
\r
286 void ServiceImpl::GetUsers(std::vector<IBPP::User>& users)
\r
288 if (gds.Call()->mGDSVersion < 60)
\r
289 throw LogicExceptionImpl("Service", _("Requires the version 6 of GDS32.DLL"));
\r
291 throw LogicExceptionImpl("Service::GetUsers", _("Service is not connected."));
\r
294 spb.Insert(isc_action_svc_display_user);
\r
297 (*gds.Call()->m_service_start)(status.Self(), &mHandle, 0, spb.Size(), spb.Self());
\r
298 if (status.Errors())
\r
299 throw SQLExceptionImpl(status, "Service::GetUsers", _("isc_service_start failed"));
\r
302 char request[] = {isc_info_svc_get_users};
\r
304 (*gds.Call()->m_service_query)(status.Self(), &mHandle, 0, 0, 0,
\r
305 sizeof(request), request, result.Size(), result.Self());
\r
306 if (status.Errors())
\r
307 throw SQLExceptionImpl(status, "Service::GetUsers", _("isc_service_query failed"));
\r
310 char* p = result.Self();
\r
311 if (*p != isc_info_svc_get_users)
\r
312 throw SQLExceptionImpl(status, "Service::GetUsers", _("isc_service_query returned unexpected answer"));
\r
314 p += 3; // Skips the 'isc_info_svc_get_users' and its total length
\r
316 while (*p != isc_info_end)
\r
318 if (*p == isc_spb_sec_userid)
\r
320 user.userid = (uint32_t)(*gds.Call()->m_vax_integer)(p+1, 4);
\r
323 else if (*p == isc_spb_sec_groupid)
\r
325 user.groupid = (uint32_t)(*gds.Call()->m_vax_integer)(p+1, 4);
\r
330 unsigned short len = (unsigned short)(*gds.Call()->m_vax_integer)(p+1, 2);
\r
333 case isc_spb_sec_username :
\r
334 // For each user, this is the first element returned
\r
335 if (! user.username.empty()) users.push_back(user); // Flush previous user
\r
337 if (len != 0) user.username.assign(p+3, len);
\r
339 case isc_spb_sec_password :
\r
340 if (len != 0) user.password.assign(p+3, len);
\r
342 case isc_spb_sec_firstname :
\r
343 if (len != 0) user.firstname.assign(p+3, len);
\r
345 case isc_spb_sec_middlename :
\r
346 if (len != 0) user.middlename.assign(p+3, len);
\r
348 case isc_spb_sec_lastname :
\r
349 if (len != 0) user.lastname.assign(p+3, len);
\r
355 if (! user.username.empty()) users.push_back(user); // Flush last user
\r
358 void ServiceImpl::SetPageBuffers(const std::string& dbfile, int buffers)
\r
360 if (gds.Call()->mGDSVersion < 60)
\r
361 throw LogicExceptionImpl("Service", _("Requires the version 6 of GDS32.DLL"));
\r
363 throw LogicExceptionImpl("Service::SetPageBuffers", _("Service is not connected."));
\r
364 if (dbfile.empty())
\r
365 throw LogicExceptionImpl("Service::SetPageBuffers", _("Main database file must be specified."));
\r
370 spb.Insert(isc_action_svc_properties);
\r
371 spb.InsertString(isc_spb_dbname, 2, dbfile.c_str());
\r
372 spb.InsertQuad(isc_spb_prp_page_buffers, buffers);
\r
374 (*gds.Call()->m_service_start)(status.Self(), &mHandle, 0, spb.Size(), spb.Self());
\r
375 if (status.Errors())
\r
376 throw SQLExceptionImpl(status, "Service::SetPageBuffers", _("isc_service_start failed"));
\r
381 void ServiceImpl::SetSweepInterval(const std::string& dbfile, int sweep)
\r
383 if (gds.Call()->mGDSVersion < 60)
\r
384 throw LogicExceptionImpl("Service", _("Requires the version 6 of GDS32.DLL"));
\r
386 throw LogicExceptionImpl("Service::SetSweepInterval", _("Service is not connected."));
\r
387 if (dbfile.empty())
\r
388 throw LogicExceptionImpl("Service::SetSweepInterval", _("Main database file must be specified."));
\r
393 spb.Insert(isc_action_svc_properties);
\r
394 spb.InsertString(isc_spb_dbname, 2, dbfile.c_str());
\r
395 spb.InsertQuad(isc_spb_prp_sweep_interval, sweep);
\r
397 (*gds.Call()->m_service_start)(status.Self(), &mHandle, 0, spb.Size(), spb.Self());
\r
398 if (status.Errors())
\r
399 throw SQLExceptionImpl(status, "Service::SetSweepInterval", _("isc_service_start failed"));
\r
404 void ServiceImpl::SetSyncWrite(const std::string& dbfile, bool sync)
\r
406 if (gds.Call()->mGDSVersion < 60)
\r
407 throw LogicExceptionImpl("Service", _("Requires the version 6 of GDS32.DLL"));
\r
409 throw LogicExceptionImpl("Service::SetSyncWrite", _("Service is not connected."));
\r
410 if (dbfile.empty())
\r
411 throw LogicExceptionImpl("Service::SetSyncWrite", _("Main database file must be specified."));
\r
416 spb.Insert(isc_action_svc_properties);
\r
417 spb.InsertString(isc_spb_dbname, 2, dbfile.c_str());
\r
418 if (sync) spb.InsertByte(isc_spb_prp_write_mode, (char)isc_spb_prp_wm_sync);
\r
419 else spb.InsertByte(isc_spb_prp_write_mode, (char)isc_spb_prp_wm_async);
\r
421 (*gds.Call()->m_service_start)(status.Self(), &mHandle, 0, spb.Size(), spb.Self());
\r
422 if (status.Errors())
\r
423 throw SQLExceptionImpl(status, "Service::SetSyncWrite", _("isc_service_start failed"));
\r
428 void ServiceImpl::SetReadOnly(const std::string& dbfile, bool readonly)
\r
430 if (gds.Call()->mGDSVersion < 60)
\r
431 throw LogicExceptionImpl("Service", _("Requires the version 6 of GDS32.DLL"));
\r
433 throw LogicExceptionImpl("Service::SetReadOnly", _("Service is not connected."));
\r
434 if (dbfile.empty())
\r
435 throw LogicExceptionImpl("Service::SetReadOnly", _("Main database file must be specified."));
\r
440 spb.Insert(isc_action_svc_properties);
\r
441 spb.InsertString(isc_spb_dbname, 2, dbfile.c_str());
\r
442 if (readonly) spb.InsertByte(isc_spb_prp_access_mode, (char)isc_spb_prp_am_readonly);
\r
443 else spb.InsertByte(isc_spb_prp_access_mode, (char)isc_spb_prp_am_readwrite);
\r
445 (*gds.Call()->m_service_start)(status.Self(), &mHandle, 0, spb.Size(), spb.Self());
\r
446 if (status.Errors())
\r
447 throw SQLExceptionImpl(status, "Service::SetReadOnly", _("isc_service_start failed"));
\r
452 void ServiceImpl::SetReserveSpace(const std::string& dbfile, bool reserve)
\r
454 if (gds.Call()->mGDSVersion < 60)
\r
455 throw LogicExceptionImpl("Service", _("Requires the version 6 of GDS32.DLL"));
\r
457 throw LogicExceptionImpl("Service::SetReserveSpace", _("Service is not connected."));
\r
458 if (dbfile.empty())
\r
459 throw LogicExceptionImpl("Service::SetReserveSpace", _("Main database file must be specified."));
\r
464 spb.Insert(isc_action_svc_properties);
\r
465 spb.InsertString(isc_spb_dbname, 2, dbfile.c_str());
\r
466 if (reserve) spb.InsertByte(isc_spb_prp_reserve_space, (char)isc_spb_prp_res);
\r
467 else spb.InsertByte(isc_spb_prp_reserve_space, (char)isc_spb_prp_res_use_full);
\r
469 (*gds.Call()->m_service_start)(status.Self(), &mHandle, 0, spb.Size(), spb.Self());
\r
470 if (status.Errors())
\r
471 throw SQLExceptionImpl(status, "Service::SetReserveSpace", _("isc_service_start failed"));
\r
476 void ServiceImpl::Shutdown(const std::string& dbfile, IBPP::DSM mode, int sectimeout)
\r
478 if (gds.Call()->mGDSVersion < 60)
\r
479 throw LogicExceptionImpl("Service", _("Requires the version 6 of GDS32.DLL"));
\r
481 throw LogicExceptionImpl("Service::Shutdown", _("Service is not connected."));
\r
482 if (dbfile.empty())
\r
483 throw LogicExceptionImpl("Service::Shutdown", _("Main database file must be specified."));
\r
488 spb.Insert(isc_action_svc_properties);
\r
489 spb.InsertString(isc_spb_dbname, 2, dbfile.c_str());
\r
492 case IBPP::dsDenyAttach :
\r
493 spb.InsertQuad(isc_spb_prp_deny_new_attachments, sectimeout);
\r
495 case IBPP::dsDenyTrans :
\r
496 spb.InsertQuad(isc_spb_prp_deny_new_transactions, sectimeout);
\r
498 case IBPP::dsForce :
\r
499 spb.InsertQuad(isc_spb_prp_shutdown_db, sectimeout);
\r
503 (*gds.Call()->m_service_start)(status.Self(), &mHandle, 0, spb.Size(), spb.Self());
\r
504 if (status.Errors())
\r
505 throw SQLExceptionImpl(status, "Service::Shutdown", _("isc_service_start failed"));
\r
510 void ServiceImpl::Restart(const std::string& dbfile)
\r
512 if (gds.Call()->mGDSVersion < 60)
\r
513 throw LogicExceptionImpl("Service", _("Requires the version 6 of GDS32.DLL"));
\r
515 throw LogicExceptionImpl("Service::Restart", _("Service is not connected."));
\r
516 if (dbfile.empty())
\r
517 throw LogicExceptionImpl("Service::Restart", _("Main database file must be specified."));
\r
522 spb.Insert(isc_action_svc_properties);
\r
523 spb.InsertString(isc_spb_dbname, 2, dbfile.c_str());
\r
524 spb.InsertQuad(isc_spb_options, isc_spb_prp_db_online);
\r
526 (*gds.Call()->m_service_start)(status.Self(), &mHandle, 0, spb.Size(), spb.Self());
\r
527 if (status.Errors())
\r
528 throw SQLExceptionImpl(status, "Service::Restart", _("isc_service_start failed"));
\r
533 void ServiceImpl::Sweep(const std::string& dbfile)
\r
535 if (gds.Call()->mGDSVersion < 60)
\r
536 throw LogicExceptionImpl("Service", _("Requires the version 6 of GDS32.DLL"));
\r
538 throw LogicExceptionImpl("Service::Sweep", _("Service is not connected."));
\r
539 if (dbfile.empty())
\r
540 throw LogicExceptionImpl("Service::Sweep", _("Main database file must be specified."));
\r
545 spb.Insert(isc_action_svc_repair);
\r
546 spb.InsertString(isc_spb_dbname, 2, dbfile.c_str());
\r
547 spb.InsertQuad(isc_spb_options, isc_spb_rpr_sweep_db);
\r
549 (*gds.Call()->m_service_start)(status.Self(), &mHandle, 0, spb.Size(), spb.Self());
\r
550 if (status.Errors())
\r
551 throw SQLExceptionImpl(status, "Service::Sweep", _("isc_service_start failed"));
\r
556 void ServiceImpl::Repair(const std::string& dbfile, IBPP::RPF flags)
\r
558 if (gds.Call()->mGDSVersion < 60)
\r
559 throw LogicExceptionImpl("Service", _("Requires the version 6 of GDS32.DLL"));
\r
561 throw LogicExceptionImpl("Service::Repair", _("Service is not connected."));
\r
562 if (dbfile.empty())
\r
563 throw LogicExceptionImpl("Service::Repair", _("Main database file must be specified."));
\r
568 spb.Insert(isc_action_svc_repair);
\r
569 spb.InsertString(isc_spb_dbname, 2, dbfile.c_str());
\r
572 if (flags & IBPP::rpValidateFull) mask = (isc_spb_rpr_full | isc_spb_rpr_validate_db);
\r
573 else if (flags & IBPP::rpValidatePages) mask = isc_spb_rpr_validate_db;
\r
574 else if (flags & IBPP::rpMendRecords) mask = isc_spb_rpr_mend_db;
\r
575 else throw LogicExceptionImpl("Service::Repair",
\r
576 _("One of rpMendRecords, rpValidatePages, rpValidateFull is required."));
\r
578 if (flags & IBPP::rpReadOnly) mask |= isc_spb_rpr_check_db;
\r
579 if (flags & IBPP::rpIgnoreChecksums) mask |= isc_spb_rpr_ignore_checksum;
\r
580 if (flags & IBPP::rpKillShadows) mask |= isc_spb_rpr_kill_shadows;
\r
582 spb.InsertQuad(isc_spb_options, mask);
\r
584 (*gds.Call()->m_service_start)(status.Self(), &mHandle, 0, spb.Size(), spb.Self());
\r
585 if (status.Errors())
\r
586 throw SQLExceptionImpl(status, "Service::Repair", _("isc_service_start failed"));
\r
591 void ServiceImpl::StartBackup(const std::string& dbfile,
\r
592 const std::string& bkfile, IBPP::BRF flags)
\r
594 if (gds.Call()->mGDSVersion < 60)
\r
595 throw LogicExceptionImpl("Service", _("Requires the version 6 of GDS32.DLL"));
\r
597 throw LogicExceptionImpl("Service::Backup", _("Service is not connected."));
\r
598 if (dbfile.empty())
\r
599 throw LogicExceptionImpl("Service::Backup", _("Main database file must be specified."));
\r
600 if (bkfile.empty())
\r
601 throw LogicExceptionImpl("Service::Backup", _("Backup file must be specified."));
\r
606 spb.Insert(isc_action_svc_backup);
\r
607 spb.InsertString(isc_spb_dbname, 2, dbfile.c_str());
\r
608 spb.InsertString(isc_spb_bkp_file, 2, bkfile.c_str());
\r
609 if (flags & IBPP::brVerbose) spb.Insert(isc_spb_verbose);
\r
611 unsigned int mask = 0;
\r
612 if (flags & IBPP::brIgnoreChecksums) mask |= isc_spb_bkp_ignore_checksums;
\r
613 if (flags & IBPP::brIgnoreLimbo) mask |= isc_spb_bkp_ignore_limbo;
\r
614 if (flags & IBPP::brMetadataOnly) mask |= isc_spb_bkp_metadata_only;
\r
615 if (flags & IBPP::brNoGarbageCollect) mask |= isc_spb_bkp_no_garbage_collect;
\r
616 if (flags & IBPP::brNonTransportable) mask |= isc_spb_bkp_non_transportable;
\r
617 if (flags & IBPP::brConvertExtTables) mask |= isc_spb_bkp_convert;
\r
618 if (mask != 0) spb.InsertQuad(isc_spb_options, mask);
\r
620 (*gds.Call()->m_service_start)(status.Self(), &mHandle, 0, spb.Size(), spb.Self());
\r
621 if (status.Errors())
\r
622 throw SQLExceptionImpl(status, "Service::Backup", _("isc_service_start failed"));
\r
625 void ServiceImpl::StartRestore(const std::string& bkfile, const std::string& dbfile,
\r
626 int pagesize, IBPP::BRF flags)
\r
628 if (gds.Call()->mGDSVersion < 60)
\r
629 throw LogicExceptionImpl("Service", _("Requires the version 6 of GDS32.DLL"));
\r
631 throw LogicExceptionImpl("Service::Restore", _("Service is not connected."));
\r
632 if (bkfile.empty())
\r
633 throw LogicExceptionImpl("Service::Restore", _("Backup file must be specified."));
\r
634 if (dbfile.empty())
\r
635 throw LogicExceptionImpl("Service::Restore", _("Main database file must be specified."));
\r
640 spb.Insert(isc_action_svc_restore);
\r
641 spb.InsertString(isc_spb_bkp_file, 2, bkfile.c_str());
\r
642 spb.InsertString(isc_spb_dbname, 2, dbfile.c_str());
\r
643 if (flags & IBPP::brVerbose) spb.Insert(isc_spb_verbose);
\r
644 if (pagesize != 0) spb.InsertQuad(isc_spb_res_page_size, pagesize);
\r
647 if (flags & IBPP::brReplace) mask = isc_spb_res_replace;
\r
648 else mask = isc_spb_res_create; // Safe default mode
\r
650 if (flags & IBPP::brDeactivateIdx) mask |= isc_spb_res_deactivate_idx;
\r
651 if (flags & IBPP::brNoShadow) mask |= isc_spb_res_no_shadow;
\r
652 if (flags & IBPP::brNoValidity) mask |= isc_spb_res_no_validity;
\r
653 if (flags & IBPP::brPerTableCommit) mask |= isc_spb_res_one_at_a_time;
\r
654 if (flags & IBPP::brUseAllSpace) mask |= isc_spb_res_use_all_space;
\r
655 if (mask != 0) spb.InsertQuad(isc_spb_options, mask);
\r
657 (*gds.Call()->m_service_start)(status.Self(), &mHandle, 0, spb.Size(), spb.Self());
\r
658 if (status.Errors())
\r
659 throw SQLExceptionImpl(status, "Service::Restore", _("isc_service_start failed"));
\r
662 const char* ServiceImpl::WaitMsg()
\r
668 if (gds.Call()->mGDSVersion < 60)
\r
669 throw LogicExceptionImpl("Service", _("Requires the version 6 of GDS32.DLL"));
\r
671 req.Insert(isc_info_svc_line); // Request one line of textual output
\r
673 // _service_query will only block until a line of result is available
\r
674 // (or until the end of the task if it does not report information)
\r
675 (*gds.Call()->m_service_query)(status.Self(), &mHandle, 0, 0, 0,
\r
676 req.Size(), req.Self(), result.Size(), result.Self());
\r
677 if (status.Errors())
\r
678 throw SQLExceptionImpl(status, "ServiceImpl::Wait", _("isc_service_query failed"));
\r
680 // If message length is zero bytes, task is finished
\r
681 if (result.GetString(isc_info_svc_line, mWaitMessage) == 0) return 0;
\r
683 // Task is not finished, but we have something to report
\r
684 return mWaitMessage.c_str();
\r
687 void ServiceImpl::Wait()
\r
694 if (gds.Call()->mGDSVersion < 60)
\r
695 throw LogicExceptionImpl("Service", _("Requires the version 6 of GDS32.DLL"));
\r
697 spb.Insert(isc_info_svc_line);
\r
700 // Sleeps 1 millisecond upfront. This will release the remaining
\r
701 // timeslot of the thread. Doing so will give a good chance for small
\r
702 // services tasks to finish before we check if they are still running.
\r
703 // The deal is to limit (in that particular case) the number of loops
\r
704 // polling _service_query that will happen.
\r
708 // _service_query will only block until a line of result is available
\r
709 // (or until the end of the task if it does not report information)
\r
710 (*gds.Call()->m_service_query)(status.Self(), &mHandle, 0, 0, 0,
\r
711 spb.Size(), spb.Self(), result.Size(), result.Self());
\r
712 if (status.Errors())
\r
713 throw SQLExceptionImpl(status, "ServiceImpl::Wait", _("isc_service_query failed"));
\r
715 // If message length is zero bytes, task is finished
\r
716 if (result.GetString(isc_info_svc_line, msg) == 0) return;
\r
723 IBPP::IService* ServiceImpl::AddRef()
\r
725 ASSERTION(mRefCount >= 0);
\r
730 void ServiceImpl::Release()
\r
732 // Release cannot throw, except in DEBUG builds on assertion
\r
733 ASSERTION(mRefCount >= 0);
\r
735 try { if (mRefCount <= 0) delete this; }
\r
739 // (((((((( OBJECT INTERNAL METHODS ))))))))
\r
741 void ServiceImpl::SetServerName(const char* newName)
\r
743 if (newName == 0) mServerName.erase();
\r
744 else mServerName = newName;
\r
747 void ServiceImpl::SetUserName(const char* newName)
\r
749 if (newName == 0) mUserName.erase();
\r
750 else mUserName = newName;
\r
753 void ServiceImpl::SetUserPassword(const char* newPassword)
\r
755 if (newPassword == 0) mUserPassword.erase();
\r
756 else mUserPassword = newPassword;
\r
759 ServiceImpl::ServiceImpl(const std::string& ServerName,
\r
760 const std::string& UserName, const std::string& UserPassword)
\r
761 : mRefCount(0), mHandle(0),
\r
762 mServerName(ServerName), mUserName(UserName), mUserPassword(UserPassword)
\r
766 ServiceImpl::~ServiceImpl()
\r
768 try { if (Connected()) Disconnect(); }
\r