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
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046 #ifdef _MSC_VER
00047 #pragma warning(disable:4786)
00048 #endif
00049
00050 #include "abktimer.h"
00051 #include "abkrand.h"
00052 #include "abkMD5.h"
00053
00054 #include <fstream>
00055 #include <stdio.h>
00056 #ifdef WIN32
00057 #define _X86_
00058 #include <stdarg.h>
00059 #include <windef.h>
00060 #include <winbase.h>
00061 #include <process.h>
00062 #include <stdio.h>
00063 #else
00064 #include <unistd.h>
00065 #endif
00066
00067 using std::ios;
00068
00069 ofstream *SeedHandler::_PseedOutFile = NULL;
00070 ifstream *SeedHandler::_PseedInFile = NULL;
00071 unsigned SeedHandler::_nextSeed = UINT_MAX;
00072 bool SeedHandler::_loggingOff=false;
00073 bool SeedHandler::_haveRandObj=false;
00074 bool SeedHandler::_cleaned=false;
00075 unsigned SeedHandler::_externalSeed=UINT_MAX;
00076 unsigned SeedHandler::_progOverrideExternalSeed=UINT_MAX;
00077
00078 std::map<std::string,unsigned,SeedHandlerCompareStrings > SeedHandler::_counters;
00079
00080 SeedCleaner cleaner;
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103
00104
00105
00106
00107
00108
00109
00110
00111
00112
00113
00114
00115
00116
00117
00118
00119
00120
00121
00122
00123
00124
00125
00126
00127
00128
00129
00130
00131
00132
00133
00134
00135
00136
00137
00138
00139
00140
00141
00142
00143
00144
00145
00146
00147
00148
00149
00150
00151
00152
00153 void SeedHandler::_init()
00154 {
00155 abkfatal(!_cleaned,"Can't create random object"
00156 " after calling SeedHandler::clean()");
00157
00158 if (!_haveRandObj)
00159 {
00160 _chooseInitNondetSeed();
00161
00162 if (!_loggingOff)
00163 {
00164 _initializeOutFile();
00165 }
00166 }
00167
00168 _haveRandObj=true;
00169
00170 }
00171
00172
00173
00174
00175 SeedHandler::SeedHandler(unsigned seed):
00176 _locIdent(NULL),_counter(UINT_MAX),_isSeedMultipartite(false)
00177 {
00178 _init();
00179 if (seed==UINT_MAX)
00180 _seed = _nextSeed++;
00181 else
00182
00183 {
00184 if (_PseedInFile)
00185 {
00186 *_PseedInFile>>_seed;
00187
00188
00189 if (_PseedInFile->fail())
00190
00191 {
00192 _PseedInFile->close();
00193 delete _PseedInFile;
00194 _PseedInFile = NULL;
00195 _seed=seed;
00196
00197 }
00198
00199 }
00200 else
00201 _seed = seed;
00202
00203 if (!_loggingOff)
00204 {
00205 abkfatal(_PseedOutFile,"Internal error: unable to log "
00206 "random seed to file");
00207 *_PseedOutFile << _seed << endl;
00208 }
00209 }
00210 }
00211
00212
00213
00214 SeedHandler::SeedHandler(const char *locIdent,
00215 unsigned counterOverride):
00216 _isSeedMultipartite(true)
00217 {
00218 _init();
00219 _locIdent = strdup(locIdent);
00220
00221 if (counterOverride!=UINT_MAX)
00222 _counter=counterOverride;
00223 else
00224 {
00225 std::map<std::string,unsigned,SeedHandlerCompareStrings >::iterator iC;
00226 iC = _counters.find(_locIdent);
00227 if (iC==_counters.end()) _counters[_locIdent]=_counter=0;
00228 else { iC->second++; _counter=iC->second; }
00229 }
00230 }
00231
00232
00233
00234 SeedHandler::~SeedHandler()
00235 {
00236 if (!_isSeedMultipartite)
00237 {
00238 abkassert(_locIdent==NULL,"Non-null _locIdent with old-style seed");
00239 }
00240 else
00241 {
00242 free(_locIdent);
00243 _locIdent=NULL;
00244 }
00245 }
00246
00247
00248
00249 void SeedHandler::turnOffLogging()
00250 {
00251 _loggingOff=true;
00252 }
00253
00254
00255
00256
00257 void SeedHandler::overrideExternalSeed(unsigned extseed)
00258 {
00259 abkfatal(!_haveRandObj,"Can't call SeedHandler::overrideExternalSeed() "
00260 "after creating a random object");
00261 abkfatal(extseed != UINT_MAX,
00262 "Can't pass UINT_MAX to SeedHandler::overrideExternalSeed()");
00263 _progOverrideExternalSeed=extseed;
00264 }
00265
00266
00267
00268
00269 void SeedHandler::clean()
00270 {
00271 _cleaned=true;
00272
00273 if(_PseedOutFile)
00274 {
00275 _PseedOutFile->seekp(0,ios::beg);
00276 _PseedOutFile->put('0');
00277 _PseedOutFile->close();
00278 }
00279
00280 if(_PseedInFile)_PseedInFile->close();
00281
00282 delete _PseedOutFile;delete _PseedInFile;
00283 _PseedOutFile=NULL;
00284 _PseedInFile=NULL;
00285 }
00286
00287
00288
00289
00290
00291 void SeedHandler::_chooseInitNondetSeed()
00292 {
00293 #ifdef __GNUC__
00294 #if( __GNUC__ <= 3)
00295 _PseedInFile = new ifstream("seeds.in",ios::in);
00296 #else
00297 _PseedInFile = new ifstream("seeds.in",ios::in|ios::nocreate);
00298 #endif
00299 #else
00300 _PseedInFile = new ifstream("seeds.in",ios::in);
00301 #endif
00302
00303 if (!*_PseedInFile)
00304 {
00305 delete _PseedInFile;
00306 _PseedInFile=NULL;
00307 }
00308
00309 if (_PseedInFile)
00310 {
00311 unsigned DummyInUseLine;
00312 cerr<<"File seeds.in exists and will override all seeds, including "
00313 "hardcoded ones " << endl;
00314 *_PseedInFile >> DummyInUseLine;
00315 abkwarn(!DummyInUseLine,"File seeds.in appears to come from a process "
00316 "that never completed\n");
00317 *_PseedInFile >> _nextSeed;
00318
00319 abkfatal(!(_PseedInFile->fail()),"File seeds.in exists but program "
00320 "was unable to read initial seed "
00321 "therefrom.");
00322 abkwarn(_progOverrideExternalSeed==UINT_MAX,
00323 "\nThere is a programmatic override of the external seed,"
00324 " which will be ignored because seeds.in exists");
00325 }
00326 else if (_progOverrideExternalSeed==UINT_MAX)
00327 {
00328 Timer tm;
00329
00330 char buf[255];
00331 #if defined(WIN32)
00332 int procID=_getpid();
00333 LARGE_INTEGER hiPrecTime;
00334 ::QueryPerformanceCounter(&hiPrecTime);
00335 LONGLONG hiP1=hiPrecTime.QuadPart;
00336 sprintf(buf,"%g %d %I64d",tm.getUnixTime(),procID,hiP1);
00337 #else
00338 unsigned procID=getpid();
00339 unsigned rndbuf[2];
00340 FILE *rnd=fopen("/dev/random","r");
00341 fread(rndbuf,sizeof(rndbuf),1,rnd);
00342 fclose(rnd);
00343 sprintf(buf,"%g %d %d %d",tm.getUnixTime(),procID,rndbuf[0],rndbuf[1]);
00344 #endif
00345
00346 MD5 hash(buf);
00347 _nextSeed=hash;
00348 }
00349 else
00350 {
00351 _nextSeed=_progOverrideExternalSeed;
00352 }
00353 _externalSeed=_nextSeed;
00354 }
00355
00356
00357
00358
00359 void SeedHandler::_initializeOutFile()
00360 {
00361 unsigned inUse;
00362
00363 #ifdef __GNUC__
00364 #if( __GNUC__ < 3)
00365 ifstream outFileAsInFile("seeds.out",ios::in|ios::nocreate);
00366 #else
00367 ifstream outFileAsInFile("seeds.out",ios::in);
00368 #endif
00369 #else
00370 ifstream outFileAsInFile("seeds.out",ios::in);
00371 #endif
00372
00373 if (!!outFileAsInFile)
00374 {
00375
00376 outFileAsInFile >> inUse;
00377 if (outFileAsInFile.fail())
00378 {
00379 char errtxt[1023];
00380
00381 sprintf(errtxt,"Unable to determine whether file seeds.out is"
00382 " in use; random seeds from "
00383 "this process will not be logged.\n Initial non-"
00384 "deterministic seed is %u",_nextSeed);
00385
00386 abkwarn(0,errtxt);
00387 _loggingOff=true;
00388 }
00389 else
00390 {
00391 if (inUse)
00392 {
00393 char errtxt[1023];
00394
00395 sprintf(errtxt,"File seeds.out is in use; random seeds from "
00396 "this process will not be logged.\nInitial non-"
00397 "deterministic seed is %u.\nIf there is no "
00398 "other process running in this directory, then "
00399 "an earlier\nprocess may have terminated\n"
00400 "abnormally. "
00401 "You should remove or rename seeds.out\n"
00402 ,_nextSeed);
00403
00404 abkwarn(0,errtxt);
00405 _loggingOff=true;
00406 }
00407 }
00408 }
00409 outFileAsInFile.close();
00410
00411 if (!_loggingOff)
00412 {
00413 _PseedOutFile=new ofstream("seeds.out",ios::out);
00414
00415 if (!_PseedOutFile)
00416 {
00417 char errtxt[1023];
00418
00419 sprintf(errtxt,"Unable to create file seeds.out; random seeds from "
00420 "this process will not be logged.\n Initial non-"
00421 "deterministic seed is %u",_nextSeed);
00422
00423 abkwarn(0,errtxt);
00424 _loggingOff=true;
00425 delete _PseedOutFile;_PseedOutFile=NULL;
00426 }
00427
00428 *_PseedOutFile << "1" << endl;
00429
00430 *_PseedOutFile << _nextSeed << endl;
00431 }
00432
00433 }
00434
00435
00436
00437
00438
00439
00440
00441