Back to index

nordugrid-arc-nox  1.1.0~rc6
perftest_slcs.cpp
Go to the documentation of this file.
00001 #ifdef HAVE_CONFIG_H
00002 #include <config.h>
00003 #endif
00004 
00005 // perftest_slcs.cpp
00006 
00007 #include <iostream>
00008 #include <fstream>
00009 #include <string>
00010 #include <stdlib.h>
00011 #include <glibmm/thread.h>
00012 #include <glibmm/timer.h>
00013 
00014 #include <arc/GUID.h>
00015 #include <arc/ArcConfig.h>
00016 #include <arc/Logger.h>
00017 #include <arc/URL.h>
00018 #include <arc/message/PayloadSOAP.h>
00019 #include <arc/message/MCC.h>
00020 #include <arc/client/ClientInterface.h>
00021 #include <arc/client/ClientSAML2SSO.h>
00022 #include <arc/credential/Credential.h>
00023 
00024 #include <arc/xmlsec/XmlSecUtils.h>
00025 
00026 // Some global shared variables...
00027 Glib::Mutex* mutex;
00028 bool run;
00029 int finishedThreads;
00030 unsigned long completedRequests;
00031 unsigned long failedRequests;
00032 unsigned long totalRequests;
00033 Glib::TimeVal completedTime;
00034 Glib::TimeVal failedTime;
00035 Glib::TimeVal totalTime;
00036 std::string url_str;
00037 std::string idp_name;
00038 std::string username;
00039 std::string password;
00040 
00041 // Round off a double to an integer.
00042 int Round(double x){
00043   return int(x+0.5);
00044 }
00045 
00046 // Send requests and collect statistics.
00047 void sendRequests(){
00048   // Some variables...
00049   unsigned long completedRequests = 0;
00050   unsigned long failedRequests = 0;
00051   Glib::TimeVal completedTime(0,0);
00052   Glib::TimeVal failedTime(0,0);
00053   Glib::TimeVal tBefore;
00054   Glib::TimeVal tAfter;
00055   bool connected;
00056 
00057   Arc::URL url(url_str);
00058 
00059   Arc::MCCConfig mcc_cfg;
00060   mcc_cfg.AddCAFile("../../services/slcs/cacert2.pem");
00061   mcc_cfg.AddCADir("../echo/certificates");
00062 
00063   Arc::NS slcs_ns;
00064   slcs_ns["slcs"] = "http://www.nordugrid.org/schemas/slcs";
00065  
00066   while(run){
00067     // Create a Client.
00068     Arc::ClientSOAPwithSAML2SSO *client = NULL;
00069     client = new Arc::ClientSOAPwithSAML2SSO(mcc_cfg,url);
00070 
00071     connected=true;
00072     //while(run and connected){
00073       // Prepare the request and time it.
00074       Arc::PayloadSOAP req(slcs_ns);
00075 
00076       tBefore.assign_current_time();
00077 
00078       Arc::Time t;
00079       int lifetime = 12;
00080       int keysize = 1024;
00081       Arc::Credential request(t, Arc::Period(lifetime * 3600), keysize, "EEC");
00082       std::string cert_req_str;
00083       if (!request.GenerateRequest(cert_req_str))
00084         throw std::runtime_error("Failed to generate certificate request");
00085 
00086       std::string private_key;
00087       request.OutputPrivatekey(private_key);
00088 
00089       req.NewChild("GetSLCSCertificateRequest").NewChild("X509Request") = cert_req_str;
00090 
00091       // Send the request
00092       Arc::PayloadSOAP* resp = NULL;
00093       Arc::MCC_Status status = client->process(&req,&resp, idp_name, username, password);
00094 
00095       tAfter.assign_current_time();
00096  
00097       if(!status) {
00098         // Request failed.
00099         failedRequests++;
00100         failedTime+=tAfter-tBefore;
00101        connected=false;
00102       } else {
00103         if(resp == NULL) {
00104           // Response was not SOAP or no response at all.
00105           failedRequests++;
00106           failedTime+=tAfter-tBefore;
00107           connected=false;
00108         } else {
00109           if (std::string((*resp)["GetSLCSCertificateResponse"]["X509Certificate"]).size()==0){
00110             // The response was not what it should be.
00111             failedRequests++;
00112             failedTime+=tAfter-tBefore;
00113             connected=false;
00114           }
00115           else{
00116             // Everything worked just fine!
00117             completedRequests++;
00118             completedTime+=tAfter-tBefore;
00119           
00120             std::string cert_str = (std::string)((*resp)["GetSLCSCertificateResponse"]["X509Certificate"]);
00121             std::string ca_str = (std::string)((*resp)["GetSLCSCertificateResponse"]["CACertificate"]);
00122           }
00123         }
00124       }
00125       if(resp) delete resp;
00126     //}
00127     if(client) delete client;
00128   }
00129 
00130   // Update global variables.
00131   Glib::Mutex::Lock lock(*mutex);
00132   ::completedRequests+=completedRequests;
00133   ::failedRequests+=failedRequests;
00134   ::completedTime+=completedTime;
00135   ::failedTime+=failedTime;
00136   finishedThreads++;
00137   std::cout << "Number of finished threads: " << finishedThreads << std::endl;
00138 }
00139 
00140 int main(int argc, char* argv[]){
00141   // Some variables...
00142   int numberOfThreads;
00143   int duration;
00144   int i;
00145   Glib::Thread** threads;
00146   const char* config_file = NULL;
00147   int debug_level = -1;
00148   Arc::LogStream logcerr(std::cerr);
00149 
00150   // Process options - quick hack, must use Glib options later
00151   while(argc >= 3) {
00152     if(strcmp(argv[1],"-c") == 0) {
00153       config_file = argv[2];
00154       argv[2]=argv[0]; argv+=2; argc-=2;
00155     } else if(strcmp(argv[1],"-d") == 0) {
00156       debug_level=Arc::string_to_level(argv[2]);
00157       argv[2]=argv[0]; argv+=2; argc-=2;
00158     } else {
00159       break;
00160     };
00161   } 
00162   if(debug_level >= 0) {
00163     Arc::Logger::getRootLogger().setThreshold((Arc::LogLevel)debug_level);
00164     Arc::Logger::getRootLogger().addDestination(logcerr);
00165   }
00166   // Extract command line arguments.
00167   if (argc!=7){
00168     std::cerr << "Wrong number of arguments!" << std::endl
00169              << std::endl
00170              << "Usage:" << std::endl
00171              << "perftest [-c config] [-d debug] url idpname username password threads duration" << std::endl
00172              << std::endl
00173              << "Arguments:" << std::endl
00174              << "url     The url of the slcs service." << std::endl
00175               << "idpname   The name of the SP, e.g. https://squark.uio.no/idp/shibboleth" << std::endl
00176               << "username  The username to IdP " << std::endl
00177               << "password  The password to IdP   " << std::endl
00178              << "threads  The number of concurrent requests." << std::endl
00179              << "duration The duration of the test in seconds." << std::endl
00180              << "config   The file containing client chain XML configuration with " << std::endl
00181               << "         'soap' entry point and HOSTNAME, PORTNUMBER and PATH " << std::endl
00182               << "         keyword for hostname, port and HTTP path of 'echo' service." << std::endl
00183              << "debug    The textual representation of desired debug level. Available " << std::endl
00184               << "         levels: DEBUG, VERBOSE, INFO, WARNING, ERROR, FATAL." << std::endl;
00185     exit(EXIT_FAILURE);
00186   }
00187   url_str = std::string(argv[1]);
00188   idp_name = std::string(argv[2]);
00189   username = std::string(argv[3]);
00190   password = std::string(argv[4]);
00191   numberOfThreads = atoi(argv[5]);
00192   duration = atoi(argv[6]);
00193 
00194   Arc::init_xmlsec();
00195 
00196   // Start threads.
00197   run=true;
00198   finishedThreads=0;
00199   //Glib::thread_init();
00200   mutex=new Glib::Mutex;
00201   threads = new Glib::Thread*[numberOfThreads];
00202   for (i=0; i<numberOfThreads; i++) {
00203     threads[i]=Glib::Thread::create(sigc::ptr_fun(sendRequests),true);
00204     //Glib::usleep(1000000);
00205   }
00206 
00207   // Sleep while the threads are working.
00208   Glib::usleep(duration*1000000);
00209 
00210   // Stop the threads
00211   run=false;
00212   while(finishedThreads<numberOfThreads)
00213     Glib::usleep(100000);
00214 
00215   // Print the result of the test.
00216   Glib::Mutex::Lock lock(*mutex);
00217   totalRequests = completedRequests+failedRequests;
00218   totalTime = completedTime+failedTime;
00219   std::cout << "========================================" << std::endl;
00220   std::cout << "URL: "
00221            << url_str << std::endl;
00222   std::cout << "Number of threads: "
00223            << numberOfThreads << std::endl;
00224   std::cout << "Duration: "
00225            << duration << " s" << std::endl;
00226   std::cout << "Number of requests: "
00227            << totalRequests << std::endl;
00228   std::cout << "Completed requests: "
00229            << completedRequests << " ("
00230            << Round(completedRequests*100.0/totalRequests)
00231            << "%)" << std::endl;
00232   std::cout << "Failed requests: "
00233            << failedRequests << " ("
00234            << Round(failedRequests*100.0/totalRequests)
00235            << "%)" << std::endl;
00236   std::cout << "Completed requests per min: "
00237             << Round(((double)completedRequests)/duration*60)
00238             << std::endl;
00239   std::cout << "Average response time for all requests: "
00240            << Round(1000*totalTime.as_double()/totalRequests)
00241            << " ms" << std::endl;
00242   if (completedRequests!=0)
00243     std::cout << "Average response time for completed requests: "
00244              << Round(1000*completedTime.as_double()/completedRequests)
00245              << " ms" << std::endl;
00246   if (failedRequests!=0)
00247     std::cout << "Average response time for failed requests: "
00248              << Round(1000*failedTime.as_double()/failedRequests)
00249              << " ms" << std::endl;
00250   std::cout << "========================================" << std::endl;
00251 
00252   Arc::final_xmlsec();
00253 
00254   return 0;
00255 }