server.cc

Go to the documentation of this file.
00001 
00007 #include "at_startup.H"
00008 
00009 // sanity checks
00010 #ifdef IS_CLIENT
00011  #error "The server is not a client!"
00012 #endif
00013 
00014 #ifndef IS_SERVER
00015  #error "The server needs IS_SERVER to function correctly!"
00016 #endif
00017 
00018 #ifndef USE_NETWORK
00019  #error "The server uses network features!"
00020 #endif
00021 
00022 #ifdef IS_STANDALONE
00023  #error "The server is not standalone!"
00024 #endif
00025 
00026 
00027 
00028 extern "C"
00029 {
00030  #include <unistd.h>
00031 }
00032 
00033 #include <cstdio>
00034 #include <cstdlib>
00035 #include <fstream>
00036 #include <sstream>
00037 #include <cmath>
00038 #include <gmp.h>
00039 #include <list>
00040 #include <set>
00041 #include <ctime>
00042 
00043 #include "qsieve.H"
00044 #include "StaticFactorbase.H"
00045 
00046 
00047 #include "FactorFound.H"
00048 TFoundFactors FoundFactors;
00049 
00050 #include <vector>
00051 #include <stack>
00052 #include <algorithm>
00053 
00054 extern "C"
00055 {
00056  #include <sys/utsname.h>
00057  #include <pthread.h>
00058 }
00059 
00060 #include <csignal>
00061 #include "mutex.H"
00062 
00063 
00064 
00065 const string RecoveryFile         = "recovery.dat";
00066 const string FoundFactorsFile     = "FoundFactors.dat";
00067 const string StaticRelationsFile  = "static_relations.dat";
00068 const string SpecialRelationsFile = "special_relations.dat";
00069 
00070 
00071 // provide streams for storing relations and other data
00072 // *************************************************************************
00073 // **** important:
00074 // **** If "ostream" and "istream" are handled by the same filebuf,
00075 // **** then you *must not* rely on 
00076 // **** "tellp()" and "tellg()" behave independently from each other!
00077 // **** Any write operation may change also the value of "tellg()"
00078 // **** and any read operation may change the value of "tellp()"!
00079 // ************************************************************************* 
00080 
00081 
00082 // for Recovery
00083 filebuf Recovery_buffer;
00084 ostream Recovery_to_file (&Recovery_buffer);
00085 istream Recovery_from_file (&Recovery_buffer);
00086 
00087 
00088 #include "mpqsPolynom.H"
00089 
00090 
00091 mpz_t n, // number to factorize (will be reduced during factorization)
00092       kN; // input for MPQS (includes a suitable multiplier)
00093 
00094 
00095 #include "StaticRelations.H"
00096 #include "DynamicRelations.H"
00097 #include "SpecialRelations.H"
00098 
00099 #include "Sieving.H"
00100 #include "ConfigFile.cc"
00101 
00102 
00103 CmpqsPolynom Polynom; // object to manage polynomial computations for multipolynomial sieve (MPQS)
00104 #include "mpqsStatistics.cc" // statistical stuff about found relations, client connections, etc.
00105 
00106 
00107 #include "modulo.H" // modulo operations for unsigned int
00108 using namespace numtheory;
00109 
00110 #include "FactorFound.cc"
00111 #include "polynomial.H" /* for fast polynomial arithmetic & fft-continuation */
00112 #include "fft_param.cc"  /* discrete fast fourier transform */
00113 #include "elliptic_curve.H" /* invariant part of elliptic curve method (ecm) */
00114 #include "elliptic_curve-variant.cc" /* variant part of elliptic curve method (ecm) */
00115 
00116 #include "ExitManager.cc" /* controlled termination of program */
00117 #include "StaticRelations.cc"
00118 
00119 
00120 // this stuff may only be needed by server or stand-alone version
00121 #include "easy_factor.H"
00122 
00123 
00124 #include "CRelation-inc.cc"
00125 
00126 
00127 #include "parse_term.cc"
00128 // this is a predicate stating "false"
00129 const bool without_multi_combine_init = false; // true ->multi-init, false ->no multi_init on StaticRelations::insert
00130 
00131 
00132 #include "SpecialRelations.cc"
00133 
00134 
00135 #include "Cprocess_clients.cc"
00136 #include "XML_StatusServer.cc"
00137 
00138 
00139 
00140 void kill_all_other_threads()
00141 {
00142   //cout << "Killing explicitly all other threads..." << endl;
00143   //pthread_kill_other_threads_np();
00144 }
00145 
00146 
00147 
00148 void cleanup_files()
00149 {
00150 #ifdef VERBOSE_INFO
00151   cout << "cleaning files..." << endl;
00152 #endif
00153   StaticRelations::cleanup_files();
00154   SpecialRelations::cleanup_files();
00155   DynamicRelations::cleanup_files();
00156   Recovery_buffer.close();
00157   remove(RecoveryFile.c_str());
00158 }
00159 
00160 void cleanup_memory()
00161 {
00162 #ifdef VERBOSE_INFO
00163   cout << "cleanup allocated memory" << endl;
00164 #endif
00165   StaticRelations::cleanup_memory();
00166   mpz_clear(CmpqsFactor::DLP_Threshold);
00167   mpz_clear(kN); mpz_clear(n);
00168 }
00169 
00170 
00171 void signalhandler(int signr)
00172 {
00173 #ifdef VERBOSE_WARN
00174   cout << "Signal " << signr << " received. (ThreadId=" << pthread_self() << ")" << endl;
00175 #endif
00176   exit(1);
00177 }
00178 
00179 
00180 
00181 
00182 int main(const int argc, const char* const argv[])
00183 {
00184 
00185 #ifdef USE_NCURSES
00186   new Cncursed(); // trigger activation of ncursed streams
00187 #endif
00188 
00189   PrintHeader("Qsieve server");
00190     
00191   if (argc>2)
00192     {
00193       cerr << "number for factorization expected!" << endl;
00194       exit(1);
00195     }
00196   
00197   const bool recover = (argc==1); // without argument: Recovery-Mode
00198 
00199   atexit(kill_all_other_threads);
00200   cout.setf(ios::fixed); // fixed decimal notation, not scientific notation!
00201 
00202   mpz_init(n); // our number to factorize
00203   mpz_init(kN);
00204   ExitManager::register_exithandler(cleanup_memory); // on successful exit free allocated data
00205 
00206   Read_ConfigFile();
00207 
00208 
00209   // establish the network service at this point,
00210   // to allow clients to connect
00211   const connection_waiter my_connection_waiter(server_port);
00212 
00213   if (!recover) // not in recovery-mode -> evaluate arguments
00214     { 
00215       // get and evaluate given number
00216       char* const neuer_str = strdup(argv[1]);
00217       char* str = neuer_str; 
00218       if (!parse_term::get_number(n, str))
00219         {
00220           cout << "Wrong input at: '" << str << "'" << endl;
00221           exit(1);
00222         }
00223       else
00224         if (str[0]!='\0')
00225           {    
00226             cout << "Syntax error in input term. (parenthesis?)" << endl;
00227             exit(1);
00228           }
00229         else
00230           if (mpz_cmp_ui(n,0)<=0)
00231             {
00232               cout << "Input must be positive natural number!" << endl;
00233               exit(1);
00234             }
00235       free(neuer_str); // don't call "delete []" because of "stdup/malloc"
00236       FoundFactors.regarding=argv[1];
00237       mpz_set(FoundFactors.regarding_numeric_value,n);
00238     }
00239 
00240   if (recover)
00241     {
00242       // Recovery: continue a factorization, which was previously aborted
00243       // (try to) open the necessary file streams
00244       StaticRelations::FileBuffer.open(StaticRelationsFile.c_str(),ios::in|ios::out);
00245       SpecialRelations::FileBuffer.open(SpecialRelationsFile.c_str(),ios::in|ios::out);
00246       if (!DynamicRelations::FileBuffer.open(DynamicRelationsFile.c_str(),ios::in|ios::out))
00247        {
00248          cerr << "Cannot access " << DynamicRelationsFile << endl;
00249          exit(1);
00250        }
00251       Recovery_buffer.open(RecoveryFile.c_str(),ios::in|ios::out|ios::ate);
00252 
00253       // offenbar wird trotz ios::ate nicht (immer) ans Ende positioniert
00254       // deshalb wird die Testabfrage modifiziert:
00255       if (Recovery_from_file) Recovery_from_file.seekg(0,ios::end);
00256 #ifdef STL_STREAM_workaround
00257       if ( (!Recovery_from_file) || (Recovery_from_file.tellg()==std::streampos(0)) || (Recovery_from_file.tellg()==std::streampos(-1)) )
00258 // tellg()==0 indicates empty file -> we cannot recover
00259 // tellg()==-1 indicates failure -> we cannot recover
00260 // remark:
00261 //  in gcc 3.4 (cvs-experimental-2003-10-17 we cannot compare with "<" !!)
00262 //  do we really need a workaround to check this condition? 
00263 #else
00264       if ( (!Recovery_from_file) || (Recovery_from_file.tellg()<1) )
00265 #endif /* STL_STREAM_workaround */
00266         {
00267           cerr << "Recovery not possible!" << endl;
00268           exit(1);
00269         }
00270       
00271       Recovery_from_file.seekg(0,ios::beg);
00272       Recovery_to_file.seekp(0,ios::beg);
00273       Recovery_from_file >> n; // retrieve number
00274       Recovery_from_file.ignore(1,'\n');
00275 
00276       cout << "Continue factorization for " << endl;
00277       cout << n << endl;
00278 
00279       // mark recovery-mode in Factorization-File! One never knows, what has
00280       // happened to that file in the mean time!
00281       Factorization_to_file << " [RECOVERY] "; // flush not necessary... 
00282       FoundFactors.AutoLoad();
00283     }
00284   else
00285     {
00286       // First start of this factorization (i.e. not a recovery)
00287       // open streams
00288       StaticRelations::FileBuffer.open(StaticRelationsFile.c_str(),ios::out|ios::trunc);
00289       SpecialRelations::FileBuffer.open(SpecialRelationsFile.c_str(),ios::in|ios::out|ios::trunc);
00290       if (!DynamicRelations::FileBuffer.open(DynamicRelationsFile.c_str(),ios::in|ios::out|ios::trunc))
00291        {
00292          cerr << "Cannot access " << DynamicRelationsFile << endl;
00293          exit(1);
00294        }
00295 
00296       Recovery_buffer.open(RecoveryFile.c_str(),ios::in|ios::out|ios::trunc);
00297       
00298       cout_status << "Starting factorization for" << endl;
00299       cout_status << n << endl;
00300       
00301       Factorization_to_file << endl << "Factorization of " << argv[1] << ":" << endl;
00302       Factorization_to_file << n << " = " << endl;
00303       
00304       easy_factor(); // remove "easy" detectable factors
00305       
00306 #ifdef VERBOSE_NOTICE
00307       cout_status << "Starting factorization with ECM and MPQS for" << endl;
00308       cout_status << n << endl;
00309 #endif
00310       Recovery_to_file << n << endl;
00311       unlink("ecm-recover.dat"); // remove any existent ecm recovery file
00312     }
00313   ExitManager::register_exithandler(cleanup_files); // on successful exit delete the files
00314 
00315   signal(SIGINT, signalhandler);
00316   tune_parameters(mpz_sizeinbase(n,10));
00317 
00318 #ifdef NOTIFY_PARENT
00319   // notify parent that now the distributed phase starts
00320   // and the server will process client connections
00321   kill(getppid(),SIGUSR1); // send SIGUSR1 to the parent process
00322 #endif
00323 
00324   CXML_StatusServer::install_XML_StatusServer();
00325   if (!SkipECM)
00326    {
00327 #ifdef VERBOSE_NOTICE
00328      cout << "Waiting for net-clients (ECM)..." << endl;
00329 #endif
00330      Cprocess_clients::process_data_stream_ecm(my_connection_waiter); // start distributed ECM...
00331    }
00332 
00333 
00334 #if defined(USE_DFT) || (CONTINUATION_METHOD==2)
00335   // at this place, all possible functions that made possible use of
00336   // discrete fast fourier transform have been finished.
00337   //  --> we can release the DFT-object and associated auxiliary memory...
00338   polynomial::clear_dft_tempmemory();
00339 #endif /* USE_DFT */
00340 
00341   // now prepare everything for the Quadratic Sieve...
00342 
00343   determine_best_MPQS_Multiplier(n,kN,MPQS_Multiplier); // calculate a good/optimal value for fastest possible sieving
00344   tune_parameters(mpz_sizeinbase(n,10)); // tune parameters for n
00345 
00346 
00347   
00348   if ( sqrt(mpz_get_d(kN)) < PhysicalSieveSize )
00349     {
00350       cerr << "Sieve size too big (you may want to reduce its size)!" << endl;
00351       exit(1);
00352     }
00353 
00354   // Set a threshold for Double-Large-Primes,
00355   // this is the square of the maximal Single Large Prime...
00356   mpz_init(CmpqsFactor::DLP_Threshold);
00357   mpz_set_ui(CmpqsFactor::DLP_Threshold,SingleLargePrime_Threshold);
00358   mpz_mul(CmpqsFactor::DLP_Threshold,CmpqsFactor::DLP_Threshold,CmpqsFactor::DLP_Threshold);
00359   
00360   StaticFactorbase::compute_StaticFactorbase();
00361 
00362   // the server does not sieve anything, so initialize the sieve only, if
00363   // the program is not compiled in server mode
00364 
00365 
00366   Polynom.compute_first_polynomial(kN,LogicalSieveSize); // compute the first MPQS polynomial to sieve with
00367 
00368   
00369   if (recover)
00370     {
00371       StaticRelations::Load(); // read in Static Relations
00372       DynamicRelations::Load(); // read in Dynamic Relations
00373       SpecialRelations::Load();
00374       statistical_data::ProgressStats.take_sample(); // first statistical sample right here
00375         // CycleSearch triggers taking a sample when finding a cycle,
00376         // but this sample wouldn't contain the full DLP size (see CycleSearch)!
00377         // So we need the first sample taken before the first CycleSearch...
00378       SpecialRelations::CycleSearch();
00379   
00380 #ifdef SAFEMODE
00381       // are all the relations valid?
00382       CRelation::SanityCheckRelationsFile(StaticRelationsFile);
00383       CRelation::SanityCheckRelationsFile(DynamicRelationsFile);
00384       CRelation::SanityCheckRelationsFile(SpecialRelationsFile);
00385 #endif      
00386       streampos fpos = Recovery_from_file.tellg();
00387       Polynom.load_if_available(Recovery_from_file); // get current polynomial (to continue factorization)
00388       Recovery_to_file.seekp(fpos);
00389     }
00390 
00391   display_StatusLegend();
00392 
00393   // install seek_emergency_handler for handling subtle seek errors... (see Cprocess_clients.cc)
00394   CRelation::seek_emergency_handler = Cprocess_clients::seek_emergency_handler;
00395 
00396 #ifdef VERBOSE_NOTICE
00397   cout << "Waiting for clients (MPQS)..." << endl;
00398 #endif
00399   //cout << "I'm the main thread with id = " << pthread_self() << endl;
00400   while (true)
00401    {    
00402      int* pdata = new int;
00403      *pdata = my_connection_waiter.get_new_client_socket_descriptor();
00404      pthread_attr_t detached_thread;
00405      pthread_t thread_process_client_data;
00406 
00407      pthread_attr_init(&detached_thread);
00408      pthread_attr_setdetachstate(&detached_thread, PTHREAD_CREATE_DETACHED);
00409 
00410      //cout << "creating thread..." << endl;
00411      const int retcode = pthread_create(&thread_process_client_data,&detached_thread,
00412                           Cprocess_clients::THREAD_process_data_stream, pdata);
00413      if (retcode != 0)
00414       {
00415         cerr << "pthread_create failed!" << endl;
00416         delete pdata;
00417         exit(1);
00418       }
00419    }
00420 
00421 
00422 
00423 #ifdef VERBOSE_INFO  
00424   cout << endl << "Session ended successfully." << endl;
00425 #endif
00426   return 0;
00427 }

Generated on Wed Nov 7 23:29:26 2007 for Qsieve by  doxygen 1.5.4