00001 #include "Fitter.h"
00002 #include "../src/FitStrategy.h"
00003 #include "FitterWorkerGroup.h"
00004 #include "ThresholdFitAlgorithm.h"
00005 #include "ThresholdFitAlgorithm2.h"
00006
00007 #include "Sct/SctNames.h"
00008 #include "Sct/SctParameters.h"
00009 #include "Sct/DestroyingDeleter.h"
00010 #include "Sct/StdExceptionWrapper.h"
00011 #include "Sct/IS/IONameIS.h"
00012
00013 #include <iostream>
00014 #include <vector>
00015 #include <cassert>
00016 #include <ctime>
00017 #include <string>
00018 #include <TMath.h>
00019 #include <boost/timer.hpp>
00020
00021 using namespace std;
00022 using namespace Sct;
00023 using namespace SctData;
00024 using namespace boost;
00025
00026 namespace SctFitter {
00027 void doFits(ISCallbackInfo * isc);
00028
00029 Fitter* Fitter::fitter=0;
00030
00031 Fitter& Fitter::instance() {
00032 if (!fitter)
00033 throw Sct::IllegalStateError("Attempt to use uninitialised Fitter", __FILE__, __LINE__);
00034 return *fitter;
00035 }
00036
00037 Fitter& Fitter::initialize(FitterArguments args) throw(ConfigurationException) {
00038 fitter = new Fitter(args);
00039 return *fitter;
00040 }
00041
00042 void Fitter::shutdown(){
00043 if (workergroup) workergroup->stop();
00044 getFitterServer().stop();
00045 }
00046
00047 Fitter::Fitter(FitterArguments args) throw(ConfigurationException) :
00048 IPCNamedObject<POA_FitterI::FitterInterface>(
00049 SctNames::getPartition(),
00050 args.instanceName()),
00051 m_nFitsDone(0), m_nFitErrors(0), m_nScans(0), m_scanTimeTaken(0), m_ioTimeTaken(0), m_scan("No last scan"),
00052 m_fitStrategy(0), workergroup(0), m_args(args)
00053 {
00054 std::cout << "Fitting Service " << m_args.print() << endl;
00055 Sct::SctNames::Mrs() << "FITTER_START" << MRS_PARAM<const char*>("Name",m_args.instanceName().c_str())
00056 << MRS_INFORMATION << ENDM;
00057 auto_ptr<ISInfoReceiver> ir(new ISInfoReceiver(SctNames::getPartition()));
00058 if (!ir.get())
00059 throw ConfigurationException("Fitter::initialize can't make infoReceiver ", __FILE__, __LINE__) ;
00060 m_infoReceiver = ir;
00061 try{
00062 internal_setFitStrategy(m_args.getStrategyName());
00063 }catch(Sct::Throwable& e){
00064 std::string defaultStrategy("RootFitStrategy");
00065 e.sendToMrs(MRS_DIAGNOSTIC);
00066 internal_setFitStrategy(defaultStrategy);
00067 }
00068 workergroup = new FitterWorkerGroup();
00069 workergroup->reportTo(m_args.getISStatusName());
00070 updateSubscriptions();
00071 useAnalyticAlgorithm(m_args.analytic());
00072 internal_setFitOptions(m_args.getFitOptions());
00073 }
00074
00075 Fitter::~Fitter() throw() {}
00076
00077
00078 std::string Fitter::getOutputIsServer() const{
00079 return m_args.getOutputISServer();
00080 }
00081
00082 IPCServer& Fitter::getFitterServer() throw() {
00083 static IPCServer fitterServer;
00084 return fitterServer;
00085 }
00086
00087
00088
00089 void Fitter::go() throw(IsException) {
00090 workergroup->go(m_args.getNWorkers());
00091 if (m_args.recoveryMode()) fitAll();
00092 }
00093
00094 void Fitter::updateSubscriptions(){
00095 if (workergroup) workergroup->setPaused(true);
00096 recursive_mutex::scoped_lock scoped_lock(counterMutex);
00097
00098 const std::list<SctService::Arguments::Subscription>& input=m_args.getInputISServers();
00099 for (std::list<SctService::Arguments::Subscription>::const_iterator i=input.begin();
00100 i!=input.end(); ++i){
00101 try{
00102 ISInfo::Status s=m_infoReceiver->subscribe((*i).server.c_str(),
00103 (*i).regexp.c_str(), doFits);
00104 if (s!=ISInfo::Success) {
00105 ostringstream os;
00106 os <<"Fitter Could not subscribe to IS server ["<<(*i).server
00107 <<"] with regexp [" << (*i).regexp << "]";
00108 IsException(s, os.str(), __FILE__, __LINE__).sendToMrs();
00109 }else{
00110 ostringstream os;
00111 os <<"Fitter subscribed to IS server [" << (*i).server
00112 <<"] with regexp [" << (*i).regexp << "]";
00113 Sct::SctNames::Mrs() << "FIT_SUBSCRIBE" << MRS_TEXT(os.str()) << MRS_INFORMATION << ENDM;
00114 }
00115 }catch(Throwable & e){
00116 e.sendToMrs();
00117 }catch(std::exception & e){
00118 Sct::StdExceptionWrapper(e, __FILE__, __LINE__).sendToMrs();
00119 }
00120 }
00121 if (workergroup) workergroup->setPaused(false);
00122 }
00123
00124
00125 void Fitter::doFits(ISCallbackInfo * isc) throw(IsException, LogicError) {
00126
00127 if (isc->reason() != ISInfoCreated && isc->reason() != ISInfoUpdated )
00128 return;
00129
00130
00131 Fitter::instance().workergroup->push(isc->name());
00132 }
00133
00134
00135 void Fitter::fit(const char* name) throw() {
00136
00137 workergroup->push(name);
00138 }
00139
00140
00141 void Fitter::fitAll() throw() {
00142 std::list<string> alreadyDone;
00143 {
00144 ISInfoIterator iter(SctNames::getPartition(), getOutputIsServer(), "SctData::FitScanResult.*");
00145 while (iter()) {
00146 Sct::IS::IONameIS name(iter.name());
00147 alreadyDone.push_back(name.getUniqueID());
00148 }
00149 }
00150
00151 const std::list<SctService::Arguments::Subscription>& input=m_args.getInputISServers();
00152 unsigned nToRecover=0;
00153 for (std::list<SctService::Arguments::Subscription>::const_iterator i=input.begin(); i!=input.end(); ++i){
00154 ISInfoIterator iter(SctNames::getPartition(), (*i).server.c_str(),
00155 (*i).regexp.c_str());
00156 while (iter()) {
00157 Sct::IS::IONameIS name(iter.name());
00158 std::string id=name.getUniqueID();
00159 if (std::find(alreadyDone.begin(), alreadyDone.end(), id)==alreadyDone.end()){
00160 nToRecover++;
00161 workergroup->push(iter.name());
00162 }
00163 }
00164 }
00165 std::ostringstream msg;
00166 msg << "Need to fit total of " << nToRecover << " objects";
00167 SctNames::Mrs() << "FITTING_RECOVERY" << MRS_TEXT(msg.str()) << MRS_DIAGNOSTIC << ENDM;
00168 }
00169
00170
00171 char* Fitter::getFitOptions() throw() {
00172 recursive_mutex::scoped_lock scoped_lock(counterMutex);
00173 string options = "";
00174 try {
00175 options = internal_getFitStrategy().getOptions();
00176 } catch (LogicError &e) {
00177
00178 }
00179 char *newOpt=new char[options.length()+1];
00180 strcpy(newOpt, options.c_str());
00181 return newOpt;
00182 }
00183
00184
00185 char* Fitter::status() throw() {
00186 recursive_mutex::scoped_lock scoped_lock(counterMutex);
00187
00188 string msg = internal_status();
00189 char *statusMessage = new char[msg.length()+1];
00190 strcpy(statusMessage, msg.c_str());
00191 return statusMessage;
00192 }
00193
00194 void Fitter::internal_setFitOptions(const string & opt) throw (LogicError) {
00195 recursive_mutex::scoped_lock scoped_lock(counterMutex);
00196 internal_getFitStrategy().setOptions(opt);
00197 }
00198
00199
00200 void Fitter::setFitOptions(const char *n) throw() {
00201 recursive_mutex::scoped_lock scoped_lock(counterMutex);
00202 string name( n );
00203 try {
00204 internal_setFitOptions(name);
00205 } catch (LogicError &e) {
00206 return;
00207 }
00208 }
00209
00210
00211 void Fitter::useAnalyticAlgorithm (CORBA::Boolean use) {
00212 if (use) {
00213 ThresholdFitAlgorithm2::putInMap();
00214 } else {
00215 ThresholdFitAlgorithm::putInMap();
00216 }
00217 }
00218
00219 bool Fitter::internal_isUsingAnalyticAlgorithm() const {
00220 recursive_mutex::scoped_lock scoped_lock(counterMutex);
00221 return ThresholdFitAlgorithm2::isInMap();
00222 }
00223
00224
00225 CORBA::Boolean Fitter::isUsingAnalyticAlgorithm() {
00226 recursive_mutex::scoped_lock scoped_lock(counterMutex);
00227 return internal_isUsingAnalyticAlgorithm();
00228 }
00229
00230 char* Fitter::getFitStrategy() throw() {
00231 recursive_mutex::scoped_lock scoped_lock(counterMutex);
00232 string strat;
00233 try {
00234 strat = internal_getFitStrategy().getName();
00235 } catch (LogicError &e) {
00236 e.sendToMrs();
00237 }
00238 char *newOpt=new char[strat.length()+1];
00239 strcpy(newOpt, strat.c_str());
00240 return newOpt;
00241 }
00242
00243
00244 void Fitter::setFitStrategy(const char *n) throw() {
00245 recursive_mutex::scoped_lock scoped_lock(counterMutex);
00246 string name( n );
00247 cout <<"trying to set fit strategy "<<name<<endl;
00248 try {
00249 internal_setFitStrategy(name);
00250 } catch (LogicError& e) {
00251 std::string message("failed to set fit strategy ");
00252 message += name;
00253 Sct::InvalidArgumentError(message, __FILE__, __LINE__).sendToMrs();
00254 return;
00255 }
00256 cout <<"set fit strategy "<<name<<endl;
00257 }
00258
00259 const char* Fitter::internal_status() const throw() {
00260 recursive_mutex::scoped_lock scoped_lock(counterMutex);
00261 string strategyName;
00262 try {
00263 strategyName=internal_getFitStrategy().getName();
00264 } catch (LogicError &e) {
00265 strategyName="NONE";
00266 }
00267 ostringstream oss;
00268 oss << m_args.print()<<endl;
00269 oss << "Current: \n\tStrategy=" << strategyName << endl
00270 << "\tOptions=" << internal_getFitStrategy().getOptions() << endl
00271 << "\tAnalytic fits=" << internal_isUsingAnalyticAlgorithm() << endl;
00272 oss << "\tWorkers=" << workergroup->nWorkers() << endl
00273 << "\t (Busy=" << workergroup->busy() << ")" << endl
00274 << "\tFits Done=" << internal_nFitsDone() << endl
00275 << "\tErrors=" << internal_nFitErrors() << endl
00276 << "\tScans Done=" << m_nScans << endl
00277 << "\tLast scan: " << internal_lastScan() << endl;
00278 oss << "\tQueue=" << workergroup->queueSize();
00279 if (workergroup->isFifo()){
00280 oss << " [FIFO]\n";
00281 }else{
00282 oss << " [FILO]\n";
00283 }
00284 oss << "Timing:"<<endl
00285 << "\tI/O time: " << m_ioTimeTaken << endl
00286 << "\tScan time: "<< m_scanTimeTaken << endl
00287 << "\tApprox average time/scan/thread: " << getAverageTimePerScan() << endl;
00288 m_status = oss.str();
00289 return m_status.c_str();
00290 }
00291
00292 void Fitter::incrementFitErrors() throw() {
00293 recursive_mutex::scoped_lock scoped_lock(counterMutex);
00294 ++m_nFitErrors;
00295 }
00296
00297 void Fitter::incrementFitsDone() throw() {
00298 recursive_mutex::scoped_lock scoped_lock(counterMutex);
00299 ++m_nFitsDone;
00300 }
00301
00302 void Fitter::scanDone(double time) throw() {
00303 recursive_mutex::scoped_lock scoped_lock(counterMutex);
00304 ++m_nScans;
00305 m_scanTimeTaken += time;
00306 }
00307
00308 void Fitter::addIOTime(double time) throw() {
00309 recursive_mutex::scoped_lock scoped_lock(counterMutex);
00310 m_ioTimeTaken += time;
00311 }
00312
00313
00314 double Fitter::getAverageTimePerScan() const throw() {
00315 recursive_mutex::scoped_lock scoped_lock(counterMutex);
00316 double time = (m_ioTimeTaken+m_scanTimeTaken)/workergroup->nWorkers();
00317 if (m_nScans > 0) time /= m_nScans;
00318 return time;
00319 }
00320
00321
00322 long Fitter::internal_nFitsDone() const throw() {
00323 recursive_mutex::scoped_lock scoped_lock(counterMutex);
00324 return m_nFitsDone;
00325 }
00326
00327 long Fitter::internal_nFitErrors() const throw() {
00328 recursive_mutex::scoped_lock scoped_lock(counterMutex);
00329 return m_nFitErrors;
00330 }
00331
00332
00333 long Fitter::nFitsDone() throw() {
00334 recursive_mutex::scoped_lock scoped_lock(counterMutex);
00335 return internal_nFitsDone();
00336 }
00337
00338
00339 long Fitter::nFitErrors() throw() {
00340 recursive_mutex::scoped_lock scoped_lock(counterMutex);
00341 return internal_nFitErrors();
00342 }
00343
00344
00345 long Fitter::queueLength() {
00346 recursive_mutex::scoped_lock scoped_lock(counterMutex);
00347 return workergroup->queueSize();
00348 }
00349
00350
00351 long Fitter::busy() {
00352 recursive_mutex::scoped_lock scoped_lock(counterMutex);
00353 return workergroup->busy();
00354 }
00355
00356 const char* Fitter::internal_lastScan() const throw() {
00357 recursive_mutex::scoped_lock scoped_lock(counterMutex);
00358 return m_scan.c_str();
00359 }
00360
00361
00362 char* Fitter::lastScan() throw() {
00363 recursive_mutex::scoped_lock scoped_lock(counterMutex);
00364 char * message = new char[m_scan.length()+1];
00365 strcpy(message, m_scan.c_str() );
00366 return message;
00367 }
00368
00369 bool Fitter::isFifo(){
00370 return workergroup->isFifo();
00371 }
00372
00373 void Fitter::setFifo(bool val){
00374 workergroup->setFifo(val);
00375 }
00376
00377 FitStrategy& Fitter::internal_getFitStrategy() const throw(LogicError) {
00378 recursive_mutex::scoped_lock scoped_lock(counterMutex);
00379 if (!m_fitStrategy)
00380 throw InvariantViolatedError("Fitter::getStrategy() no fit strategy defined", __FILE__, __LINE__);
00381 return *m_fitStrategy;
00382 }
00383
00384 void Fitter::internal_setFitStrategy(const string & name) throw(LogicError) {
00385 recursive_mutex::scoped_lock scoped_lock(counterMutex);
00386 m_fitStrategy = FitStrategyFactory::instance().getStrategy(name);
00387 SctNames::Mrs() << "FIT_STRATEGY" << MRS_TEXT(string("set fit strategy to ")+name)
00388 << MRS_INFORMATION << ENDM;
00389 }
00390
00391 }