service.cpp

Go to the documentation of this file.
00001 ///////////////////////////////////////////////////////////////////////////////
00002 //
00003 //      File    : $Id: service.cpp 9523 2011-05-13 18:20:03Z frederico.bede $
00004 //      Subject : IBPP, Service class implementation
00005 //
00006 ///////////////////////////////////////////////////////////////////////////////
00007 //
00008 //      (C) Copyright 2000-2006 T.I.P. Group S.A. and the IBPP Team (www.ibpp.org)
00009 //
00010 //      The contents of this file are subject to the IBPP License (the "License");
00011 //      you may not use this file except in compliance with the License.  You may
00012 //      obtain a copy of the License at http://www.ibpp.org or in the 'license.txt'
00013 //      file which must have been distributed along with this file.
00014 //
00015 //      This software, distributed under the License, is distributed on an "AS IS"
00016 //      basis, WITHOUT WARRANTY OF ANY KIND, either express or implied.  See the
00017 //      License for the specific language governing rights and limitations
00018 //      under the License.
00019 //
00020 ///////////////////////////////////////////////////////////////////////////////
00021 //
00022 //      COMMENTS
00023 //      * Tabulations should be set every four characters when editing this file.
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 //      (((((((( OBJECT INTERFACE IMPLEMENTATION ))))))))
00048 
00049 void ServiceImpl::Connect()
00050 {
00051         if (mHandle     != 0) return;   // Already connected
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         // Attach to the Service Manager
00061         IBS status;
00062         SPB spb;
00063         std::string connect;
00064 
00065         // Build a SPB based on the     properties
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;            // Should be, but better be     sure...
00084                 throw SQLExceptionImpl(status, "Service::Connect", _("isc_service_attach failed"));
00085         }
00086 }
00087 
00088 void ServiceImpl::Disconnect()
00089 {
00090         if (mHandle     == 0) return; // Already disconnected
00091         
00092         if (gds.Call()->mGDSVersion < 60)
00093                 throw LogicExceptionImpl("Service", _("Requires the version 6 of GDS32.DLL"));
00094 
00095         IBS status;
00096 
00097         // Detach from the service manager
00098         (*gds.Call()->m_service_detach)(status.Self(), &mHandle);
00099 
00100         // Set mHandle to 0 now, just in case we need to throw, because Disconnect()
00101         // is called from Service destructor and we want to maintain a coherent state.
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         // Based on a patch provided by Torsten Martinsen (SourceForge 'bullestock')
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; // Skips the 'isc_info_svc_get_users' and its total length
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                                 // For each user, this is the first element returned
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; // Skips the 'isc_info_svc_get_users' and its total length
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                                 // For each user, this is the first element returned
00335                                 if (! user.username.empty()) users.push_back(user);     // Flush previous 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);     // Flush last 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; // Safe default mode
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);  // Request one line of textual output
00672 
00673         // _service_query will only block until a line of result is available
00674         // (or until the end of the task if it does not report information)
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         // If message length is zero bytes,     task is finished
00681         if (result.GetString(isc_info_svc_line, mWaitMessage) == 0) return 0;
00682 
00683         // Task is not finished, but we have something to report
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                 // Sleeps 1 millisecond upfront. This will release the remaining
00701                 // timeslot of the thread. Doing so will give a good chance for small
00702                 // services tasks to finish before we check if they are still running.
00703                 // The deal is to limit (in that particular case) the number of loops
00704                 // polling _service_query that will happen.
00705 
00706                 Sleep(1);
00707 
00708                 // _service_query will only block until a line of result is available
00709                 // (or until the end of the task if it does not report information) 
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                 // If message length is zero bytes,     task is finished
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         // Release cannot throw, except in DEBUG builds on assertion
00733         ASSERTION(mRefCount >= 0);
00734         --mRefCount;
00735         try { if (mRefCount <= 0) delete this; }
00736                 catch (...) { }
00737 }
00738 
00739 //      (((((((( OBJECT INTERNAL METHODS ))))))))
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 //      Eof
00774 //

Generated on Sun Jul 29 04:01:07 2012 for TerraLib - Development Source by  doxygen 1.5.3