00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027 #if defined(_MSC_VER)
00028 #pragma warning(disable: 4786 4996)
00029 #ifndef _DEBUG
00030 #pragma warning(disable: 4702)
00031 #endif
00032 #endif
00033
00034 #include "_ibpp.h"
00035
00036 #ifdef HAS_HDRSTOP
00037 #pragma hdrstop
00038 #endif
00039
00040 using namespace ibpp_internals;
00041
00042 #ifdef IBPP_UNIX
00043 #include <unistd.h>
00044 #define Sleep(x) usleep(x)
00045 #endif
00046
00047
00048
00049 void ServiceImpl::Connect()
00050 {
00051 if (mHandle != 0) return;
00052
00053 if (gds.Call()->mGDSVersion < 60)
00054 throw LogicExceptionImpl("Service", _("Requires the version 6 of GDS32.DLL"));
00055 if (mUserName.empty())
00056 throw LogicExceptionImpl("Service::Connect", _("Unspecified user name."));
00057 if (mUserPassword.empty())
00058 throw LogicExceptionImpl("Service::Connect", _("Unspecified user password."));
00059
00060
00061 IBS status;
00062 SPB spb;
00063 std::string connect;
00064
00065
00066 spb.Insert(isc_spb_version);
00067 spb.Insert(isc_spb_current_version);
00068 spb.InsertString(isc_spb_user_name, 1, mUserName.c_str());
00069 spb.InsertString(isc_spb_password, 1, mUserPassword.c_str());
00070
00071 if (! mServerName.empty())
00072 {
00073 connect = mServerName;
00074 connect += ":";
00075 }
00076
00077 connect += "service_mgr";
00078
00079 (*gds.Call()->m_service_attach)(status.Self(), (short)connect.size(), (char*)connect.c_str(),
00080 &mHandle, spb.Size(), spb.Self());
00081 if (status.Errors())
00082 {
00083 mHandle = 0;
00084 throw SQLExceptionImpl(status, "Service::Connect", _("isc_service_attach failed"));
00085 }
00086 }
00087
00088 void ServiceImpl::Disconnect()
00089 {
00090 if (mHandle == 0) return;
00091
00092 if (gds.Call()->mGDSVersion < 60)
00093 throw LogicExceptionImpl("Service", _("Requires the version 6 of GDS32.DLL"));
00094
00095 IBS status;
00096
00097
00098 (*gds.Call()->m_service_detach)(status.Self(), &mHandle);
00099
00100
00101
00102 mHandle = 0;
00103 if (status.Errors())
00104 throw SQLExceptionImpl(status, "Service::Disconnect", _("isc_service_detach failed"));
00105 }
00106
00107 void ServiceImpl::GetVersion(std::string& version)
00108 {
00109
00110
00111 if (gds.Call()->mGDSVersion < 60)
00112 throw LogicExceptionImpl("Service", _("Requires the version 6 of GDS32.DLL"));
00113 if (mHandle == 0)
00114 throw LogicExceptionImpl("Service::GetVersion", _("Service is not connected."));
00115
00116 IBS status;
00117 SPB spb;
00118 RB result(250);
00119
00120 spb.Insert(isc_info_svc_server_version);
00121
00122 (*gds.Call()->m_service_query)(status.Self(), &mHandle, 0, 0, 0, spb.Size(), spb.Self(),
00123 result.Size(), result.Self());
00124 if (status.Errors())
00125 throw SQLExceptionImpl(status, "Service::GetVersion", _("isc_service_query failed"));
00126
00127 result.GetString(isc_info_svc_server_version, version);
00128 }
00129
00130 void ServiceImpl::AddUser(const IBPP::User& user)
00131 {
00132 if (gds.Call()->mGDSVersion >= 60 && mHandle == 0)
00133 throw LogicExceptionImpl("Service::AddUser", _("Service is not connected."));
00134 if (user.username.empty())
00135 throw LogicExceptionImpl("Service::AddUser", _("Username required."));
00136 if (user.password.empty())
00137 throw LogicExceptionImpl("Service::AddUser", _("Password required."));
00138
00139 IBS status;
00140 SPB spb;
00141 spb.Insert(isc_action_svc_add_user);
00142 spb.InsertString(isc_spb_sec_username, 2, user.username.c_str());
00143 spb.InsertString(isc_spb_sec_password, 2, user.password.c_str());
00144 if (! user.firstname.empty())
00145 spb.InsertString(isc_spb_sec_firstname, 2, user.firstname.c_str());
00146 if (! user.middlename.empty())
00147 spb.InsertString(isc_spb_sec_middlename, 2, user.middlename.c_str());
00148 if (! user.lastname.empty())
00149 spb.InsertString(isc_spb_sec_lastname, 2, user.lastname.c_str());
00150 if (user.userid != 0)
00151 spb.InsertQuad(isc_spb_sec_userid, (int32_t)user.userid);
00152 if (user.groupid != 0)
00153 spb.InsertQuad(isc_spb_sec_groupid, (int32_t)user.groupid);
00154
00155 (*gds.Call()->m_service_start)(status.Self(), &mHandle, 0, spb.Size(), spb.Self());
00156 if (status.Errors())
00157 throw SQLExceptionImpl(status, "Service::AddUser", _("isc_service_start failed"));
00158
00159 Wait();
00160 }
00161
00162 void ServiceImpl::ModifyUser(const IBPP::User& user)
00163 {
00164 if (gds.Call()->mGDSVersion >= 60 && mHandle == 0)
00165 throw LogicExceptionImpl("Service::ModifyUser", _("Service is not connected."));
00166 if (user.username.empty())
00167 throw LogicExceptionImpl("Service::ModifyUser", _("Username required."));
00168
00169 IBS status;
00170 SPB spb;
00171
00172 spb.Insert(isc_action_svc_modify_user);
00173 spb.InsertString(isc_spb_sec_username, 2, user.username.c_str());
00174 if (! user.password.empty())
00175 spb.InsertString(isc_spb_sec_password, 2, user.password.c_str());
00176 if (! user.firstname.empty())
00177 spb.InsertString(isc_spb_sec_firstname, 2, user.firstname.c_str());
00178 if (! user.middlename.empty())
00179 spb.InsertString(isc_spb_sec_middlename, 2, user.middlename.c_str());
00180 if (! user.lastname.empty())
00181 spb.InsertString(isc_spb_sec_lastname, 2, user.lastname.c_str());
00182 if (user.userid != 0)
00183 spb.InsertQuad(isc_spb_sec_userid, (int32_t)user.userid);
00184 if (user.groupid != 0)
00185 spb.InsertQuad(isc_spb_sec_groupid, (int32_t)user.groupid);
00186
00187 (*gds.Call()->m_service_start)(status.Self(), &mHandle, 0, spb.Size(), spb.Self());
00188 if (status.Errors())
00189 throw SQLExceptionImpl(status, "Service::ModifyUser", _("isc_service_start failed"));
00190
00191 Wait();
00192 }
00193
00194 void ServiceImpl::RemoveUser(const std::string& username)
00195 {
00196
00197 if (gds.Call()->mGDSVersion >= 60 && mHandle == 0)
00198 throw LogicExceptionImpl("Service::RemoveUser", _("Service is not connected."));
00199 if (username.empty())
00200 throw LogicExceptionImpl("Service::RemoveUser", _("Username required."));
00201
00202 IBS status;
00203 SPB spb;
00204
00205 spb.Insert(isc_action_svc_delete_user);
00206 spb.InsertString(isc_spb_sec_username, 2, username.c_str());
00207
00208 (*gds.Call()->m_service_start)(status.Self(), &mHandle, 0, spb.Size(), spb.Self());
00209 if (status.Errors())
00210 throw SQLExceptionImpl(status, "Service::RemoveUser", _("isc_service_start failed"));
00211
00212 Wait();
00213 }
00214
00215 void ServiceImpl::GetUser(IBPP::User& user)
00216 {
00217 if (gds.Call()->mGDSVersion < 60)
00218 throw LogicExceptionImpl("Service", _("Requires the version 6 of GDS32.DLL"));
00219 if (mHandle == 0)
00220 throw LogicExceptionImpl("Service::GetUser", _("Service is not connected."));
00221 if (user.username.empty())
00222 throw LogicExceptionImpl("Service::GetUser", _("Username required."));
00223
00224 SPB spb;
00225 spb.Insert(isc_action_svc_display_user);
00226 spb.InsertString(isc_spb_sec_username, 2, user.username.c_str());
00227
00228 IBS status;
00229 (*gds.Call()->m_service_start)(status.Self(), &mHandle, 0, spb.Size(), spb.Self());
00230 if (status.Errors())
00231 throw SQLExceptionImpl(status, "Service::GetUser", _("isc_service_start failed"));
00232
00233 RB result(8000);
00234 char request[] = {isc_info_svc_get_users};
00235 status.Reset();
00236 (*gds.Call()->m_service_query)(status.Self(), &mHandle, 0, 0, 0,
00237 sizeof(request), request, result.Size(), result.Self());
00238 if (status.Errors())
00239 throw SQLExceptionImpl(status, "Service::GetUser", _("isc_service_query failed"));
00240
00241 char* p = result.Self();
00242 if (*p != isc_info_svc_get_users)
00243 throw SQLExceptionImpl(status, "Service::GetUser", _("isc_service_query returned unexpected answer"));
00244
00245 p += 3;
00246 user.clear();
00247 while (*p != isc_info_end)
00248 {
00249 if (*p == isc_spb_sec_userid)
00250 {
00251 user.userid = (uint32_t)(*gds.Call()->m_vax_integer)(p+1, 4);
00252 p += 5;
00253 }
00254 else if (*p == isc_spb_sec_groupid)
00255 {
00256 user.groupid = (uint32_t)(*gds.Call()->m_vax_integer)(p+1, 4);
00257 p += 5;
00258 }
00259 else
00260 {
00261 unsigned short len = (unsigned short)(*gds.Call()->m_vax_integer)(p+1, 2);
00262 switch (*p)
00263 {
00264 case isc_spb_sec_username :
00265
00266 if (len != 0) user.username.assign(p+3, len);
00267 break;
00268 case isc_spb_sec_password :
00269 if (len != 0) user.password.assign(p+3, len);
00270 break;
00271 case isc_spb_sec_firstname :
00272 if (len != 0) user.firstname.assign(p+3, len);
00273 break;
00274 case isc_spb_sec_middlename :
00275 if (len != 0) user.middlename.assign(p+3, len);
00276 break;
00277 case isc_spb_sec_lastname :
00278 if (len != 0) user.lastname.assign(p+3, len);
00279 break;
00280 }
00281 p += (3 + len);
00282 }
00283 }
00284 }
00285
00286 void ServiceImpl::GetUsers(std::vector<IBPP::User>& users)
00287 {
00288 if (gds.Call()->mGDSVersion < 60)
00289 throw LogicExceptionImpl("Service", _("Requires the version 6 of GDS32.DLL"));
00290 if (mHandle == 0)
00291 throw LogicExceptionImpl("Service::GetUsers", _("Service is not connected."));
00292
00293 SPB spb;
00294 spb.Insert(isc_action_svc_display_user);
00295
00296 IBS status;
00297 (*gds.Call()->m_service_start)(status.Self(), &mHandle, 0, spb.Size(), spb.Self());
00298 if (status.Errors())
00299 throw SQLExceptionImpl(status, "Service::GetUsers", _("isc_service_start failed"));
00300
00301 RB result(8000);
00302 char request[] = {isc_info_svc_get_users};
00303 status.Reset();
00304 (*gds.Call()->m_service_query)(status.Self(), &mHandle, 0, 0, 0,
00305 sizeof(request), request, result.Size(), result.Self());
00306 if (status.Errors())
00307 throw SQLExceptionImpl(status, "Service::GetUsers", _("isc_service_query failed"));
00308
00309 users.clear();
00310 char* p = result.Self();
00311 if (*p != isc_info_svc_get_users)
00312 throw SQLExceptionImpl(status, "Service::GetUsers", _("isc_service_query returned unexpected answer"));
00313
00314 p += 3;
00315 IBPP::User user;
00316 while (*p != isc_info_end)
00317 {
00318 if (*p == isc_spb_sec_userid)
00319 {
00320 user.userid = (uint32_t)(*gds.Call()->m_vax_integer)(p+1, 4);
00321 p += 5;
00322 }
00323 else if (*p == isc_spb_sec_groupid)
00324 {
00325 user.groupid = (uint32_t)(*gds.Call()->m_vax_integer)(p+1, 4);
00326 p += 5;
00327 }
00328 else
00329 {
00330 unsigned short len = (unsigned short)(*gds.Call()->m_vax_integer)(p+1, 2);
00331 switch (*p)
00332 {
00333 case isc_spb_sec_username :
00334
00335 if (! user.username.empty()) users.push_back(user);
00336 user.clear();
00337 if (len != 0) user.username.assign(p+3, len);
00338 break;
00339 case isc_spb_sec_password :
00340 if (len != 0) user.password.assign(p+3, len);
00341 break;
00342 case isc_spb_sec_firstname :
00343 if (len != 0) user.firstname.assign(p+3, len);
00344 break;
00345 case isc_spb_sec_middlename :
00346 if (len != 0) user.middlename.assign(p+3, len);
00347 break;
00348 case isc_spb_sec_lastname :
00349 if (len != 0) user.lastname.assign(p+3, len);
00350 break;
00351 }
00352 p += (3 + len);
00353 }
00354 }
00355 if (! user.username.empty()) users.push_back(user);
00356 }
00357
00358 void ServiceImpl::SetPageBuffers(const std::string& dbfile, int buffers)
00359 {
00360 if (gds.Call()->mGDSVersion < 60)
00361 throw LogicExceptionImpl("Service", _("Requires the version 6 of GDS32.DLL"));
00362 if (mHandle == 0)
00363 throw LogicExceptionImpl("Service::SetPageBuffers", _("Service is not connected."));
00364 if (dbfile.empty())
00365 throw LogicExceptionImpl("Service::SetPageBuffers", _("Main database file must be specified."));
00366
00367 IBS status;
00368 SPB spb;
00369
00370 spb.Insert(isc_action_svc_properties);
00371 spb.InsertString(isc_spb_dbname, 2, dbfile.c_str());
00372 spb.InsertQuad(isc_spb_prp_page_buffers, buffers);
00373
00374 (*gds.Call()->m_service_start)(status.Self(), &mHandle, 0, spb.Size(), spb.Self());
00375 if (status.Errors())
00376 throw SQLExceptionImpl(status, "Service::SetPageBuffers", _("isc_service_start failed"));
00377
00378 Wait();
00379 }
00380
00381 void ServiceImpl::SetSweepInterval(const std::string& dbfile, int sweep)
00382 {
00383 if (gds.Call()->mGDSVersion < 60)
00384 throw LogicExceptionImpl("Service", _("Requires the version 6 of GDS32.DLL"));
00385 if (mHandle == 0)
00386 throw LogicExceptionImpl("Service::SetSweepInterval", _("Service is not connected."));
00387 if (dbfile.empty())
00388 throw LogicExceptionImpl("Service::SetSweepInterval", _("Main database file must be specified."));
00389
00390 IBS status;
00391 SPB spb;
00392
00393 spb.Insert(isc_action_svc_properties);
00394 spb.InsertString(isc_spb_dbname, 2, dbfile.c_str());
00395 spb.InsertQuad(isc_spb_prp_sweep_interval, sweep);
00396
00397 (*gds.Call()->m_service_start)(status.Self(), &mHandle, 0, spb.Size(), spb.Self());
00398 if (status.Errors())
00399 throw SQLExceptionImpl(status, "Service::SetSweepInterval", _("isc_service_start failed"));
00400
00401 Wait();
00402 }
00403
00404 void ServiceImpl::SetSyncWrite(const std::string& dbfile, bool sync)
00405 {
00406 if (gds.Call()->mGDSVersion < 60)
00407 throw LogicExceptionImpl("Service", _("Requires the version 6 of GDS32.DLL"));
00408 if (mHandle == 0)
00409 throw LogicExceptionImpl("Service::SetSyncWrite", _("Service is not connected."));
00410 if (dbfile.empty())
00411 throw LogicExceptionImpl("Service::SetSyncWrite", _("Main database file must be specified."));
00412
00413 IBS status;
00414 SPB spb;
00415
00416 spb.Insert(isc_action_svc_properties);
00417 spb.InsertString(isc_spb_dbname, 2, dbfile.c_str());
00418 if (sync) spb.InsertByte(isc_spb_prp_write_mode, (char)isc_spb_prp_wm_sync);
00419 else spb.InsertByte(isc_spb_prp_write_mode, (char)isc_spb_prp_wm_async);
00420
00421 (*gds.Call()->m_service_start)(status.Self(), &mHandle, 0, spb.Size(), spb.Self());
00422 if (status.Errors())
00423 throw SQLExceptionImpl(status, "Service::SetSyncWrite", _("isc_service_start failed"));
00424
00425 Wait();
00426 }
00427
00428 void ServiceImpl::SetReadOnly(const std::string& dbfile, bool readonly)
00429 {
00430 if (gds.Call()->mGDSVersion < 60)
00431 throw LogicExceptionImpl("Service", _("Requires the version 6 of GDS32.DLL"));
00432 if (mHandle == 0)
00433 throw LogicExceptionImpl("Service::SetReadOnly", _("Service is not connected."));
00434 if (dbfile.empty())
00435 throw LogicExceptionImpl("Service::SetReadOnly", _("Main database file must be specified."));
00436
00437 IBS status;
00438 SPB spb;
00439
00440 spb.Insert(isc_action_svc_properties);
00441 spb.InsertString(isc_spb_dbname, 2, dbfile.c_str());
00442 if (readonly) spb.InsertByte(isc_spb_prp_access_mode, (char)isc_spb_prp_am_readonly);
00443 else spb.InsertByte(isc_spb_prp_access_mode, (char)isc_spb_prp_am_readwrite);
00444
00445 (*gds.Call()->m_service_start)(status.Self(), &mHandle, 0, spb.Size(), spb.Self());
00446 if (status.Errors())
00447 throw SQLExceptionImpl(status, "Service::SetReadOnly", _("isc_service_start failed"));
00448
00449 Wait();
00450 }
00451
00452 void ServiceImpl::SetReserveSpace(const std::string& dbfile, bool reserve)
00453 {
00454 if (gds.Call()->mGDSVersion < 60)
00455 throw LogicExceptionImpl("Service", _("Requires the version 6 of GDS32.DLL"));
00456 if (mHandle == 0)
00457 throw LogicExceptionImpl("Service::SetReserveSpace", _("Service is not connected."));
00458 if (dbfile.empty())
00459 throw LogicExceptionImpl("Service::SetReserveSpace", _("Main database file must be specified."));
00460
00461 IBS status;
00462 SPB spb;
00463
00464 spb.Insert(isc_action_svc_properties);
00465 spb.InsertString(isc_spb_dbname, 2, dbfile.c_str());
00466 if (reserve) spb.InsertByte(isc_spb_prp_reserve_space, (char)isc_spb_prp_res);
00467 else spb.InsertByte(isc_spb_prp_reserve_space, (char)isc_spb_prp_res_use_full);
00468
00469 (*gds.Call()->m_service_start)(status.Self(), &mHandle, 0, spb.Size(), spb.Self());
00470 if (status.Errors())
00471 throw SQLExceptionImpl(status, "Service::SetReserveSpace", _("isc_service_start failed"));
00472
00473 Wait();
00474 }
00475
00476 void ServiceImpl::Shutdown(const std::string& dbfile, IBPP::DSM mode, int sectimeout)
00477 {
00478 if (gds.Call()->mGDSVersion < 60)
00479 throw LogicExceptionImpl("Service", _("Requires the version 6 of GDS32.DLL"));
00480 if (mHandle == 0)
00481 throw LogicExceptionImpl("Service::Shutdown", _("Service is not connected."));
00482 if (dbfile.empty())
00483 throw LogicExceptionImpl("Service::Shutdown", _("Main database file must be specified."));
00484
00485 IBS status;
00486 SPB spb;
00487
00488 spb.Insert(isc_action_svc_properties);
00489 spb.InsertString(isc_spb_dbname, 2, dbfile.c_str());
00490 switch (mode)
00491 {
00492 case IBPP::dsDenyAttach :
00493 spb.InsertQuad(isc_spb_prp_deny_new_attachments, sectimeout);
00494 break;
00495 case IBPP::dsDenyTrans :
00496 spb.InsertQuad(isc_spb_prp_deny_new_transactions, sectimeout);
00497 break;
00498 case IBPP::dsForce :
00499 spb.InsertQuad(isc_spb_prp_shutdown_db, sectimeout);
00500 break;
00501 }
00502
00503 (*gds.Call()->m_service_start)(status.Self(), &mHandle, 0, spb.Size(), spb.Self());
00504 if (status.Errors())
00505 throw SQLExceptionImpl(status, "Service::Shutdown", _("isc_service_start failed"));
00506
00507 Wait();
00508 }
00509
00510 void ServiceImpl::Restart(const std::string& dbfile)
00511 {
00512 if (gds.Call()->mGDSVersion < 60)
00513 throw LogicExceptionImpl("Service", _("Requires the version 6 of GDS32.DLL"));
00514 if (mHandle == 0)
00515 throw LogicExceptionImpl("Service::Restart", _("Service is not connected."));
00516 if (dbfile.empty())
00517 throw LogicExceptionImpl("Service::Restart", _("Main database file must be specified."));
00518
00519 IBS status;
00520 SPB spb;
00521
00522 spb.Insert(isc_action_svc_properties);
00523 spb.InsertString(isc_spb_dbname, 2, dbfile.c_str());
00524 spb.InsertQuad(isc_spb_options, isc_spb_prp_db_online);
00525
00526 (*gds.Call()->m_service_start)(status.Self(), &mHandle, 0, spb.Size(), spb.Self());
00527 if (status.Errors())
00528 throw SQLExceptionImpl(status, "Service::Restart", _("isc_service_start failed"));
00529
00530 Wait();
00531 }
00532
00533 void ServiceImpl::Sweep(const std::string& dbfile)
00534 {
00535 if (gds.Call()->mGDSVersion < 60)
00536 throw LogicExceptionImpl("Service", _("Requires the version 6 of GDS32.DLL"));
00537 if (mHandle == 0)
00538 throw LogicExceptionImpl("Service::Sweep", _("Service is not connected."));
00539 if (dbfile.empty())
00540 throw LogicExceptionImpl("Service::Sweep", _("Main database file must be specified."));
00541
00542 IBS status;
00543 SPB spb;
00544
00545 spb.Insert(isc_action_svc_repair);
00546 spb.InsertString(isc_spb_dbname, 2, dbfile.c_str());
00547 spb.InsertQuad(isc_spb_options, isc_spb_rpr_sweep_db);
00548
00549 (*gds.Call()->m_service_start)(status.Self(), &mHandle, 0, spb.Size(), spb.Self());
00550 if (status.Errors())
00551 throw SQLExceptionImpl(status, "Service::Sweep", _("isc_service_start failed"));
00552
00553 Wait();
00554 }
00555
00556 void ServiceImpl::Repair(const std::string& dbfile, IBPP::RPF flags)
00557 {
00558 if (gds.Call()->mGDSVersion < 60)
00559 throw LogicExceptionImpl("Service", _("Requires the version 6 of GDS32.DLL"));
00560 if (mHandle == 0)
00561 throw LogicExceptionImpl("Service::Repair", _("Service is not connected."));
00562 if (dbfile.empty())
00563 throw LogicExceptionImpl("Service::Repair", _("Main database file must be specified."));
00564
00565 IBS status;
00566 SPB spb;
00567
00568 spb.Insert(isc_action_svc_repair);
00569 spb.InsertString(isc_spb_dbname, 2, dbfile.c_str());
00570
00571 unsigned int mask;
00572 if (flags & IBPP::rpValidateFull) mask = (isc_spb_rpr_full | isc_spb_rpr_validate_db);
00573 else if (flags & IBPP::rpValidatePages) mask = isc_spb_rpr_validate_db;
00574 else if (flags & IBPP::rpMendRecords) mask = isc_spb_rpr_mend_db;
00575 else throw LogicExceptionImpl("Service::Repair",
00576 _("One of rpMendRecords, rpValidatePages, rpValidateFull is required."));
00577
00578 if (flags & IBPP::rpReadOnly) mask |= isc_spb_rpr_check_db;
00579 if (flags & IBPP::rpIgnoreChecksums) mask |= isc_spb_rpr_ignore_checksum;
00580 if (flags & IBPP::rpKillShadows) mask |= isc_spb_rpr_kill_shadows;
00581
00582 spb.InsertQuad(isc_spb_options, mask);
00583
00584 (*gds.Call()->m_service_start)(status.Self(), &mHandle, 0, spb.Size(), spb.Self());
00585 if (status.Errors())
00586 throw SQLExceptionImpl(status, "Service::Repair", _("isc_service_start failed"));
00587
00588 Wait();
00589 }
00590
00591 void ServiceImpl::StartBackup(const std::string& dbfile,
00592 const std::string& bkfile, IBPP::BRF flags)
00593 {
00594 if (gds.Call()->mGDSVersion < 60)
00595 throw LogicExceptionImpl("Service", _("Requires the version 6 of GDS32.DLL"));
00596 if (mHandle == 0)
00597 throw LogicExceptionImpl("Service::Backup", _("Service is not connected."));
00598 if (dbfile.empty())
00599 throw LogicExceptionImpl("Service::Backup", _("Main database file must be specified."));
00600 if (bkfile.empty())
00601 throw LogicExceptionImpl("Service::Backup", _("Backup file must be specified."));
00602
00603 IBS status;
00604 SPB spb;
00605
00606 spb.Insert(isc_action_svc_backup);
00607 spb.InsertString(isc_spb_dbname, 2, dbfile.c_str());
00608 spb.InsertString(isc_spb_bkp_file, 2, bkfile.c_str());
00609 if (flags & IBPP::brVerbose) spb.Insert(isc_spb_verbose);
00610
00611 unsigned int mask = 0;
00612 if (flags & IBPP::brIgnoreChecksums) mask |= isc_spb_bkp_ignore_checksums;
00613 if (flags & IBPP::brIgnoreLimbo) mask |= isc_spb_bkp_ignore_limbo;
00614 if (flags & IBPP::brMetadataOnly) mask |= isc_spb_bkp_metadata_only;
00615 if (flags & IBPP::brNoGarbageCollect) mask |= isc_spb_bkp_no_garbage_collect;
00616 if (flags & IBPP::brNonTransportable) mask |= isc_spb_bkp_non_transportable;
00617 if (flags & IBPP::brConvertExtTables) mask |= isc_spb_bkp_convert;
00618 if (mask != 0) spb.InsertQuad(isc_spb_options, mask);
00619
00620 (*gds.Call()->m_service_start)(status.Self(), &mHandle, 0, spb.Size(), spb.Self());
00621 if (status.Errors())
00622 throw SQLExceptionImpl(status, "Service::Backup", _("isc_service_start failed"));
00623 }
00624
00625 void ServiceImpl::StartRestore(const std::string& bkfile, const std::string& dbfile,
00626 int pagesize, IBPP::BRF flags)
00627 {
00628 if (gds.Call()->mGDSVersion < 60)
00629 throw LogicExceptionImpl("Service", _("Requires the version 6 of GDS32.DLL"));
00630 if (mHandle == 0)
00631 throw LogicExceptionImpl("Service::Restore", _("Service is not connected."));
00632 if (bkfile.empty())
00633 throw LogicExceptionImpl("Service::Restore", _("Backup file must be specified."));
00634 if (dbfile.empty())
00635 throw LogicExceptionImpl("Service::Restore", _("Main database file must be specified."));
00636
00637 IBS status;
00638 SPB spb;
00639
00640 spb.Insert(isc_action_svc_restore);
00641 spb.InsertString(isc_spb_bkp_file, 2, bkfile.c_str());
00642 spb.InsertString(isc_spb_dbname, 2, dbfile.c_str());
00643 if (flags & IBPP::brVerbose) spb.Insert(isc_spb_verbose);
00644 if (pagesize != 0) spb.InsertQuad(isc_spb_res_page_size, pagesize);
00645
00646 unsigned int mask;
00647 if (flags & IBPP::brReplace) mask = isc_spb_res_replace;
00648 else mask = isc_spb_res_create;
00649
00650 if (flags & IBPP::brDeactivateIdx) mask |= isc_spb_res_deactivate_idx;
00651 if (flags & IBPP::brNoShadow) mask |= isc_spb_res_no_shadow;
00652 if (flags & IBPP::brNoValidity) mask |= isc_spb_res_no_validity;
00653 if (flags & IBPP::brPerTableCommit) mask |= isc_spb_res_one_at_a_time;
00654 if (flags & IBPP::brUseAllSpace) mask |= isc_spb_res_use_all_space;
00655 if (mask != 0) spb.InsertQuad(isc_spb_options, mask);
00656
00657 (*gds.Call()->m_service_start)(status.Self(), &mHandle, 0, spb.Size(), spb.Self());
00658 if (status.Errors())
00659 throw SQLExceptionImpl(status, "Service::Restore", _("isc_service_start failed"));
00660 }
00661
00662 const char* ServiceImpl::WaitMsg()
00663 {
00664 IBS status;
00665 SPB req;
00666 RB result(1024);
00667
00668 if (gds.Call()->mGDSVersion < 60)
00669 throw LogicExceptionImpl("Service", _("Requires the version 6 of GDS32.DLL"));
00670
00671 req.Insert(isc_info_svc_line);
00672
00673
00674
00675 (*gds.Call()->m_service_query)(status.Self(), &mHandle, 0, 0, 0,
00676 req.Size(), req.Self(), result.Size(), result.Self());
00677 if (status.Errors())
00678 throw SQLExceptionImpl(status, "ServiceImpl::Wait", _("isc_service_query failed"));
00679
00680
00681 if (result.GetString(isc_info_svc_line, mWaitMessage) == 0) return 0;
00682
00683
00684 return mWaitMessage.c_str();
00685 }
00686
00687 void ServiceImpl::Wait()
00688 {
00689 IBS status;
00690 SPB spb;
00691 RB result(1024);
00692 std::string msg;
00693
00694 if (gds.Call()->mGDSVersion < 60)
00695 throw LogicExceptionImpl("Service", _("Requires the version 6 of GDS32.DLL"));
00696
00697 spb.Insert(isc_info_svc_line);
00698 for (;;)
00699 {
00700
00701
00702
00703
00704
00705
00706 Sleep(1);
00707
00708
00709
00710 (*gds.Call()->m_service_query)(status.Self(), &mHandle, 0, 0, 0,
00711 spb.Size(), spb.Self(), result.Size(), result.Self());
00712 if (status.Errors())
00713 throw SQLExceptionImpl(status, "ServiceImpl::Wait", _("isc_service_query failed"));
00714
00715
00716 if (result.GetString(isc_info_svc_line, msg) == 0) return;
00717
00718 status.Reset();
00719 result.Reset();
00720 }
00721 }
00722
00723 IBPP::IService* ServiceImpl::AddRef()
00724 {
00725 ASSERTION(mRefCount >= 0);
00726 ++mRefCount;
00727 return this;
00728 }
00729
00730 void ServiceImpl::Release()
00731 {
00732
00733 ASSERTION(mRefCount >= 0);
00734 --mRefCount;
00735 try { if (mRefCount <= 0) delete this; }
00736 catch (...) { }
00737 }
00738
00739
00740
00741 void ServiceImpl::SetServerName(const char* newName)
00742 {
00743 if (newName == 0) mServerName.erase();
00744 else mServerName = newName;
00745 }
00746
00747 void ServiceImpl::SetUserName(const char* newName)
00748 {
00749 if (newName == 0) mUserName.erase();
00750 else mUserName = newName;
00751 }
00752
00753 void ServiceImpl::SetUserPassword(const char* newPassword)
00754 {
00755 if (newPassword == 0) mUserPassword.erase();
00756 else mUserPassword = newPassword;
00757 }
00758
00759 ServiceImpl::ServiceImpl(const std::string& ServerName,
00760 const std::string& UserName, const std::string& UserPassword)
00761 : mRefCount(0), mHandle(0),
00762 mServerName(ServerName), mUserName(UserName), mUserPassword(UserPassword)
00763 {
00764 }
00765
00766 ServiceImpl::~ServiceImpl()
00767 {
00768 try { if (Connected()) Disconnect(); }
00769 catch (...) { }
00770 }
00771
00772
00773
00774