header

MDFed.cc

Go to the documentation of this file.
00001 /*
00002   Copyright (c) Members of the EGEE Collaboration. 2004.
00003   See http://www.eu-egee.org/partners/ for details on the copyright
00004   holders.
00005 
00006   Licensed under the Apache License, Version 2.0 (the "License");
00007   you may not use this file except in compliance with the License.
00008   You may obtain a copy of the License at
00009 
00010     http://www.apache.org/licenses/LICENSE-2.0
00011 
00012   Unless required by applicable law or agreed to in writing, software
00013   distributed under the License is distributed on an "AS IS" BASIS,
00014   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00015   See the License for the specific language governing permissions and
00016   limitations under the License.
00017 */
00018 
00019 #include "MDFed.h"
00020 #include <iostream>
00021 #include <fstream>
00022 #include "debug.h"
00023 
00024 using namespace std;
00025 
00026 MDFed::MDFed(bool dbg)
00027   : debug(dbg), pmdc(NULL)
00028 {
00029 }
00030 
00031 MDFed::~MDFed() 
00032 {
00033 }
00034 
00035 /************************************************
00036  * setParentMDClient
00037  *   Set parent MDClient 
00038  *   In case of ServerSide Federation, it is NULL. 
00039  ***********************************************/
00040 
00041 void MDFed::setParentMDClient(MDClient* mdc)
00042 {
00043   pmdc = mdc;
00044 }
00045 
00046 /************************************************
00047  * decodeFedFlags
00048  *   Retrieve Policies for federation
00049  *     - cmdType : command type 
00050  *     - allowFedConnFail : whether to allow connection failure
00051  *     - allowFedExecFail : whether to allow execution failure
00052  ***********************************************/
00053 
00054 int MDFed::decodeFedFlags(std::string& flags)
00055 {
00056     char* ptr;
00057     int flag_int = strtol(flags.c_str(), &ptr, 10);
00058 
00059     decodeFedFlags(flag_int);
00060 }
00061 
00062 int MDFed::decodeFedFlags(int flag_int)
00063 {
00064     cmdType  = flag_int ;
00065     allowFedConnFail = flag_int & ALLOW_FED_CONN ;
00066     allowFedExecFail = flag_int & ALLOW_FED_EXEC ;
00067 
00068     DMESG("CMD TYPE : " << cmdType << std::endl);
00069     DMESG("FED CONN : " << allowFedConnFail << std::endl);
00070     DMESG("FED EXEC : " << allowFedExecFail << std::endl);
00071 }
00072 
00073 /************************************************
00074  * lookupFedHosts
00075  *   Check whether there is information about the given host
00076  *   If it exists, set its status to 1 
00077  ***********************************************/
00078 
00079 int MDFed::lookupFedHosts(std::string &dn) {
00080     std::list<AMGA::MDChild>::iterator I = mdchild.begin();
00081     while( I != mdchild.end() ) {
00082       if( I->dn == dn ) {
00083         I->status = 1;
00084         DMESG("Using : " << dn << " : " << I->dn << std::endl);
00085         return 0;
00086       } else {
00087         DMESG("Not Using : " << dn << " : " << I->dn << std::endl);
00088       }
00089       I++;
00090     }
00091     return -1;
00092 }
00093 
00094 
00095 /************************************************
00096  * retrieveFedHosts
00097  *   Retrieve lists of hosts managing real data
00098  *   Only called with Client Side Federation
00099  ***********************************************/
00100 
00101 int MDFed::retrieveFedHosts(std::string& errmsg)
00102 {
00103   int count = 0 ;
00104   std::string sflags;
00105   int cmdType;
00106   int allowConnErr, allowExecErr;
00107 
00108   if( pmdc == NULL ) return -1;
00109   errmsg = pmdc->getError();
00110 
00111   /* retrieve federation policy */
00112   if( pmdc->fetchRow(sflags) ) {
00113     errmsg = "Federation Flag Retrieval Error\n" ;
00114     return -1;
00115   }
00116 
00117   decodeFedFlags(sflags);
00118 
00119   while( ! pmdc->eot() ) {
00120     std::string tmp_dn;
00121     std::string tmp_host;
00122     std::string tmp_port;
00123 
00124     /* retrieve host name and port number managing federated data */
00125     if( pmdc->fetchRow(tmp_host) || pmdc->fetchRow(tmp_port) ) {
00126       count = 0;
00127       break;
00128     }
00129 
00130     tmp_dn = tmp_host;
00131     tmp_dn.append(":");
00132     tmp_dn.append(tmp_port);
00133 
00134     /* Check whether the host exists already */
00135     if ( lookupFedHosts(tmp_dn) > -1 ) {
00136       count++;
00137       continue;
00138     }
00139 
00140     char* ptr;
00141     int tmp_port_int = strtol(tmp_port.c_str(), &ptr, 10);
00142     if( tmp_port_int == 0 ) tmp_port_int = MD_DEFAULT_PORT;
00143 
00144     /* Create a new MDClient for new federated hosts */
00145     MDClient *child = new MDClient(tmp_host, tmp_port_int);
00146     AMGA::MDChild mdc(tmp_dn, tmp_host, tmp_port_int, (void*) child);
00147 
00148     /* set it to valid */
00149     mdc.status = 1;
00150     /* set its connection is not setup yet */
00151     mdc.connection = 0;
00152     DMESG("new service2 : " << tmp_dn << std::endl);
00153     mdchild.push_back(mdc);
00154     count++;
00155   }
00156 
00157   if( count == 0 ) {
00158     errmsg = "Federation Host Retrieval Error\n" ;
00159     return -1;
00160   }
00161 
00162   return 0;
00163 }
00164 
00165 /************************************************
00166  * addFedHosts
00167  *   Insert information about a federated host
00168  *   Only called with Server Side Federation
00169  ***********************************************/
00170 
00171 int MDFed::addFedHost(std::string tmp_host, int tmp_port, Site & s)
00172 {
00173   std::string tmp_dn; 
00174   std::stringstream out_t;
00175 
00176   out_t << tmp_host << ":" << tmp_port;
00177   tmp_dn = out_t.str();
00178 
00179   /* Check whether the host exists already */
00180   if ( lookupFedHosts(tmp_dn) > -1 ) 
00181     return -1;
00182 
00183   char* ptr;
00184 
00185   char fname[L_tmpnam+1];
00186   tmpnam(fname);
00187   MDClient* child;
00188 
00189   ofstream myfile;
00190   myfile.open(fname);
00191   
00192 
00193   /* Load a site information on the given host 
00194      , which is mainly related to authentication */
00195   if (strlen(s.login)) 
00196     myfile << "Login = " << s.login << "\n";
00197   if (strlen(s.password)) 
00198     myfile << "Password = " << s.password << "\n";
00199   if ( s.useSSL ) 
00200     myfile << "UseSSL = 1\n";
00201   else 
00202     myfile << "UseSSL = 0\n";
00203 
00204   if ( s.authenticateWithCertificate )
00205     myfile << "AuthenticateWithCertificate = 1\n";
00206   else
00207     myfile << "AuthenticateWithCertificate = 0\n";
00208 
00209   if ( strlen(s.certFile) ) 
00210     myfile << "CertFile = " << s.certFile << "\n";
00211   if ( strlen(s.keyFile) ) 
00212     myfile << "KeyFile = " << s.keyFile << "\n";
00213   if ( s.useGridProxy )
00214     myfile << "UseGridProxy = 1\n";
00215   else 
00216     myfile << "UseGridProxy = 0\n";
00217   if (s.verifyServerCert)
00218     myfile << "VerifyServerCert = 1\n";
00219   else 
00220     myfile << "VerifyServerCert = 0\n";
00221   if ( strlen(s.trustedCertDir) ) 
00222     myfile << "TrustedCertDir = " << s.trustedCertDir << "\n";
00223   if ( strlen(s.certPassword) )
00224     myfile << "PrivateKeyPassword = " << s.certPassword << "\n";
00225   myfile.close();
00226 
00227   /* Create a new MDClient for new federated hosts */
00228   child = new MDClient(tmp_host, tmp_port, false, fname);
00229   remove (fname);
00230 
00231   AMGA::MDChild mdc(tmp_dn, tmp_host, tmp_port, (void*) child);
00232 
00233   mdc.status = 1;
00234   mdc.connection = 0;
00235   DMESG("new service : " << tmp_dn << std::endl);
00236   mdchild.push_back(mdc);
00237   return 0;
00238 }
00239 
00240 
00241 /************************************************
00242  * removeFedHeader
00243  *   In case of SELECT, column information from the second federated server
00244  *   should be removed. 
00245  ***********************************************/
00246 
00247 int MDFed::removeFedHeader(int col){
00248   std::string s;
00249 
00250   DMESG("Removing : " << col << " rows" << std::endl);
00251   for(int i=0; i < col; i++ ) {
00252     if( fetchRow(s, false) ) {
00253       return -1;
00254     }
00255   }
00256   return 0;
00257 }
00258 
00259 /************************************************
00260  * initNextFedHosts
00261  *   Find and connect next federated host, and execute the given command
00262  *
00263  *   flags : first call to this function for a command
00264  ***********************************************/
00265 
00266 int MDFed::initNextFedHosts(int flags, std::string& errmsg)
00267 {
00268 
00269     DMESG("initNextFedHosts start ...  " << std::endl);
00270 
00271     std::list<AMGA::MDChild>::iterator I;
00272     if ( flags ) {
00273       I = mdchild.begin();
00274       failureCode = 0;
00275     } else {
00276       /* if the type is random, 
00277            it should have had a successful execution when the flag was true*/
00278       if ( (cmdType & FED_FILTER) == FED_RANDOM ) return -1;
00279       I = currentChild ;
00280       I++;
00281     }
00282 
00283     int tmp_success = 0;
00284     while( I != mdchild.end() ) {
00285       bool justConnected = false;
00286 
00287       // if the host is not a valid one, skip
00288       if( I->status == 0 ) { I++; continue; }
00289 
00290       DMESG("Service II : " << I->dn << std::endl);
00291       currentChild = I;
00292 
00293       MDClient *child = (MDClient*) I->mdc;
00294 
00295       // if connection is not made, make a new connection to a host
00296       if ( I->connection == 0 ) {
00297         if ( child->connectToServer() ) {
00298           DMESG("Failed to connect ...  " << cmdType << std::endl);
00299           errmsg = "failed to access federated directory ";
00300 
00301           // if it allows connection failure, try another server
00302           if ( allowFedConnFail || ((cmdType & FED_FILTER) == FED_RANDOM) ) {
00303             DMESG("Failure code 2 " << std::endl);
00304             failureCode |= 2;
00305             I++; continue;
00306           } else {
00307             errmsg.append("[").append(I->dn).append("]");
00308             return -1;
00309           }
00310         }
00311         // this variable is set only when connection is just made. 
00312         justConnected = true;
00313       }
00314 
00315       // mark the connection is set
00316       I->connection = 1;
00317 
00318       // execute the command
00319       if ( child->execute(lastCommand) ) {
00320 
00321         // if connection is made some time agon, let's give another chance
00322         // if (justConnected == false) { I->connection = 0; continue; }
00323         errmsg = child->getError();
00324         DMESG("Execution Failure : " << errmsg << std::endl);
00325 
00326         // get rid of all the remained data at the socket
00327         if(! child->endOfTransmission) child->fetchData();
00328 
00329         // if it allows execution failure, try another server    
00330         if ( allowFedExecFail  || ((cmdType & FED_FILTER) == FED_RANDOM) ) {
00331           DMESG("Failure code 1 " << std::endl);
00332           failureCode |= 1;
00333           I++; continue;
00334         } else {
00335           errmsg.append("[").append(I->dn).append("]");
00336           return -1;
00337         }
00338       }
00339 
00340       // In case of SELECT, 
00341       // column information from the second federated server should be removed.
00342       if( (flags == 0) && (cmdType & FED_SELE))  {
00343         DMESG("Removing HEADER of Select  " << std::endl);
00344         if ( removeFedHeader(child->resultCols) < 0 ) {
00345           errmsg = "Failed to remove Fed Header";
00346           return -1;
00347         }
00348       }
00349 
00350       tmp_success++;
00351       I++;
00352 
00353       /* FED_ONCE means that the commands should be executed at all servers
00354          right now */
00355       if ( (cmdType & FED_ONCE) == 0 )
00356         return 0;
00357 
00358       /* FED_RANDOM means that it is successful if the command is executed
00359          successfully */
00360       if ( (cmdType & FED_FILTER) == FED_RANDOM )
00361         return 0;
00362     }
00363     DMESG("initNextFedHosts end ...  " << std::endl);
00364     if (tmp_success > 0) return 0;
00365     return -1;
00366 }
00367 
00368 /************************************************
00369  * clearFedHosts
00370  *   set the status of all the hosts to be not valid
00371  ***********************************************/
00372 
00373 void MDFed::clearFedHosts() {
00374     std::list<AMGA::MDChild>::iterator I = mdchild.begin();
00375     while( I != mdchild.end() ) {
00376       I->status = 0;
00377       I++;
00378     }
00379 }
00380 
00381 /************************************************
00382  * initFed
00383  *   initilize federation
00384  *   it is executed whenever a new command is executed 
00385  *     and its target is federated
00386  ***********************************************/
00387 
00388 int MDFed::initFed(std::string& errmsg, bool serverSide){
00389 
00390     /* In case of client side federation,
00391        retrieve list of federated hosts from the server */
00392     if ( (serverSide == 0) && (retrieveFedHosts(errmsg) < 0) ) {
00393       DMESG("retrieveFedHost Error" << std::endl);
00394       if ( pmdc != NULL) pmdc->setError(errmsg);
00395       return 99; 
00396     }
00397 
00398     // If the command is not supported one by federation
00399     if( (cmdType & FED_FILTER) == FED_NONE) {
00400       DMESG("Not allowed Command Error" << std::endl);
00401       errmsg = "Not allowed command for federation" ;
00402       if ( pmdc != NULL) pmdc->setError(errmsg);
00403       return 99; 
00404     }
00405 
00406     // Find a next federated host, connect and execute the command
00407     if ( initNextFedHosts(1, errmsg) < 0 ) {
00408       DMESG("init Next Host Error" << std::endl);
00409       if ( pmdc != NULL) pmdc->setError(errmsg);
00410       return 99 ; 
00411     }
00412 
00413     proxyState = true;
00414     return 0;
00415 }
00416 
00417 /************************************************
00418  * fetchRow
00419  *   Fetch a row in terms of federation
00420  *   If end of data, then go for a next federated host
00421  ***********************************************/
00422 
00423 int MDFed::fetchRow(std::string &line, bool readAhead)
00424 {
00425     MDClient* child ;
00426     child = (MDClient*) currentChild->mdc;
00427     
00428     int bytes;
00429     std::string errmsg;
00430     while ( (bytes = child->fetchRow(line, readAhead)) < 0 ) {
00431       if ( initNextFedHosts(0,errmsg) < 0 ) {
00432         return 0;
00433       }
00434       child = (MDClient*) currentChild->mdc;
00435     }
00436     return bytes;
00437 }
00438 
00439 
00440 /************************************************
00441  * eot
00442  *   Check end of data in terms of federation
00443  ***********************************************/
00444 
00445 int MDFed::eot()
00446 {
00447     MDClient *child ;
00448     child = (MDClient*) currentChild->mdc;
00449 
00450     std::string errmsg;
00451     while (child->eot()) {
00452       if ( initNextFedHosts(0, errmsg) < 0 ) {
00453         return true;
00454       }
00455       child = (MDClient*) currentChild->mdc;
00456     }
00457     return false;
00458 }
00459 
00460 
00461 /************************************************
00462  * disconnectFed
00463  *   disconnect from all federated hosts
00464  ***********************************************/
00465 
00466 void MDFed::disconnectFed(bool saveSession)
00467 {
00468   std::list<AMGA::MDChild>::iterator I = mdchild.begin();
00469 
00470   MDClient *child ;
00471   while( I != mdchild.end() ) {
00472     if( (I->mdc != NULL) && (I->connection == 1) ) {
00473       child = (MDClient*) I->mdc;
00474       //child->disconnect(saveSession);
00475       child->disconnect(false);
00476       delete child;
00477     }
00478     I++;
00479   }
00480 
00481   mdchild.clear();
00482 }
00483 
00484 
00485 
00486 
00487 
00488 
00489 

Generated on Mon Apr 16 13:59:17 2012 for AMGA by  doxygen 1.4.7