00001
00020 #include <math.h>
00021 #include <errno.h>
00022 #include <sys/file.h>
00023 #include <sys/types.h>
00024 #include <signal.h>
00025 #include <stdio.h>
00026 #include <ctype.h>
00027
00028 #include <qfile.h>
00029 #include <qfileinfo.h>
00030 #include <qdatetime.h>
00031 #include <qtextstream.h>
00032
00033 #include "seticontainer.h"
00034
00035
00036 #define DIGITS (double)1.0e-6
00037
00038
00039 SetiContainer::SetiContainer(const QString& dir, int refresh)
00040 {
00041
00042 refreshIval = refresh*1000;
00043
00044
00045 setDirectory(dir);
00046
00047
00048 refTimer = startTimer(refreshIval);
00049
00050
00051 sttTimer1 = startTimer(500);
00052 sttTimer2 = startTimer(120000);
00053 }
00054
00055
00056 SetiContainer::~SetiContainer()
00057 {
00058 }
00059
00060
00061 void SetiContainer::setDirectory(const QString& dir)
00062 {
00063
00064 setiDirectory = dir;
00065
00066
00067 sahVersion = readClientVersion();
00068
00069 versionRead = false;
00070 if(sahVersion > 0)
00071 versionRead = true;
00072
00073 stfFileName = dir + "/state.sah";
00074 wufFileName = dir + "/work_unit.sah";
00075 uifFileName = dir + "/user_info.sah";
00076 rsfFileName = dir + "/result.sah";
00077 rhdFileName = dir + "/result_header.sah";
00078 wtpFileName = dir + "/wtemp.sah";
00079
00080
00081 initAllData();
00082
00083
00084 oldProgress = stfData.prog;
00085
00086
00087 cltState = Stopped;
00088 cltPid = 0;
00089 localClt = false;
00090 fastCheck = true;
00091 }
00092
00093
00094 void SetiContainer::initAllData(bool sig)
00095 {
00096
00097 initStateFileData();
00098 initWorkUnitData();
00099 initUserInfoData();
00100
00101
00102 stfTimeStamp = QString::null;
00103 uifTimeStamp = QString::null;
00104 wufTimeStamp = QString::null;
00105 pidTimeStamp = QString::null;
00106
00107
00108 updateSahData(sig);
00109 }
00110
00111
00112 void SetiContainer::setRefreshInterval(int refresh)
00113 {
00114 refreshIval = refresh*1000;
00115
00116
00117 killTimer(refTimer);
00118 refTimer = startTimer(refreshIval);
00119 }
00120
00121
00122 void SetiContainer::timerEvent(QTimerEvent* e)
00123 {
00124 if(e->timerId() == refTimer)
00125 updateSahData();
00126 else if(e->timerId() == sttTimer2)
00127 checkClientStatePassive();
00128 else if(e->timerId() == sttTimer1)
00129 {
00130 bool oldFastCheck = fastCheck;
00131 if((int)cpuTime() > 600 && (int)remainingTime() > 600)
00132 fastCheck = false;
00133 else
00134 fastCheck = true;
00135 if(fastCheck != oldFastCheck)
00136 {
00137
00138
00139
00140 killTimer(sttTimer1);
00141 if(fastCheck)
00142 sttTimer1 = startTimer(500);
00143 else
00144 sttTimer1 = startTimer(2500);
00145 }
00146 checkClientState();
00147 }
00148 }
00149
00150
00151 int SetiContainer::updateSahData(bool sig)
00152 {
00153 int err;
00154 int filesMissing = 0;
00155
00156
00157 if(versionRead == false)
00158 {
00159 sahVersion = readClientVersion();
00160 if(sahVersion > 0)
00161 versionRead = true;
00162 }
00163 else
00164 {
00165 if(QFile::exists(setiDirectory + "/version.sah") == false &&
00166 QFile::exists(setiDirectory + "/version.txt") == false)
00167 {
00168 sahVersion = 0;
00169 versionRead = false;
00170 }
00171 }
00172
00173 err = readUserInfoFile(sig);
00174 if(err)
00175 {
00176 filesMissing++;
00177 #ifndef NDEBUG
00178 qDebug("SetiContainer (%s): user_info.sah missing.",
00179 (const char*)directory());
00180 #endif
00181 }
00182
00183 err = readWorkUnitFile(sig);
00184 if(err)
00185 {
00186 filesMissing++;
00187 #ifndef NDEBUG
00188 qDebug("SetiContainer (%s): work_unit.sah missing.",
00189 (const char*)directory());
00190 #endif
00191 }
00192
00193 err = readStateFile(sig);
00194 if(err)
00195 {
00196 filesMissing++;
00197 #ifndef NDEBUG
00198 qDebug("SetiContainer (%s): state.sah missing.",
00199 (const char*)directory());
00200 #endif
00201 }
00202
00203
00204 if(filesMissing == 3)
00205 {
00206 if(cltState != Stopped)
00207 {
00208 cltState = Stopped;
00209 emit stateChanged(cltState);
00210 }
00211 err = 1;
00212 }
00213
00214 return(err);
00215 }
00216
00217
00218 int SetiContainer::readSahFile(const QString& file, QStringList& list, const QString& endId)
00219 {
00220 int ret(0);
00221 QFile sah(file);
00222
00223
00224 list.clear();
00225
00226 if(sah.open(IO_ReadOnly))
00227 {
00228 QTextStream t(&sah);
00229 QString s;
00230 while( !t.atEnd() )
00231 {
00232 s = t.readLine();
00233
00234 if (s.isEmpty() || (endId && endId == s)) break;
00235 list.append(s);
00236 }
00237 sah.close();
00238 }
00239 else
00240 ret = 1;
00241
00242 return(ret);
00243 }
00244
00245
00246 int SetiContainer::readStateFile(bool sig)
00247 {
00248 int ret(0);
00249
00250
00251 if(exists(SC_StateFile) == false) return(1);
00252
00253
00254 QFileInfo fi(stfFileName);
00255 QDateTime dt = QDateTime(fi.lastModified());
00256 QString ts = dt.toString();
00257
00258 if(ts != stfTimeStamp)
00259 {
00260 stfTimeStamp = ts;
00261 ret = readSahFile(stfFileName, stateFile);
00262
00263 if(ret == 0)
00264 scanStateFile(sig);
00265 }
00266
00267 return(ret);
00268 }
00269
00270
00271 int SetiContainer::readWorkUnitFile(bool sig)
00272 {
00273 int ret(0);
00274
00275
00276 if(exists(SC_WorkUnitFile) == false) return(1);
00277
00278
00279 QFileInfo fi(wufFileName);
00280 QDateTime dt = QDateTime(fi.lastModified());
00281 QString ts = dt.toString();
00282
00283 if(ts != wufTimeStamp)
00284 {
00285 wufTimeStamp = ts;
00286 ret = readSahFile(wufFileName, workunitFile, "end_seti_header");
00287
00288 if(ret == 0)
00289 scanWorkUnitData(sig);
00290 }
00291
00292 return(ret);
00293 }
00294
00295
00296 int SetiContainer::readUserInfoFile(bool sig)
00297 {
00298 int ret(0);
00299
00300
00301 if(exists(SC_UserInfoFile) == false) return(1);
00302
00303
00304 QFileInfo fi(uifFileName);
00305 QDateTime dt = QDateTime(fi.lastModified());
00306 QString ts = dt.toString();
00307
00308 if(ts != uifTimeStamp)
00309 {
00310 uifTimeStamp = ts;
00311 ret = readSahFile(uifFileName, userinfoFile);
00312
00313 if(ret == 0)
00314 scanUserInfoData(sig);
00315 }
00316
00317 return(ret);
00318 }
00319
00320
00321 QString SetiContainer::readEntry(int sah, const QString& e)
00322 {
00323 QString val;
00324
00325 switch(sah)
00326 {
00327 case SC_StateFile:
00328 val = readEntry(stfFileName, e);
00329 break;
00330 case SC_UserInfoFile:
00331 val = readEntry(uifFileName, e);
00332 break;
00333 case SC_WorkUnitFile:
00334 val = readEntry(wufFileName, e);
00335 break;
00336 case SC_ResultFile:
00337 val = readEntry(rsfFileName, e);
00338 break;
00339 default:
00340 val = QString::null;
00341 break;
00342 }
00343
00344 return(val);
00345 }
00346
00347
00348
00349 QString SetiContainer::readEntry(const QString& fn, const QString& e)
00350 {
00351 QString v = QString::null;
00352 QString l,s;
00353 int eq(-1);
00354 bool found(false);
00355 QFile sah(fn);
00356
00357 if(sah.open(IO_ReadOnly))
00358 {
00359 QTextStream t(&sah);
00360 while( !t.eof() )
00361 {
00362 s = t.readLine();
00363
00364
00365 if (s.isEmpty()) break;
00366 eq = s.find('=');
00367 if(eq != -1)
00368 {
00369 l = s.left(eq);
00370 if(l == e) {found = true; break;}
00371 }
00372 }
00373 if(found && s.length()-eq-1 > 0)
00374 v = s.right( s.length()-eq-1 );
00375 sah.close();
00376 }
00377
00378 return( v );
00379 }
00380
00381
00382 QString SetiContainer::readEntry(QStringList& list, const QString& e)
00383 {
00384 QString v = QString::null;
00385 QString s;
00386 int pos;
00387 bool found(false);
00388
00389 QStringList::Iterator it;
00390 for(it=list.begin(); it!=list.end(); ++it)
00391 {
00392
00393 s = (*it);
00394 pos = s.find(e);
00395
00396 if(pos == 0)
00397 {
00398 found = true;
00399 break;
00400 }
00401 }
00402
00403 if(found)
00404 {
00405
00406 pos = s.find('=');
00407
00408 if(pos > 0 && s.length()-pos-1 > 0)
00409 v = s.right(s.length()-pos-1);
00410 }
00411
00412 return(v);
00413 }
00414
00415
00416 void SetiContainer::initWUScore(WUScore* score)
00417 {
00418 score->spike.power = 0.0;
00419 score->spike.score = 0.0;
00420 score->spike.bin = 0;
00421 score->spike.fft_index = 0;
00422 score->spike.fft_len = 0;
00423 score->spike.chirprate = 0.0;
00424 score->spike.ra = 0.0;
00425 score->spike.dec = 0.0;
00426 score->spike.frequency = 0.0;
00427 score->spike.wu_name = "";
00428
00429 score->gaussian.score = 0.0;
00430 score->gaussian.power = 0.0;
00431 score->gaussian.bin = 0;
00432 score->gaussian.chisq = 0.0;
00433 score->gaussian.true_mean = 0.0;
00434 score->gaussian.sigma = 0.0;
00435 score->gaussian.fft_index = 0;
00436 score->gaussian.fft_len = 0;
00437 score->gaussian.chirprate = 0.0;
00438 score->gaussian.ra = 0.0;
00439 score->gaussian.dec = 0.0;
00440 score->gaussian.frequency = 0.0;
00441 score->gaussian.wu_name = "";
00442 for(int i=0;i<64;i++) score->gaussian.data[i] = 0.0;
00443 score->gaussian.data_len = 0;
00444
00445 score->pulse.score = 0.0;
00446 score->pulse.power = 0.0;
00447 score->pulse.mean = 0.0;
00448 score->pulse.period = 0.0;
00449 score->pulse.freq_bin = 0;
00450 score->pulse.time_bin = 0;
00451 score->pulse.fft_len = 0;
00452 score->pulse.chirprate = 0.0;
00453 score->pulse.ra = 0.0;
00454 score->pulse.dec = 0.0;
00455 score->pulse.frequency = 0.0;
00456 score->pulse.wu_name = "";
00457 for(int i=0;i<512;i++) score->pulse.data[i] = 0;
00458 score->pulse.data_len = 0;
00459
00460 score->triplet.score = 0.0;
00461 score->triplet.power = 0.0;
00462 score->triplet.mean = 0.0;
00463 score->triplet.period = 0.0;
00464 score->triplet.bperiod = 0.0;
00465 score->triplet.tpotind0_0 = 0;
00466 score->triplet.tpotind0_1 = 0;
00467 score->triplet.tpotind1_0 = 0;
00468 score->triplet.tpotind1_1 = 0;
00469 score->triplet.tpotind2_0 = 0;
00470 score->triplet.tpotind2_1 = 0;
00471 score->triplet.freq_bin = 0;
00472 score->triplet.time_bin = 0.0;
00473 score->triplet.scale = 0.0;
00474 score->triplet.fft_len = 0;
00475 score->triplet.chirprate = 0.0;
00476 score->triplet.ra = 0.0;
00477 score->triplet.dec = 0.0;
00478 score->triplet.frequency = 0.0;
00479 score->triplet.wu_name = "";
00480 for(int i=0;i<512;i++) score->triplet.data[i] = 0;
00481 score->triplet.data_len = 0;
00482 }
00483
00484
00485 void SetiContainer::initStateFileData()
00486 {
00487 stfData.ncfft = 0;
00488 stfData.cr = 0.0;
00489 stfData.fl = 0;
00490 stfData.cpu = 0.0;
00491 stfData.prog = 0.0;
00492 stfData.potfreq = 0;
00493 stfData.potactivity = 0;
00494 stfData.outfilepos = 0;
00495 initWUScore(&stfData.max);
00496 }
00497
00498
00499 void SetiContainer::initWorkUnitData()
00500 {
00501 wufData.task = "";
00502 wufData.version = 0;;
00503 wufData.name = "";
00504 wufData.data_type = "";
00505 wufData.data_class = 0;
00506 wufData.splitter_version = "";
00507 wufData.start_ra = 0.0;
00508 wufData.start_dec = 0.0;
00509 wufData.end_ra = 0.0;
00510 wufData.end_dec = 0.0;
00511 wufData.angle_range = 0.0;
00512 wufData.time_recorded = "";
00513 wufData.subband_center = 0.0;
00514 wufData.subband_base = 0.0;
00515 wufData.subband_sample_rate = 0.0;
00516 wufData.fft_len = 0;
00517 wufData.ifft_len = 0;
00518 wufData.subband_number = 0;
00519 wufData.receiver = "";
00520 wufData.nsamples = 0;
00521 wufData.tape_version = "";
00522 wufData.num_positions = 0;
00523 wufData.coordinates.clear();
00524 }
00525
00526
00527 void SetiContainer::initUserInfoData()
00528 {
00529 uifData.id = 0;
00530 uifData.key = 0;
00531 uifData.email_addr = "";
00532 uifData.name = "";
00533 uifData.url = "";
00534 uifData.country = "";
00535 uifData.postal_code = 0;
00536 uifData.show_name = false;
00537 uifData.show_email = false;
00538 uifData.venue = 0;
00539 uifData.register_time = "";
00540 uifData.last_wu_time = "";
00541 uifData.last_result_time = "";
00542 uifData.nwus = 0;
00543 uifData.nresults = 0;
00544 uifData.total_cpu = 0.0;
00545 uifData.params_index = 0;
00546 }
00547
00548
00549 void SetiContainer::scanStateFile(bool sig)
00550 {
00551 QString val;
00552
00553 val = readEntry(stateFile, "ncfft");
00554 stfData.ncfft = val.toInt();
00555
00556 val = readEntry(stateFile, "cr");
00557 stfData.cr = val.toDouble();
00558
00559 val = readEntry(stateFile, "fl");
00560 stfData.fl = val.toInt();
00561
00562 val = readEntry(stateFile, "cpu");
00563 stfData.cpu = val.toDouble();
00564
00565 double oldprog = stfData.prog;
00566 val = readEntry(stateFile, "prog");
00567 stfData.prog = val.toDouble();
00568 double diff = fmod(stfData.prog-oldprog, DIGITS);
00569 if(diff > 0.0 && sig)
00570 {
00571 emit progressIncreased();
00572
00573
00574
00575 if(cltState != Running && oldprog > 0.0)
00576 {
00577 cltState = Running;
00578 emit stateChanged(cltState);
00579 }
00580 }
00581 if(diff < 0.0 && sig) emit progressDecreased();
00582
00583 val = readEntry(stateFile, "potfreq");
00584 stfData.potfreq = val.toInt();
00585
00586 val = readEntry(stateFile, "potactivity");
00587 stfData.potactivity = val.toInt();
00588
00589 val = readEntry(stateFile, "outfilepos");
00590 stfData.outfilepos = val.toInt();
00591
00592 scanSpikeData(sig);
00593 scanGaussianData(sig);
00594 scanPulseData(sig);
00595 scanTripletData(sig);
00596
00597 }
00598
00599
00600 void SetiContainer::scanSpikeData(bool sig)
00601 {
00602 QString val;
00603
00604
00605 double oldspike = stfData.max.spike.power;
00606 val = readEntry(stateFile, "bs_power");
00607 stfData.max.spike.power = val.toDouble();
00608
00609 double diff = fmod(stfData.max.spike.power-oldspike, DIGITS);
00610 if(diff > 0.0)
00611 {
00612
00613 val = readEntry(stateFile, "bs_bin");
00614 stfData.max.spike.bin = val.toInt();
00615
00616
00617 val = readEntry(stateFile, "bs_chirp_rate");
00618 stfData.max.spike.chirprate = val.toDouble();
00619
00620
00621 val = readEntry(stateFile, "bs_fft_ind");
00622 stfData.max.spike.fft_index = val.toInt();
00623
00624
00625 val = readEntry(stateFile, "bs_fft_len");
00626 stfData.max.spike.fft_len = val.toInt();
00627
00628
00629 val = readEntry(stateFile, "bs_score");
00630 stfData.max.spike.score = val.toDouble();
00631
00632 stfData.max.spike.wu_name = wuName();
00633
00634 if(sig) emit newSpike(stfData.max.spike);
00635 }
00636 }
00637
00638
00639 void SetiContainer::scanGaussianData(bool sig)
00640 {
00641 QString val;
00642
00643
00644 double oldgaussian = stfData.max.gaussian.score;
00645 val = readEntry(stateFile, "bg_score");
00646 stfData.max.gaussian.score = val.toDouble();
00647
00648 double diff = fmod(stfData.max.gaussian.score-oldgaussian, DIGITS);
00649 if(diff > 0.0)
00650 {
00651
00652 val = readEntry(stateFile, "bg_bin");
00653 stfData.max.gaussian.bin = val.toInt();
00654
00655
00656 val = readEntry(stateFile, "bg_power");
00657 stfData.max.gaussian.power = val.toDouble();
00658
00659
00660 val = readEntry(stateFile, "bg_chisq");
00661 stfData.max.gaussian.chisq = val.toDouble();
00662
00663
00664 val = readEntry(stateFile, "bg_fft_len");
00665 stfData.max.gaussian.fft_len = val.toInt();
00666
00667
00668 val = readEntry(stateFile, "bg_chirp_rate");
00669 stfData.max.gaussian.chirprate = val.toDouble();
00670
00671
00672 val = readEntry(stateFile, "bg_sigma");
00673 stfData.max.gaussian.sigma = val.toDouble();
00674
00675
00676 val = readEntry(stateFile, "bg_true_mean");
00677 stfData.max.gaussian.true_mean = val.toDouble();
00678
00679
00680 val = readEntry(stateFile, "bg_fft_ind");
00681 stfData.max.gaussian.fft_index = val.toInt();
00682
00683
00684 scanGaussianGraphData();
00685
00686 stfData.max.gaussian.wu_name = wuName();
00687
00688 if(sig) emit newGaussian(stfData.max.gaussian);
00689 }
00690 }
00691
00692
00693 void SetiContainer::scanGaussianGraphData()
00694 {
00695 QString val;
00696
00697 for(int i=0;i<=63;i++)
00698 {
00699 val = readEntry(stateFile, QString("bg_pot %1").arg(i));
00700 stfData.max.gaussian.data[i] = val.toDouble();
00701 }
00702 stfData.max.gaussian.data_len = 64;
00703 }
00704
00705
00706 void SetiContainer::scanPulseData(bool sig)
00707 {
00708 QString val;
00709
00710
00711 double oldpulse = stfData.max.pulse.score;
00712 val = readEntry(stateFile, "bp_score");
00713 stfData.max.pulse.score = val.toDouble();
00714
00715 double diff = fmod(stfData.max.pulse.score-oldpulse, DIGITS);
00716 if(diff > 0.0)
00717 {
00718
00719 val = readEntry(stateFile, "bp_power");
00720 stfData.max.pulse.power = val.toDouble();
00721
00722
00723 val = readEntry(stateFile, "bp_mean");
00724 stfData.max.pulse.mean = val.toDouble();
00725
00726
00727 val = readEntry(stateFile, "bp_period");
00728 stfData.max.pulse.period = val.toDouble();
00729
00730
00731 val = readEntry(stateFile, "bp_chirp_rate");
00732 stfData.max.pulse.chirprate = val.toDouble();
00733
00734
00735 val = readEntry(stateFile, "bp_freq_bin");
00736 stfData.max.pulse.freq_bin = val.toInt();
00737
00738
00739 val = readEntry(stateFile, "bp_time_bin");
00740 stfData.max.pulse.time_bin = val.toInt();
00741
00742
00743 val = readEntry(stateFile, "bp_fft_len");
00744 stfData.max.pulse.time_bin = val.toInt();
00745
00746
00747 if(scanPulseGraphData() == false)
00748 debug("Pulse data could not be read.");
00749
00750 stfData.max.pulse.wu_name = wuName();
00751
00752 if(sig) emit newPulse(stfData.max.pulse);
00753 }
00754 }
00755
00756
00757 bool SetiContainer::scanPulseGraphData()
00758 {
00759 bool status = false;
00760 int dl;
00761
00762 QString buf = readEntry(stateFile, "bp_pot");
00763 dl = readDataString(&stfData.max.pulse.data[0], buf, 512);
00764 if(dl > 0)
00765 {
00766 stfData.max.pulse.data_len = dl;
00767 status = true;
00768 }
00769
00770 return(status);
00771 }
00772
00773
00774 void SetiContainer::scanTripletData(bool sig)
00775 {
00776 QString val;
00777
00778
00779 double oldtriplet = stfData.max.triplet.score;
00780 val = readEntry(stateFile, "bt_score");
00781 stfData.max.triplet.score = val.toDouble();
00782
00783 double diff = fmod(stfData.max.triplet.score-oldtriplet, DIGITS);
00784 if(diff > 0.0)
00785 {
00786
00787 val = readEntry(stateFile, "bt_power");
00788 stfData.max.triplet.power = val.toDouble();
00789
00790
00791 val = readEntry(stateFile, "bt_mean");
00792 stfData.max.triplet.mean = val.toDouble();
00793
00794
00795 val = readEntry(stateFile, "bt_period");
00796 stfData.max.triplet.period = val.toDouble();
00797
00798
00799 val = readEntry(stateFile, "bt_chirp_rate");
00800 stfData.max.triplet.chirprate = val.toDouble();
00801
00802
00803 val = readEntry(stateFile, "bt_tpotind0_0");
00804 stfData.max.triplet.tpotind0_0 = val.toInt();
00805 val = readEntry(stateFile, "bt_tpotind0_1");
00806 stfData.max.triplet.tpotind0_1 = val.toInt();
00807 val = readEntry(stateFile, "bt_tpotind1_0");
00808 stfData.max.triplet.tpotind1_0 = val.toInt();
00809 val = readEntry(stateFile, "bt_tpotind1_1");
00810 stfData.max.triplet.tpotind1_1 = val.toInt();
00811 val = readEntry(stateFile, "bt_tpotind2_0");
00812 stfData.max.triplet.tpotind2_0 = val.toInt();
00813 val = readEntry(stateFile, "bt_tpotind2_1");
00814 stfData.max.triplet.tpotind2_1 = val.toInt();
00815
00816
00817 val = readEntry(stateFile, "bt_bperiod");
00818 stfData.max.triplet.bperiod = val.toDouble();
00819
00820
00821 val = readEntry(stateFile, "bt_freq_bin");
00822 stfData.max.triplet.freq_bin = val.toInt();
00823
00824
00825 val = readEntry(stateFile, "bt_time_bin");
00826 stfData.max.triplet.time_bin = val.toDouble();
00827
00828
00829 val = readEntry(stateFile, "bt_scale");
00830 stfData.max.triplet.scale = val.toDouble();
00831
00832
00833 val = readEntry(stateFile, "bt_fft_len");
00834 stfData.max.triplet.fft_len = val.toInt();
00835
00836
00837 if(scanTripletGraphData() == false)
00838 debug("Triplet data could not be read.");
00839
00840 stfData.max.triplet.wu_name = wuName();
00841
00842 if(sig) emit newTriplet(stfData.max.triplet);
00843 }
00844 }
00845
00846
00847 bool SetiContainer::scanTripletGraphData()
00848 {
00849 bool status = false;
00850 int dl;
00851 QString buf;
00852
00853 buf = readEntry(stateFile, "bt_pot");
00854 dl = readDataString(&stfData.max.triplet.data[0], buf, 512);
00855 if(dl > 0)
00856 {
00857 stfData.max.triplet.data_len = dl;
00858 status = true;
00859 }
00860
00861 return(status);
00862 }
00863
00864
00865 int SetiContainer::readDataString(unsigned short int data[],
00866 QString& str, int cnt)
00867 {
00868 char byte[2];
00869 int i = 0;
00870
00871 if(!str.isEmpty())
00872 {
00873 QTextStream ts(&str, IO_ReadOnly);
00874 unsigned int val;
00875 while(!ts.atEnd() && i < cnt)
00876 {
00877 ts >> byte[0] >> byte[1];
00878 if(isxdigit(byte[0]) && isxdigit(byte[1]))
00879 sscanf(byte, "%x", &val);
00880 else
00881 break;
00882 data[i] = (unsigned short int)val;
00883 i++;
00884 }
00885 }
00886
00887 return(i);
00888 }
00889
00890
00891 void SetiContainer::scanUserInfoData(bool sig)
00892 {
00893 QString val;
00894
00895
00896 val = readEntry(userinfoFile, "id");
00897 uifData.id = val.toInt();
00898
00899
00900 val = readEntry(userinfoFile, "key");
00901 uifData.key = val.toInt();
00902
00903
00904 uifData.email_addr = readEntry(userinfoFile, "email_addr");
00905
00906
00907 uifData.name = readEntry(userinfoFile, "name");
00908
00909
00910 uifData.url = readEntry(userinfoFile, "url");
00911
00912
00913 uifData.country = readEntry(userinfoFile, "country");
00914
00915
00916 val = readEntry(userinfoFile, "postal_code");
00917 uifData.postal_code = val.toInt();
00918
00919
00920 val = readEntry(userinfoFile, "show_name");
00921 if(val == "yes")
00922 uifData.show_name = true;
00923 else
00924 uifData.show_name = false;
00925
00926
00927 val = readEntry(userinfoFile, "show_email");
00928 if(val == "yes")
00929 uifData.show_email = true;
00930 else
00931 uifData.show_email = false;
00932
00933
00934 val = readEntry(userinfoFile, "venue");
00935 uifData.venue = val.toInt();
00936
00937
00938 uifData.register_time = readEntry(userinfoFile, "register_time");
00939
00940
00941 uifData.last_wu_time = readEntry(userinfoFile, "last_wu_time");
00942
00943
00944 uifData.last_result_time = readEntry(userinfoFile, "last_result_time");
00945
00946
00947 val = readEntry(userinfoFile, "nwus");
00948 uifData.nwus = val.toInt();
00949
00950
00951 val = readEntry(userinfoFile, "nresults");
00952 uifData.nresults = val.toInt();
00953
00954
00955 val = readEntry(userinfoFile, "total_cpu");
00956 uifData.total_cpu = val.toDouble();
00957
00958
00959 val = readEntry(userinfoFile, "params_index");
00960 uifData.params_index = val.toInt();
00961
00962
00963 if(sig) emit updatedUserInfoData();
00964 }
00965
00966
00967 void SetiContainer::scanWorkUnitData(bool sig)
00968 {
00969 QString val;
00970
00971
00972 wufData.task = readEntry(workunitFile, "task");
00973
00974
00975 val = readEntry(workunitFile, "version");
00976 wufData.version = val.toInt();
00977
00978
00979 wufData.name = readEntry(workunitFile, "name");
00980
00981
00982 wufData.data_type = readEntry(workunitFile, "data_type");
00983
00984
00985 val = readEntry(workunitFile, "data_class");
00986 wufData.data_class = val.toInt();
00987
00988
00989 wufData.splitter_version = readEntry(workunitFile, "splitter_version");
00990
00991
00992 val = readEntry(workunitFile, "start_ra");
00993 wufData.start_ra = val.toDouble();
00994
00995
00996 val = readEntry(workunitFile, "start_dec");
00997 wufData.start_dec = val.toDouble();
00998
00999
01000 val = readEntry(workunitFile, "end_ra");
01001 wufData.end_ra = val.toDouble();
01002
01003
01004 val = readEntry(workunitFile, "end_dec");
01005 wufData.end_dec = val.toDouble();
01006
01007
01008 val = readEntry(workunitFile, "angle_range");
01009 wufData.angle_range = val.toDouble();
01010
01011
01012 wufData.time_recorded = readEntry(workunitFile, "time_recorded");
01013
01014
01015 val = readEntry(workunitFile, "subband_center");
01016 wufData.subband_center = val.toDouble();
01017
01018
01019 val = readEntry(workunitFile, "subband_base");
01020 wufData.subband_base = val.toDouble();
01021
01022
01023 val = readEntry(workunitFile, "subband_sample_rate");
01024 wufData.subband_sample_rate = val.toDouble();
01025
01026
01027 val = readEntry(workunitFile, "fft_len");
01028 wufData.fft_len = val.toInt();
01029
01030
01031 val = readEntry(workunitFile, "ifft_len");
01032 wufData.ifft_len = val.toInt();
01033
01034
01035 val = readEntry(workunitFile, "subband_number");
01036 wufData.subband_number = val.toInt();
01037
01038
01039 wufData.receiver = readEntry(workunitFile, "receiver");
01040
01041
01042 val = readEntry(workunitFile, "nsamples");
01043 wufData.nsamples = val.toInt();
01044
01045
01046 wufData.tape_version = readEntry(workunitFile, "tape_version");
01047
01048
01049 val = readEntry(workunitFile, "num_positions");
01050 wufData.num_positions = val.toInt();
01051
01052
01053 wufData.coordinates.clear();
01054 if(wufData.num_positions > 0)
01055 {
01056 QString e;
01057 for(int i=0; i<wufData.num_positions; i++)
01058 {
01059 val = readEntry(workunitFile, (e = "coord%1").arg(i));
01060 if(!val.isEmpty())
01061 wufData.coordinates.append(val);
01062 }
01063 }
01064
01065
01066 if(sig) emit updatedWorkUnitData();
01067 }
01068
01069
01070 int SetiContainer::readClientVersion()
01071 {
01072 int version(0);
01073
01074 QString versionFile(setiDirectory + "/version.sah");
01075
01076 if(QFile::exists(versionFile))
01077 {
01078 QString entry = readEntry(versionFile, "major_version");
01079 version = 100*entry.toInt();
01080 entry = readEntry(versionFile, "minor_version");
01081 version += entry.toInt();
01082 }
01083 else if(QFile::exists(setiDirectory + "/version.txt"))
01084 version = 100;
01085
01086 return(version);
01087 }
01088
01089
01090
01091 double SetiContainer::progressRate()
01092 {
01093 double prograte = (cpuTime() > 0.0) ? (3600.0/cpuTime())*progress() : 0.0;
01094 return(prograte);
01095 }
01096
01097
01098 double SetiContainer::remainingTime()
01099 {
01100 double timeleft = (progressRate() > 0.0) ?
01101 3600.0*(100.0 - progress())/progressRate() : 0.0;
01102 return(timeleft);
01103 }
01104
01105
01106 QString SetiContainer::remainingTimeAsString()
01107 {
01108 double tl = remainingTime();
01109 return(convertTime(tl, true));
01110 }
01111
01112
01113 QString SetiContainer::convertTime(double time, bool hms)
01114 {
01115 unsigned int d, h, m, s;
01116 QString t;
01117
01118 d = static_cast<unsigned int>(time/86400.0);
01119 h = static_cast<unsigned int>(time) % 86400 / 3600;
01120 m = static_cast<unsigned int>(time) % 3600 / 60;
01121 s = static_cast<unsigned int>(time) % 60;
01122
01123
01124 if( hms || (hms == false && d == 0))
01125 {
01126 h += d*24;
01127 t.sprintf("%u:%02u:%02u", h, m, s);
01128 }
01129 else
01130 {
01131 if(d >= 365)
01132 t.sprintf("%.4f yrs", time/31536000.0);
01133 else
01134 t.sprintf("%ud:%02u:%02u:%02u", d, h, m, s);
01135 }
01136
01137 return(t);
01138 }
01139
01140
01141 QString SetiContainer::convertRAToString(double ra)
01142 {
01143 int h, m, s;
01144 QString val;
01145
01146 h = static_cast<int>(ra);
01147 m = static_cast<int>((ra - h)*60);
01148 s = static_cast<int>((ra - h)*3600 - m*60);
01149 val.sprintf("%2d h %02d min %02d s", h, m, s);
01150
01151 return(val);
01152 }
01153
01154
01155 QString SetiContainer::convertDecToString(double dec)
01156 {
01157 int d, m, s;
01158 QString val;
01159
01160 d = static_cast<int>(dec);
01161 m = static_cast<int>((dec - d)*60);
01162 s = static_cast<int>((dec - d)*3600 - m*60);
01163 val.sprintf("%2d° %02d' %02d''", d, m, s);
01164
01165 return(val);
01166 }
01167
01168
01169 QString SetiContainer::timeRecordedString()
01170 {
01171 QString tr = timeRecorded();
01172
01173 int k = tr.find('(');
01174 int l = tr.find(')');
01175 if(k > -1 && l > -1 && l > k)
01176 tr = tr.mid(k+1, l-k-1);
01177 else
01178 tr = "";
01179
01180 return(tr);
01181 }
01182
01183
01184 double SetiContainer::averageCPUTime()
01185 {
01186 double avgcpu = (numberOfResults() > 0) ? totalCPUTime()/(double)numberOfResults() : 0.0;
01187 return(avgcpu);
01188 }
01189
01190
01191 QString SetiContainer::lastResultTimeString()
01192 {
01193 QString lrt = lastResultTime();
01194
01195 int k = lrt.find('(');
01196 int l = lrt.find(')');
01197 if(k > -1 && l > -1 && l > k)
01198 lrt = lrt.mid(k+1, l-k-1);
01199 else
01200 lrt = "";
01201
01202 return(lrt);
01203 }
01204
01205
01206 QString SetiContainer::registerTimeString()
01207 {
01208 QString rt = registerTime();
01209
01210 int k = rt.find('(');
01211 int l = rt.find(')');
01212 if(k > -1 && l > -1 && l > k)
01213 rt = rt.mid(k+1, l-k-1);
01214 else
01215 rt = "";
01216
01217 return(rt);
01218 }
01219
01220
01221 bool SetiContainer::exists(int sah)
01222 {
01223 bool ex;
01224
01225 switch(sah)
01226 {
01227 case SC_StateFile:
01228 ex = QFile::exists(stfFileName);
01229 break;
01230 case SC_UserInfoFile:
01231 ex = QFile::exists(uifFileName);
01232 break;
01233 case SC_WorkUnitFile:
01234 ex = QFile::exists(wufFileName);
01235 break;
01236 case SC_ResultFile:
01237 ex = QFile::exists(rsfFileName);
01238 break;
01239 case SC_WtempFile:
01240 ex = QFile::exists(wtpFileName);
01241 break;
01242 case SC_ResultHeaderFile:
01243 ex = QFile::exists(rhdFileName);
01244 break;
01245 default:
01246 ex = false;
01247 break;
01248 }
01249
01250 return(ex);
01251 }
01252
01253
01254 double SetiContainer::teraFlops(double ar, int version)
01255 {
01256 double tf(0.0);
01257
01258 if(version == 0) version = clientVersion();
01259
01260 if(version >= 200 && version <= 204)
01261 {
01262 if(ar >= 0.2255 && ar <= 1.1274)
01263 tf = 1.45*pow(ar, -0.0826);
01264 else
01265 tf = 1.34;
01266 }
01267 else if(version >= 300 && version < 303)
01268 {
01269 if(ar < 0.2255)
01270 tf = 2.37;
01271
01272 if(ar >= 0.2255 && ar <= 1.1274)
01273 tf = 2.58*pow(ar, -0.1531);
01274
01275 if(ar > 1.1274)
01276 tf = 2.23*pow(ar, -0.0115);
01277 }
01278 else if(version >= 303)
01279 {
01280 if(ar < 0.2255)
01281 tf = 3.54*exp(0.0327*ar);
01282
01283 if(ar >= 0.2255 && ar <= 1.1274)
01284 tf = 3.74*pow(ar, -0.1075);
01285
01286 if(ar > 1.1274)
01287 tf = 3.37*pow(ar, -0.0065);
01288 }
01289 else
01290 tf = 1.5;
01291
01292 return(tf);
01293 }
01294
01295
01296 double SetiContainer::megaFlopsPerSecond()
01297 {
01298 return((10.0*teraFlops(angleRange())*progressRate())/3.6);
01299 }
01300
01301
01302 int SetiContainer::checkClientState()
01303 {
01304
01305 static int count = 0;
01306
01307 int oldState = cltState;
01308
01309 if(exists(SC_WtempFile) && !exists(SC_ResultHeaderFile))
01310 {
01311 if(
01312 exists(SC_ResultFile))
01313 {
01314
01315 if(isClientRunning())
01316 {
01317
01318
01319 localClt = true;
01320
01321 if(oldState == Running || oldState == Stopped)
01322 {
01323 cltState = Finished;
01324 count = 0;
01325 }
01326 else if(oldState == Finished)
01327 {
01328
01329 count++;
01330 if(count >= 3)
01331 cltState = Connecting;
01332 }
01333 }
01334 else
01335 {
01336 cltPid = (pid_t)0;
01337 cltState = Finished;
01338 }
01339 }
01340 else
01341 {
01342
01343
01344 if(isClientRunning())
01345 {
01346 localClt = true;
01347 cltState = Loading;
01348 }
01349 else
01350 {
01351 if(localClt)
01352 {
01353 cltPid = (pid_t)0;
01354 cltState = Stopped;
01355 }
01356 else
01357 {
01358
01359
01360 if(oldState == Running || oldState == Stopped)
01361 cltState = Finished;
01362 else
01363 cltState = Loading;
01364 }
01365 }
01366 }
01367 }
01368 else
01369 {
01370 switch(cltState)
01371 {
01372 case Finished:
01373 case Loading:
01374 case Connecting:
01375
01376 if(exists(SC_WorkUnitFile))
01377 {
01378
01379 initAllData(true);
01380
01381 stfData.prog = -1.0;
01382
01383 cltState = Running;
01384
01385 emit newWorkUnit(wufData);
01386 }
01387 break;
01388 case Running:
01389 if(localClt && !isClientRunning())
01390 {
01391 cltState = Stopped;
01392 cltPid = (pid_t)0;
01393 }
01394 break;
01395 case Stopped:
01396 if(isClientRunning())
01397 {
01398
01399
01400 localClt = true;
01401 if(exists(SC_WorkUnitFile))
01402 cltState = Running;
01403 else
01404 cltState = Connecting;
01405 }
01406 break;
01407 default:
01408 #ifndef NDEBUG
01409 qDebug("SetiContainer (%s): Invalid client state.",
01410 (const