Changeset 10741
- Timestamp:
- 05/18/11 16:00:41 (15 years ago)
- Location:
- trunk/FACT++/src
- Files:
-
- 3 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/FACT++/src/Fits.cc
r10725 r10741 35 35 //! @param numDataBytes the number of bytes taken by the variable 36 36 // 37 void Fits::AddStandardColumn(Description& desc, st d::string dataFormat, void* dataPointer, long unsigned int numDataBytes)37 void Fits::AddStandardColumn(Description& desc, string dataFormat, void* dataPointer, long unsigned int numDataBytes) 38 38 { 39 39 //check if entry already exist 40 for ( std::vector<Description>::iterator it=fStandardColDesc.begin(); it != fStandardColDesc.end(); it++)40 for (vector<Description>::iterator it=fStandardColDesc.begin(); it != fStandardColDesc.end(); it++) 41 41 if (it->name == desc.name) 42 42 return; … … 54 54 //! @param numDataBytes the number of bytes taken by the DIM data. 55 55 // 56 void Fits::InitDataColumns( std::vector<Description> desc, std::vector<std::string>& dataFormat, void* dataPointer, int numDataBytes)56 void Fits::InitDataColumns(vector<Description> desc, vector<string>& dataFormat, void* dataPointer, int numDataBytes) 57 57 {//we will copy this information here. It duplicates the data, which is not great, but it is the easiest way of doing it right now 58 58 if (desc.size() == dataFormat.size()) … … 65 65 for (unsigned int i=0;i<dataFormat.size();i++) 66 66 { 67 st d::stringstream stt;67 stringstream stt; 68 68 stt << "Data" << i; 69 69 fDataColDesc.push_back(Description(stt.str(), "comment", "unit")); … … 83 83 //! @param out a pointer to the MessageImp that should be used to log errors 84 84 // 85 void Fits::Open(const st d::string& fileName, const std::string& tableName, FITS* file, int* fitsCounter, MessageImp* out)//std::ostream& out)85 void Fits::Open(const string& fileName, const string& tableName, FITS* file, int* fitsCounter, MessageImp* out)//ostream& out) 86 86 { 87 87 // if (fMess) … … 98 98 catch (CCfits::FitsError e) 99 99 { 100 st d::stringstream str;100 stringstream str; 101 101 str << "Could not open FITS file " << fileName << " reason: " << e.message(); 102 102 fMess->Error(str); … … 115 115 //concatenate the standard and data columns 116 116 //do it the inneficient way first: its easier and faster to code. 117 std::vector<std::string> allNames;118 std::vector<std::string> allDataTypes;119 std::vector<std::string> allUnits;117 vector<string> allNames; 118 vector<string> allDataTypes; 119 vector<string> allUnits; 120 120 fTotalNumBytes = 0; 121 121 for (unsigned int i=0;i<fStandardColDesc.size();i++) … … 133 133 else 134 134 { 135 st d::stringstream stt;135 stringstream stt; 136 136 stt << "Data" << i; 137 137 allNames.push_back(stt.str()); … … 145 145 try 146 146 { 147 st d::string factTableName = "FACT-" + tableName;147 string factTableName = "FACT-" + tableName; 148 148 fTable = fFile->addTable(factTableName, 0, allNames, allDataTypes, allUnits); 149 149 fTable->makeThisCurrent(); … … 159 159 } 160 160 //read the table binary data. 161 std::vector<string> colName;161 vector<string> colName; 162 162 bTable->readData(true, colName); 163 163 164 164 //double check that the data was indeed read from the disk. Go through the fTable instead as colName is empty (yes, it is !) 165 std::map<std::string, Column*> cMap = fTable->column();166 std::map<std::string, Column*>::iterator cMapIt;165 map<string, Column*> cMap = fTable->column(); 166 map<string, Column*>::iterator cMapIt; 167 167 168 168 for (cMapIt = cMap.begin(); cMapIt != cMap.end(); cMapIt++) … … 179 179 catch(CCfits::FitsError e) 180 180 { 181 st d::stringstream str;181 stringstream str; 182 182 str << "Could not open or create FITS table " << tableName << " in file " << fileName << " reason: " << e.message(); 183 183 fMess->Error(str); … … 190 190 WriteHeaderKeys(); 191 191 } 192 // -------------------------------------------------------------------------- 193 // 194 //!This writes a single header key in the currently open file. 195 //!@param name the key 196 //!@param value the key value 197 //!@param a comment explaining the meaning of the key 192 198 template <typename T> 193 199 void Fits::WriteSingleHeaderKey(string name, T value, string comment) … … 199 205 catch (CCfits::FitsError e) 200 206 { 201 st d::stringstream str;207 stringstream str; 202 208 str << "Could not add header keys in file " << fFileName << " reason: " << e.message(); 203 209 fMess->Error(str); … … 212 218 if (!fTable) 213 219 return; 214 std::string name; 215 std::string comment; 216 217 // float floatValue; 218 // double doubleValue; 219 std::string stringValue; 220 string name; 221 string comment; 222 223 string stringValue; 220 224 221 225 WriteSingleHeaderKey("EXTREL", 1.0f, "Release Number"); … … 230 234 WriteSingleHeaderKey("TIMEREF", "UTC", "Time reference frame"); 231 235 WriteSingleHeaderKey("MJDREF", fRefMjD, "Modified Julian Date of origin"); 236 WriteSingleHeaderKey("TSTOP", fEndMjD, "Time of the last receied data"); 232 237 } 233 238 // -------------------------------------------------------------------------- … … 239 244 { 240 245 241 // try242 // {243 246 fTable->makeThisCurrent(); 244 247 int status(0); 245 248 if (fits_insert_rows(fTable->fitsPointer(), fNumRows, 1, &status)) 246 249 { 247 st d::stringstream str;250 stringstream str; 248 251 str << "Could not insert row in file " << fFileName << ". cfitsio error code: " << status; 249 252 fMess->Error(str); 250 253 } 251 // fTable->insertRows(fNumRows);252 // }253 // catch(CCfits::FitsError e)254 // {255 // std::stringstream str;256 // str << "Could not insert row in file " << fFileName << " reason: " << e.message();257 // fMess->Error(str);258 // }259 254 fNumRows++; 260 255 … … 273 268 { 274 269 const char * charSrc = static_cast<char*>(fStandardPointers[i]); 275 276 270 reverse_copy(charSrc, charSrc+fStandardNumBytes[i], &fCopyBuffer[shift]); 277 // for (int j=0; j<fStandardNumBytes[i]; j++)278 // fCopyBuffer[shift+j] = static_cast<char*>(fStandardPointers[i])[fStandardNumBytes[i]-(j+1)];279 271 shift+= fStandardNumBytes[i]; 280 272 } … … 284 276 285 277 //data copied to buffer, can write to fits 286 // int status = 0;287 //TODO check the status after the write operation288 278 fits_write_tblbytes(fFile->fitsPointer(), fNumRows, 1, fTotalNumBytes, fCopyBuffer, &status); 289 279 if (status) … … 291 281 char text[30];//max length of cfitsio error strings (from doc) 292 282 fits_get_errstatus(status, text); 293 st d::stringstream str;283 stringstream str; 294 284 str << "Error while writing FITS row in " << fFileName << ". Message: " << text << " [" << status << "]"; 295 285 fMess->Error(str); 296 286 } 297 //This forces the writting of each row to the disk. Otherwise all rows are written when the file is closed. 298 ///TODO check whether this consumes too much resources or not. If it does, flush every N write operations instead 299 /* try 300 { 301 fFile->flush(); 302 } 303 catch (CCfits::FitsError e) 304 { 305 std::stringstream str; 306 str << "Error while flushing bytes to disk. File: " << fFileName << " reason: " << e.message(); 307 fMess->Error(str); 308 } 309 */} 287 } 310 288 // -------------------------------------------------------------------------- 311 289 // … … 335 313 336 314 // -------------------------------------------------------------------------- 337 // 315 //! Returns the size on the disk of the Fits file being written. 338 316 int Fits::GetWrittenSize() 339 317 { -
trunk/FACT++/src/Fits.h
r10725 r10741 10 10 class MessageImp; 11 11 12 using namespace std; 13 12 14 class Fits 13 15 { 14 16 private: 15 17 ///The CCfits object to the FITS file 16 CCfits::FITS* fFile;18 CCfits::FITS* fFile; 17 19 ///Flag indicating whether the FITS object should be managed internally or not. 18 20 bool fOwner; … … 24 26 ///TODO make these variable static so that they are shared by every object. 25 27 ///TODO add also a static boolean to initialize these only once 26 std::vector<Description> fStandardColDesc;28 vector<Description> fStandardColDesc; 27 29 ///Format of the standard columns. 28 std::vector<std::string> fStandardFormats;30 vector<string> fStandardFormats; 29 31 ///the pointers to the standard variables 30 std::vector<void*> fStandardPointers;32 vector<void*> fStandardPointers; 31 33 ///the number of bytes taken by each standard variable 32 std::vector<int> fStandardNumBytes;34 vector<int> fStandardNumBytes; 33 35 ///the vector of data column names 34 std::vector<Description> fDataColDesc;36 vector<Description> fDataColDesc; 35 37 ///the data format of the data columns 36 std::vector<std::string> fDataFormats;38 vector<string> fDataFormats; 37 39 ///the pointer to the contiguous memory location where the data is stored (i.e. the dim data pointer) 38 40 void* fDataPointer; … … 51 53 public: 52 54 ///Name of the openned file. For querying stats 53 st d::string fFileName;55 string fFileName; 54 56 private: 55 57 ///Keep track of number of opened fits … … 83 85 84 86 ///Adds a column that exists in all FITS files 85 void AddStandardColumn(Description& desc, st d::string dataFormat, void* dataPointer, long unsigned int numDataBytes);87 void AddStandardColumn(Description& desc, string dataFormat, void* dataPointer, long unsigned int numDataBytes); 86 88 87 89 ///Adds columns specific to the service being logged. 88 void InitDataColumns( std::vector<Description> desc, std::vector<std::string>& dataFormat, void* dataPointer, int numDataBytes);90 void InitDataColumns(vector<Description> desc, vector<string>& dataFormat, void* dataPointer, int numDataBytes); 89 91 90 92 ///Opens a FITS file 91 void Open(const st d::string& fileName, const std::string& tableName, CCfits::FITS* file, int* fitsCounter, MessageImp* out);//std::ostream& out);93 void Open(const string& fileName, const string& tableName, CCfits::FITS* file, int* fitsCounter, MessageImp* out);//ostream& out); 92 94 93 95 ///Write one line of data. Use the given converter. -
trunk/FACT++/src/dataLogger.cc
r10739 r10741 11 11 \dot 12 12 digraph datalogger { 13 node [shape=record, fontname=Helvetica, fontsize=10];14 e [label="Error" color="red"];13 node [shape=record, fontname=Helvetica, fontsize=10]; 14 e [label="Error" color="red"]; 15 15 r [label="Ready"] 16 16 d [label="NightlyOpen"] 17 17 w [label="WaitingRun"] 18 l [label="Logging"]18 l [label="Logging"] 19 19 b [label="BadNightlyconfig" color="red"] 20 20 c [label="BadRunConfig" color="red"] … … 37 37 } 38 38 \enddot 39 40 @todo41 - Retrieve also the messages, not only the infos42 39 */ 43 40 //**************************************************************** … … 82 79 //Dim structures 83 80 struct DataLoggerStats { 84 long sizeWritten;85 long freeSpace;86 long writingRate;81 long sizeWritten; 82 long freeSpace; 83 long writingRate; 87 84 }; 88 85 89 86 struct NumSubAndFitsType { 90 int numSubscriptions;91 int numOpenFits;87 int numSubscriptions; 88 int numOpenFits; 92 89 }; 93 90 94 91 struct OpenFileToDim { 95 int code;96 char fileName[FILENAME_MAX];92 int code; 93 char fileName[FILENAME_MAX]; 97 94 }; 98 //For debugging DIM's services 99 class MyService95 96 class DataLogger : public StateMachineDim, DimInfoHandler 100 97 { 101 98 public: 102 MyService(){}; 103 MyService(std::string, std::string, void*, int){}; 104 MyService(std::string, const char*){}; 105 void updateService(){}; 106 void updateService(void*, int){}; 107 void setQuality(int){}; 108 }; 109 class DataLogger : public StateMachineDim, DimInfoHandler 110 { 99 /// The list of existing states specific to the DataLogger 100 enum 101 { 102 kSM_NightlyOpen = 20, ///< Nightly file openned and writing 103 kSM_WaitingRun = 30, ///< waiting for the run number to open the run file 104 kSM_Logging = 40, ///< both files openned and writing 105 kSM_BadNightlyConfig = 0x101, ///< the folder specified for Nightly logging does not exist or has bad permissions 106 kSM_BadRunConfig = 0x102, ///< the folder specified for the run logging does not exist or has wrong permissions or no run number 107 } localstates_t; 108 109 DataLogger(ostream &out); 110 ~DataLogger(); 111 112 private: 113 //Define all the data structure specific to the DataLogger here 114 /// ofstream for the NightlyLogfile 115 ofstream fNightlyLogFile; 116 /// ofstream for the run-specific Log file 117 ofstream fRunLogFile; 118 119 /// ofstream for the Nightly report file 120 ofstream fNightlyReportFile; 121 /// ofstream for the run-specific report file 122 ofstream fRunReportFile; 123 /// base path of the Nightlyfile 124 string fNightlyFileName; 125 ///base path of the run file 126 string fRunFileName; 127 ///run number (-1 means no run number specified) 128 int fRunNumber; 129 ///previous run number. to check if changed while logging 130 int fPreviousRunNumber; 131 ///Current Service Quality 132 int fQuality; 133 ///Modified Julian Date 134 double fMjD; 111 135 public: 112 /// The list of existing states specific to the DataLogger 113 enum 114 { 115 kSM_NightlyOpen = 20, ///< Nightly file openned and writing 116 kSM_WaitingRun = 30, ///< waiting for the run number to open the run file 117 kSM_Logging = 40, ///< both files openned and writing 118 kSM_BadNightlyConfig = 0x101, ///< the folder specified for Nightly logging does not exist or has bad permissions 119 kSM_BadRunConfig = 0x102, ///< the folder specified for the run logging does not exist or has wrong permissions or no run number 120 } localstates_t; 121 122 DataLogger(std::ostream &out); 123 ~DataLogger(); 124 136 ///Define all the static names 137 static const char* fConfigDay; 138 static const char* fConfigRun; 139 static const char* fConfigRunNumber; 140 static const char* fConfigLog; 141 static const char* fTransStart; 142 static const char* fTransStop; 143 static const char* fTransStartRun; 144 static const char* fTransStopRun; 145 static const char* fTransReset; 146 static const char* fTransWait; 147 static const char* fRunNumberInfo; ///< This is the name of the dimInfo received to specify the run number. It must be updated once the final name will be defined 148 static const char* fPrintCommand; 149 static const char* fDebugOnOff; 150 static const char* fStatsPeriod; 151 static const char* fStartStopOpenedFiles; 152 static const char* fStartStopNumSubsAndFits; 125 153 private: 126 //Define all the data structure specific to the DataLogger here 127 /// ofstream for the NightlyLogfile 128 std::ofstream fNightlyLogFile; 129 /// ofstream for the run-specific Log file 130 std::ofstream fRunLogFile; 131 132 /// ofstream for the Nightly report file 133 std::ofstream fNightlyReportFile; 134 /// ofstream for the run-specific report file 135 std::ofstream fRunReportFile; 136 /// base path of the Nightlyfile 137 std::string fNightlyFileName; 138 ///base path of the run file 139 std::string fRunFileName; 140 ///run number (-1 means no run number specified) 141 int fRunNumber; 142 ///previous run number. to check if changed while logging 143 int fPreviousRunNumber; 144 ///Current Service Quality 145 int fQuality; 146 ///Modified Julian Date 147 double fMjD; 148 public: 149 ///Define all the static names 150 static const char* fConfigDay; 151 static const char* fConfigRun; 152 static const char* fConfigRunNumber; 153 static const char* fConfigLog; 154 static const char* fTransStart; 155 static const char* fTransStop; 156 static const char* fTransStartRun; 157 static const char* fTransStopRun; 158 static const char* fTransReset; 159 static const char* fTransWait; 160 static const char* fRunNumberInfo; ///< This is the name of the dimInfo received to specify the run number. It must be updated once the final name will be defined 161 static const char* fPrintCommand; 162 static const char* fDebugOnOff; 163 static const char* fStatsPeriod; 164 static const char* fStartStopOpenedFiles; 165 static const char* fStartStopNumSubsAndFits; 154 //overloading of DIM's infoHandler function 155 void infoHandler(); 156 157 ///for obtaining the name of the existing services 158 ServiceList fServiceList; 159 160 ///A std pair to store both the DimInfo pointer and the corresponding outputted fits file 161 struct SubscriptionType 162 { 163 #ifdef HAVE_FITS 164 ///Nightly FITS output file 165 Fits nightlyFile; 166 ///run-specific FITS output file 167 Fits runFile; 168 #endif 169 ///the actual dimInfo pointer 170 DimStampedInfo* dimInfo; 171 ///the converter for outputting the data according to the format 172 Converter* fConv; 173 ///the number of existing handlers to this structure. 174 ///This is required otherwise I MUST handle the deleting of dimInfo outside from the destructor 175 int* numCopies; 176 void operator = (const SubscriptionType& other) 177 { 178 #ifdef HAVE_FITS 179 nightlyFile = other.nightlyFile; 180 runFile = other.runFile; 181 #endif 182 dimInfo = other.dimInfo; 183 numCopies = other.numCopies; 184 fConv = other.fConv; 185 (*numCopies)++; 186 } 187 SubscriptionType(const SubscriptionType& other) 188 { 189 #ifdef HAVE_FITS 190 nightlyFile = other.nightlyFile; 191 runFile = other.runFile; 192 #endif 193 dimInfo = other.dimInfo; 194 numCopies = other.numCopies; 195 fConv = other.fConv; 196 (*numCopies)++; 197 } 198 SubscriptionType(DimStampedInfo* info) 199 { 200 dimInfo = info; 201 fConv = NULL; 202 numCopies = new int(1); 203 } 204 SubscriptionType() 205 { 206 dimInfo = NULL; 207 fConv = NULL; 208 numCopies = new int(1); 209 } 210 ~SubscriptionType() 211 { 212 if (numCopies) 213 (*numCopies)--; 214 if (numCopies) 215 if (*numCopies < 1) 216 { 217 if (dimInfo) 218 delete dimInfo; 219 #ifdef HAVE_FITS 220 if (nightlyFile.IsOpen()) 221 nightlyFile.Close(); 222 if (runFile.IsOpen()) 223 runFile.Close(); 224 #endif 225 if (numCopies) 226 delete numCopies; 227 delete fConv; 228 fConv = NULL; 229 dimInfo = NULL; 230 numCopies = NULL; 231 } 232 } 233 }; 234 typedef map<const string, map<string, SubscriptionType> > SubscriptionsListType; 235 ///All the services to which we have subscribed to, sorted by server name. 236 SubscriptionsListType fServiceSubscriptions; 237 238 ///Reporting method for the services info received 239 void ReportPlease(DimInfo* I, SubscriptionType& sub); 240 241 ///Configuration of the nightly file path 242 int ConfigureNightlyFileName(const Event& evt); 243 ///Configuration fo the file name 244 int ConfigureRunFileName(const Event& evt); 245 ///DEPREC - configuration of the run number 246 int ConfigureRunNumber(const Event& evt); 247 ///logging method for the messages 248 int LogMessagePlease(const Event& evt); 249 ///print the current state of the dataLogger 250 int PrintStatePlease(const Event& evt); 251 ///checks whether or not the current info being treated is a run number 252 void CheckForRunNumber(DimInfo* I); 253 /// start transition 254 int StartPlease(); 255 ///from waiting to logging transition 256 int StartRunPlease(); 257 /// from logging to waiting transition 258 int StopRunPlease(); 259 ///stop and reset transition 260 int GoToReadyPlease(); 261 ///from NightlyOpen to waiting transition 262 int NightlyToWaitRunPlease(); 263 #ifdef HAVE_FITS 264 ///Open fits files 265 void OpenFITSFilesPlease(SubscriptionType& sub); 266 ///Write data to FITS files 267 void WriteToFITS(SubscriptionType& sub); 268 ///Allocate the buffers required for fits 269 void AllocateFITSBuffers(SubscriptionType& sub); 270 ///FITS file for runs grouping. only one, hence dealt with in the dataLogger itself 271 CCfits::FITS* fRunFitsFile; 272 #endif//has_fits 273 public: 274 ///checks with fServiceList whether or not the services got updated 275 bool CheckForServicesUpdate(); 276 277 private: 278 ///monitoring notification loop 279 void ServicesMonitoring(); 280 ///services notification thread 281 boost::thread fMonitoringThread; 282 ///end of the monitoring 283 bool fContinueMonitoring; 284 ///required for accurate monitoring 285 map<string, long> fFileSizesMap; 286 string fFullNightlyLogFileName; 287 string fFullNightlyReportFileName; 288 string fFullRunLogFileName; 289 string fFullRunReportFileName; 290 long fBaseSizeNightly; 291 long fPreviousSize; 292 long fBaseSizeRun; 293 ///Service for opened files 294 DimDescribedService* fOpenedNightlyFiles; 295 DimDescribedService* fOpenedRunFiles; 296 DimDescribedService* fNumSubAndFits; 297 NumSubAndFitsType fNumSubAndFitsData; 298 299 inline void NotifyOpenedFile(string name, int type, DimDescribedService* service); 300 301 public: 302 bool SetConfiguration(Configuration& conf); 303 166 304 private: 167 //overloading of DIM's infoHandler function 168 void infoHandler(); 169 170 ///for obtaining the name of the existing services 171 ServiceList fServiceList; 172 173 ///A std pair to store both the DimInfo pointer and the corresponding outputted fits file 174 struct SubscriptionType 175 { 305 set<string> fBlackList; 306 set<string> fWhiteList; 307 set<string> fGrouping; 308 bool fHasBlackList; 309 bool fHasWhiteList; 310 bool fDebugIsOn; 311 float fStatsPeriodDuration; 312 bool fOpenedFilesIsOn; 313 bool fNumSubAndFitsIsOn; 314 //functions for controlling the services behavior 315 int SetDebugOnOff(const Event& evt); 316 int SetStatsPeriod(const Event& evt); 317 int SetOpenedFilesOnOff(const Event& evt); 318 int SetNumSubsAndFitsOnOff(const Event& evt); 319 ///boolean to prevent DIM update while desctructing the dataLogger 320 bool fDestructing; 321 322 ///Small function for calculating the total size written so far 323 void calculateTotalSizeWritten(DataLoggerStats& statVar, bool& shouldWarn, bool isPrinting); 324 325 ///vectors to keep track of opened Fits files, for grouping purposes. 326 //This cannot be done otherwise, as services may disapear before the files are nicely closed. Hence which files were opened must be remembered. 327 map<string, vector<string> > fOpenedRunFits; 328 map<string, vector<string> > fOpenedNightlyFits; 329 void CreateFitsGrouping(bool runGroup); 330 }; //DataLogger 331 332 void DataLogger::calculateTotalSizeWritten(DataLoggerStats& statVar, bool& shouldWarn, bool isPrinting) 333 { 176 334 #ifdef HAVE_FITS 177 ///Nightly FITS output file 178 Fits nightlyFile; 179 ///run-specific FITS output file 180 Fits runFile; 335 if (isPrinting) 336 { 337 stringstream str; 338 str.str(""); 339 str << "There are " << fNumSubAndFitsData.numOpenFits << " FITS files open:"; 340 Message(str.str()); 341 } 342 SubscriptionsListType::iterator x; 343 map<string, SubscriptionType>::iterator y; 344 ///TODO the grouping file is dealt with several times. This should not be a problem but well, better to fix it I guess. 345 for (x=fServiceSubscriptions.begin(); x != fServiceSubscriptions.end(); x++) 346 { 347 for (y=x->second.begin(); y != x->second.end(); y++) 348 { 349 if (y->second.runFile.IsOpen()) 350 { 351 fFileSizesMap[y->second.runFile.fFileName] = y->second.runFile.GetWrittenSize(); 352 if (isPrinting) 353 Message("-> "+y->second.runFile.fFileName); 354 } 355 if (y->second.nightlyFile.IsOpen()) 356 { 357 fFileSizesMap[y->second.nightlyFile.fFileName] = y->second.nightlyFile.GetWrittenSize(); 358 if (isPrinting) 359 Message("-> "+y->second.nightlyFile.fFileName); 360 } 361 } 362 } 363 #else 364 if (isPrinting) 365 Message("FITS output disabled at compilation"); 181 366 #endif 182 ///the actual dimInfo pointer 183 DimStampedInfo* dimInfo; 184 ///the converter for outputting the data according to the format 185 Converter* fConv; 186 ///the number of existing handlers to this structure. 187 ///This is required otherwise I MUST handle the deleting of dimInfo outside from the destructor 188 int* numCopies; 189 void operator = (const SubscriptionType& other) 190 { 191 #ifdef HAVE_FITS 192 nightlyFile = other.nightlyFile; 193 runFile = other.runFile; 194 #endif 195 dimInfo = other.dimInfo; 196 numCopies = other.numCopies; 197 fConv = other.fConv; 198 (*numCopies)++; 199 } 200 SubscriptionType(const SubscriptionType& other) 201 { 202 #ifdef HAVE_FITS 203 nightlyFile = other.nightlyFile; 204 runFile = other.runFile; 205 #endif 206 dimInfo = other.dimInfo; 207 numCopies = other.numCopies; 208 fConv = other.fConv; 209 (*numCopies)++; 210 } 211 SubscriptionType(DimStampedInfo* info) 212 { 213 dimInfo = info; 214 fConv = NULL; 215 numCopies = new int(1); 216 } 217 SubscriptionType() 218 { 219 dimInfo = NULL; 220 fConv = NULL; 221 numCopies = new int(1); 222 } 223 ~SubscriptionType() 224 { 225 if (numCopies) 226 (*numCopies)--; 227 if (numCopies) 228 if (*numCopies < 1) 229 { 230 if (dimInfo) 231 delete dimInfo; 232 #ifdef HAVE_FITS 233 if (nightlyFile.IsOpen()) 234 nightlyFile.Close(); 235 if (runFile.IsOpen()) 236 runFile.Close(); 237 #endif 238 if (numCopies) 239 delete numCopies; 240 delete fConv; 241 fConv = NULL; 242 dimInfo = NULL; 243 numCopies = NULL; 244 } 245 } 246 }; 247 typedef std::map<const std::string, std::map<std::string, SubscriptionType>> SubscriptionsListType; 248 ///All the services to which we have subscribed to, sorted by server name. 249 SubscriptionsListType fServiceSubscriptions; 250 251 ///Reporting method for the services info received 252 void ReportPlease(DimInfo* I, SubscriptionType& sub); 253 254 ///Configuration of the nightly file path 255 int ConfigureNightlyFileName(const Event& evt); 256 ///Configuration fo the file name 257 int ConfigureRunFileName(const Event& evt); 258 ///DEPREC - configuration of the run number 259 int ConfigureRunNumber(const Event& evt); 260 ///logging method for the messages 261 int LogMessagePlease(const Event& evt); 262 ///print the current state of the dataLogger 263 int PrintStatePlease(const Event& evt); 264 ///checks whether or not the current info being treated is a run number 265 void CheckForRunNumber(DimInfo* I); 266 /// start transition 267 int StartPlease(); 268 ///from waiting to logging transition 269 int StartRunPlease(); 270 /// from logging to waiting transition 271 int StopRunPlease(); 272 ///stop and reset transition 273 int GoToReadyPlease(); 274 ///from NightlyOpen to waiting transition 275 int NightlyToWaitRunPlease(); 276 #ifdef HAVE_FITS 277 ///Open fits files 278 void OpenFITSFilesPlease(SubscriptionType& sub); 279 ///Write data to FITS files 280 void WriteToFITS(SubscriptionType& sub); 281 ///Allocate the buffers required for fits 282 void AllocateFITSBuffers(SubscriptionType& sub); 283 284 #ifdef ONE_RUN_FITS_ONLY 285 ///FITS file for runs. only one, hence dealt with in the dataLogger itself 286 CCfits::FITS* fRunFitsFile; 287 #endif //one_run_fits_only 288 #endif//has_fits 289 public: 290 ///checks with fServiceList whether or not the services got updated 291 bool CheckForServicesUpdate(); 292 293 private: 294 ///monitoring notification loop 295 void ServicesMonitoring(); 296 ///services notification thread 297 boost::thread fMonitoringThread; 298 ///end of the monitoring 299 bool fContinueMonitoring; 300 ///required for accurate monitoring 301 std::map<std::string, long> fFileSizesMap; 302 std::string fFullNightlyLogFileName; 303 std::string fFullNightlyReportFileName; 304 std::string fFullRunLogFileName; 305 std::string fFullRunReportFileName; 306 long fBaseSizeNightly; 307 long fPreviousSize; 308 long fBaseSizeRun; 309 ///Service for opened files 310 DimDescribedService* fOpenedNightlyFiles; 311 DimDescribedService* fOpenedRunFiles; 312 DimDescribedService* fNumSubAndFits; 313 NumSubAndFitsType fNumSubAndFitsData; 314 315 inline void NotifyOpenedFile(std::string name, int type, DimDescribedService* service); 316 317 public: 318 bool SetConfiguration(Configuration& conf); 319 320 private: 321 std::set<std::string> fBlackList; 322 std::set<std::string> fWhiteList; 323 bool fHasBlackList; 324 bool fHasWhiteList; 325 bool fDebugIsOn; 326 float fStatsPeriodDuration; 327 bool fOpenedFilesIsOn; 328 bool fNumSubAndFitsIsOn; 329 //functions for controlling the services behavior 330 int SetDebugOnOff(const Event& evt); 331 int SetStatsPeriod(const Event& evt); 332 int SetOpenedFilesOnOff(const Event& evt); 333 int SetNumSubsAndFitsOnOff(const Event& evt); 334 ///boolean to prevent DIM update while desctructing the dataLogger 335 bool fDestructing; 336 337 ///Small function for calculating the total size written so far 338 void calculateTotalSizeWritten(DataLoggerStats& statVar, bool& shouldWarn, bool isPrinting); 339 340 ///vectors to keep track of opened Fits files, for grouping purposes. 341 //This cannot be done otherwise, as services may disapear before the files are nicely closed. Hence which files were opened must be remembered. 342 map<string, string> fOpenedRunFits; 343 map<string, string> fOpenedNightlyFits; 344 void CreateFitsGrouping(bool runGroup); 345 }; //DataLogger 346 347 void DataLogger::calculateTotalSizeWritten(DataLoggerStats& statVar, bool& shouldWarn, bool isPrinting) 348 { 349 #ifdef HAVE_FITS 350 if (isPrinting) 351 { 352 stringstream str; 353 str.str(""); 354 str << "There are " << fNumSubAndFitsData.numOpenFits << " FITS files open:"; 355 Message(str.str()); 356 } 357 SubscriptionsListType::iterator x; 358 std::map<std::string, SubscriptionType>::iterator y; 359 bool runFileDone = false; 360 for (x=fServiceSubscriptions.begin(); x != fServiceSubscriptions.end(); x++) 361 { 362 for (y=x->second.begin(); y != x->second.end(); y++) 363 { 364 if (y->second.runFile.IsOpen() && !runFileDone) 365 { 366 fFileSizesMap[y->second.runFile.fFileName] = y->second.runFile.GetWrittenSize(); 367 if (isPrinting) 368 Message("-> "+y->second.runFile.fFileName); 369 #ifdef ONE_FITS_ONLY 370 runFileDone = true; 371 #endif 372 } 373 if (y->second.nightlyFile.IsOpen()) 374 { 375 fFileSizesMap[y->second.nightlyFile.fFileName] = y->second.nightlyFile.GetWrittenSize(); 376 if (isPrinting) 377 Message("-> "+y->second.nightlyFile.fFileName); 378 } 379 } 380 } 381 #else 382 if (isPrinting) 383 Message("FITS output disabled at compilation"); 384 #endif 385 struct stat st; 386 //gather log and report files sizes on disk 387 if (fNightlyLogFile.is_open()) 388 { 389 stat(fFullNightlyLogFileName.c_str(), &st); 390 fFileSizesMap[fFullNightlyLogFileName] = st.st_size; 391 } 392 if (fNightlyReportFile.is_open()) 393 { 394 stat(fFullNightlyReportFileName.c_str(), &st); 395 fFileSizesMap[fFullNightlyReportFileName] = st.st_size; 396 } 397 if (fRunLogFile.is_open()) 398 { 399 stat(fFullRunLogFileName.c_str(), &st); 400 fFileSizesMap[fFullRunLogFileName] = st.st_size; 401 } 402 if (fRunReportFile.is_open()) 403 { 404 stat(fFullRunReportFileName.c_str(), &st); 405 fFileSizesMap[fFullRunReportFileName] = st.st_size; 406 } 407 struct statvfs vfs; 408 if (!statvfs(fNightlyFileName.c_str(), &vfs)) 409 { 410 statVar.freeSpace = vfs.f_bsize*vfs.f_bavail; 411 shouldWarn = false; 412 } 413 else 414 { 415 stringstream str; 416 str.str(""); 417 str << "Unable to retrieve stats for " << fNightlyFileName << ". Reason: " << strerror(errno) << " [" << errno << "]"; 418 if (!shouldWarn) 419 Error(str); 420 shouldWarn = true; 421 statVar.freeSpace = -1; 422 } 423 //sum up all the file sizes. past and present 424 statVar.sizeWritten = 0; 425 for (std::map<std::string, long>::iterator it=fFileSizesMap.begin(); it != fFileSizesMap.end(); it++) 426 statVar.sizeWritten += it->second; 427 statVar.sizeWritten -= fBaseSizeNightly; 428 statVar.sizeWritten -= fBaseSizeRun; 367 struct stat st; 368 //gather log and report files sizes on disk 369 if (fNightlyLogFile.is_open()) 370 { 371 stat(fFullNightlyLogFileName.c_str(), &st); 372 fFileSizesMap[fFullNightlyLogFileName] = st.st_size; 373 } 374 if (fNightlyReportFile.is_open()) 375 { 376 stat(fFullNightlyReportFileName.c_str(), &st); 377 fFileSizesMap[fFullNightlyReportFileName] = st.st_size; 378 } 379 if (fRunLogFile.is_open()) 380 { 381 stat(fFullRunLogFileName.c_str(), &st); 382 fFileSizesMap[fFullRunLogFileName] = st.st_size; 383 } 384 if (fRunReportFile.is_open()) 385 { 386 stat(fFullRunReportFileName.c_str(), &st); 387 fFileSizesMap[fFullRunReportFileName] = st.st_size; 388 } 389 struct statvfs vfs; 390 if (!statvfs(fNightlyFileName.c_str(), &vfs)) 391 { 392 statVar.freeSpace = vfs.f_bsize*vfs.f_bavail; 393 shouldWarn = false; 394 } 395 else 396 { 397 stringstream str; 398 str.str(""); 399 str << "Unable to retrieve stats for " << fNightlyFileName << ". Reason: " << strerror(errno) << " [" << errno << "]"; 400 if (!shouldWarn) 401 Error(str); 402 shouldWarn = true; 403 statVar.freeSpace = -1; 404 } 405 //sum up all the file sizes. past and present 406 statVar.sizeWritten = 0; 407 for (map<string, long>::iterator it=fFileSizesMap.begin(); it != fFileSizesMap.end(); it++) 408 statVar.sizeWritten += it->second; 409 statVar.sizeWritten -= fBaseSizeNightly; 410 statVar.sizeWritten -= fBaseSizeRun; 429 411 } 430 412 //static members initialization … … 449 431 void DataLogger::ServicesMonitoring() 450 432 { 451 DataLoggerStats statVar;452 statVar.sizeWritten = 0;453 statVar.freeSpace = 0;454 statVar.writingRate = 0;455 456 struct statvfs vfs;457 if (!statvfs(fNightlyFileName.c_str(), &vfs))458 statVar.freeSpace = vfs.f_bsize*vfs.f_bavail;459 else460 statVar.freeSpace = -1;461 462 DimDescribedService srvc ("DATA_LOGGER/STATS", "X:3", statVar, "Add description here");463 fPreviousSize = 0;464 bool statWarning = false;465 //loop-wait for broadcast466 while (fContinueMonitoring)467 {468 if (fStatsPeriodDuration == 0.0f)469 {470 sleep(0.1f);471 continue;472 }473 else474 sleep(fStatsPeriodDuration);475 //update the fits files sizes476 calculateTotalSizeWritten(statVar, statWarning, false);477 if (fStatsPeriodDuration == 0.0f)478 continue;479 statVar.writingRate = (statVar.sizeWritten - fPreviousSize)/fStatsPeriodDuration;480 481 fPreviousSize = statVar.sizeWritten;482 if (statVar.writingRate != 0) //if data has been written483 {484 srvc.updateService();485 if(fDebugIsOn)486 {487 stringstream str;488 str << "Size written: " << statVar.sizeWritten/1024 << " KB; writting rate: ";489 str << statVar.writingRate/1024 << " KB/s; free space: ";490 str << statVar.freeSpace/(1024*1024) << " MB";491 Debug(str.str());492 }493 }494 }433 DataLoggerStats statVar; 434 statVar.sizeWritten = 0; 435 statVar.freeSpace = 0; 436 statVar.writingRate = 0; 437 438 struct statvfs vfs; 439 if (!statvfs(fNightlyFileName.c_str(), &vfs)) 440 statVar.freeSpace = vfs.f_bsize*vfs.f_bavail; 441 else 442 statVar.freeSpace = -1; 443 444 DimDescribedService srvc ("DATA_LOGGER/STATS", "X:3", statVar, "Add description here"); 445 fPreviousSize = 0; 446 bool statWarning = false; 447 //loop-wait for broadcast 448 while (fContinueMonitoring) 449 { 450 if (fStatsPeriodDuration == 0.0f) 451 { 452 sleep(0.1f); 453 continue; 454 } 455 else 456 sleep(fStatsPeriodDuration); 457 //update the fits files sizes 458 calculateTotalSizeWritten(statVar, statWarning, false); 459 if (fStatsPeriodDuration == 0.0f) 460 continue; 461 statVar.writingRate = (statVar.sizeWritten - fPreviousSize)/fStatsPeriodDuration; 462 463 fPreviousSize = statVar.sizeWritten; 464 if (statVar.writingRate != 0) //if data has been written 465 { 466 srvc.updateService(); 467 if(fDebugIsOn) 468 { 469 stringstream str; 470 str << "Size written: " << statVar.sizeWritten/1024 << " KB; writting rate: "; 471 str << statVar.writingRate/1024 << " KB/s; free space: "; 472 str << statVar.freeSpace/(1024*1024) << " MB"; 473 Debug(str.str()); 474 } 475 } 476 } 495 477 } 496 478 … … 503 485 //!Setup the allows states, configs and transitions for the data logger 504 486 // 505 DataLogger::DataLogger( std::ostream &out) : StateMachineDim(out, "DATA_LOGGER")487 DataLogger::DataLogger(ostream &out) : StateMachineDim(out, "DATA_LOGGER") 506 488 { 507 489 dic_disable_padding(); 508 490 dis_disable_padding(); 509 //initialize member data510 fNightlyFileName = ".";511 fRunFileName = ".";512 fRunNumber = -1;513 fPreviousRunNumber = fRunNumber;491 //initialize member data 492 fNightlyFileName = "."; 493 fRunFileName = "."; 494 fRunNumber = -1; 495 fPreviousRunNumber = fRunNumber; 514 496 #ifdef HAVE_FITS 515 #ifdef ONE_RUN_FITS_ONLY 516 fRunFitsFile = NULL; 497 fRunFitsFile = NULL; 517 498 #endif 518 #endif 519 520 //Give a name to this machine's specific states 521 AddStateName(kSM_NightlyOpen, "NightlyFileOpen", "The summary files for the night are open."); 522 AddStateName(kSM_WaitingRun, "WaitForRun", "The summary files for the night are open and we wait for a run to be started."); 523 AddStateName(kSM_Logging, "Logging", "The summary files for the night and the files for a single run are open."); 524 AddStateName(kSM_BadNightlyConfig, "ErrNightlyFolder", "The folder for the nighly summary files is invalid."); 525 AddStateName(kSM_BadRunConfig, "ErrRunFolder", "The folder for the run files is invalid."); 526 527 /*Add the possible transitions for this machine*/ 528 AddEvent(kSM_NightlyOpen, fTransStart, kSM_Ready, kSM_BadNightlyConfig) 529 (boost::bind(&DataLogger::StartPlease, this)) 530 ("Start the nightly logging. Nightly file location must be specified already"); 531 532 AddEvent(kSM_Ready, fTransStop, kSM_NightlyOpen, kSM_WaitingRun, kSM_Logging) 533 (boost::bind(&DataLogger::GoToReadyPlease, this)) 534 ("Stop all data logging, close all files."); 535 536 AddEvent(kSM_Logging, fTransStartRun, kSM_WaitingRun, kSM_BadRunConfig) 537 (boost::bind(&DataLogger::StartRunPlease, this)) 538 ("Start the run logging. Run file location must be specified already."); 539 540 AddEvent(kSM_WaitingRun, fTransStopRun, kSM_Logging) 541 (boost::bind(&DataLogger::StopRunPlease, this)) 542 ("Wait for a run to be started, open run-files as soon as a run number arrives."); 543 544 AddEvent(kSM_Ready, fTransReset, kSM_Error, kSM_BadNightlyConfig, kSM_BadRunConfig, kSM_Error) 545 (boost::bind(&DataLogger::GoToReadyPlease, this)) 546 ("Transition to exit error states. Closes the nightly file if already opened."); 547 548 AddEvent(kSM_WaitingRun, fTransWait, kSM_NightlyOpen) 549 (boost::bind(&DataLogger::NightlyToWaitRunPlease, this)); 550 551 /*Add the possible configurations for this machine*/ 552 AddEvent(fConfigDay, "C", kSM_Ready, kSM_BadNightlyConfig) 553 (boost::bind(&DataLogger::ConfigureNightlyFileName, this, _1)) 554 ("Configure the folder for the nightly files." 555 "|Path[string]:Absolute or relative path name where the nightly files should be stored."); 556 557 AddEvent(fConfigRun, "C", kSM_Ready, kSM_BadNightlyConfig, kSM_NightlyOpen, kSM_WaitingRun, kSM_BadRunConfig) 558 (boost::bind(&DataLogger::ConfigureRunFileName, this, _1)) 559 ("Configure the folder for the run files." 560 "|Path[string]:Absolute or relative path name where the run files should be stored."); 561 562 AddEvent(fConfigRunNumber, "I", kSM_Ready, kSM_BadNightlyConfig, kSM_NightlyOpen, kSM_WaitingRun, kSM_BadRunConfig) 563 (boost::bind(&DataLogger::ConfigureRunNumber, this, _1)) 564 ("configure the run number. cannot be done in logging state"); 565 566 //Provide a logging command 567 //I get the feeling that I should be going through the EventImp 568 //instead of DimCommand directly, mainly because the commandHandler 569 //is already done in StateMachineImp.cc 570 //Thus I'll simply add a configuration, which I will treat as the logging command 571 AddEvent(fConfigLog, "C", kSM_NightlyOpen, kSM_Logging, kSM_WaitingRun, kSM_BadRunConfig) 572 (boost::bind(&DataLogger::LogMessagePlease, this, _1)) 573 ("Log a single message to the log-files." 574 "|Message[string]:Message to be logged."); 575 576 //Provide a print command 577 stringstream str; 578 str << kSM_Ready << " " << kSM_NightlyOpen << " " << kSM_WaitingRun << " " << kSM_Logging << " " << kSM_BadNightlyConfig; 579 str << " " << kSM_BadRunConfig; 580 581 AddEvent(fPrintCommand, str.str().c_str(), "") 582 // AddEvent(fPrintCommand, kSM_NightlyOpen, kSM_Logging, kSM_WaitingRun, kSM_BadNightlyConfig, kSM_BadRunConfig) 583 (boost::bind(&DataLogger::PrintStatePlease, this, _1)) 584 ("Print information about the internal status of the data logger."); 585 586 fServiceList.SetHandler(this); 587 CheckForServicesUpdate(); 588 589 //start the monitoring service 590 fContinueMonitoring = true; 591 fMonitoringThread = boost::thread(boost::bind(&DataLogger::ServicesMonitoring, this)); 592 fBaseSizeNightly = 0; 593 fBaseSizeRun = 0; 594 OpenFileToDim fToDim; 595 fToDim.code = 0; 596 fToDim.fileName[0] = '\0'; 597 598 fOpenedNightlyFiles = new DimDescribedService(GetName() + "/FILENAME_NIGHTLY", "I:1;C", fToDim, 599 "Path and base name which is used to compile the filenames for the nightly files." 600 "|Type[int]:type of open files (1=log, 2=rep, 4=fits)" 601 "|Name[string]:path and base file name"); 602 603 fOpenedRunFiles = new DimDescribedService(GetName() + "/FILENAME_RUN", "I:1;C", fToDim, 604 "Path and base name which is used to compile the filenames for the run files." 605 "|Type[int]:type of open files (1=log, 2=rep, 4=fits)" 606 "|Name[string]:path and base file name"); 607 608 fNumSubAndFitsData.numSubscriptions = 0; 609 fNumSubAndFitsData.numOpenFits = 0; 610 fNumSubAndFits = new DimDescribedService(GetName() + "/NUM_SUBS", "I:2", fNumSubAndFitsData, 611 "Shows number of services to which the data logger is currently subscribed and the total number of open files." 612 "|Subscriptions[int]:number of dim services to which the data logger is currently subscribed." 613 "|NumOpenFiles[int]:number of files currently open by the data logger"); 614 615 //black/white list 616 fHasBlackList = false; 617 fHasWhiteList = false; 618 fBlackList.clear(); 619 fWhiteList.clear(); 620 //services parameters 621 fDebugIsOn = false; 622 fStatsPeriodDuration = 1.0f; 623 fOpenedFilesIsOn = true; 624 fNumSubAndFitsIsOn = true; 625 626 //provide services control commands 627 AddEvent(fDebugOnOff, "B:1", kSM_NightlyOpen, kSM_Logging, kSM_WaitingRun, kSM_Ready) 628 (boost::bind(&DataLogger::SetDebugOnOff, this, _1)) 629 ("Switch debug mode on off. Debug mode prints ifnormation about every service written to a file." 630 "|Enable[bool]:Enable of disable debuig mode (yes/no)."); 631 632 AddEvent(fStatsPeriod, "F", kSM_NightlyOpen, kSM_Logging, kSM_WaitingRun, kSM_Ready) 633 (boost::bind(&DataLogger::SetStatsPeriod, this, _1)) 634 ("Interval in which the data-logger statitistics service (STATS) is updated." 635 "Interval[s]:Floating point value in seconds."); 636 637 AddEvent(fStartStopOpenedFiles, "B:1", kSM_NightlyOpen, kSM_Logging, kSM_WaitingRun, kSM_Ready) 638 (boost::bind(&DataLogger::SetOpenedFilesOnOff ,this, _1)) 639 ("Can be used to switch the service off which distributes information about the open files."); 640 641 AddEvent(fStartStopNumSubsAndFits, "B:1", kSM_NightlyOpen, kSM_Logging, kSM_WaitingRun, kSM_Ready) 642 (boost::bind(&DataLogger::SetNumSubsAndFitsOnOff, this, _1)) 643 ("Can be used to switch the service off which distributes information about the number of subscriptions and open files."); 644 645 fDestructing = false; 646 if(fDebugIsOn) 647 { 648 Debug("DataLogger Init Done."); 649 } 499 500 //Give a name to this machine's specific states 501 AddStateName(kSM_NightlyOpen, "NightlyFileOpen", "The summary files for the night are open."); 502 AddStateName(kSM_WaitingRun, "WaitForRun", "The summary files for the night are open and we wait for a run to be started."); 503 AddStateName(kSM_Logging, "Logging", "The summary files for the night and the files for a single run are open."); 504 AddStateName(kSM_BadNightlyConfig, "ErrNightlyFolder", "The folder for the nighly summary files is invalid."); 505 AddStateName(kSM_BadRunConfig, "ErrRunFolder", "The folder for the run files is invalid."); 506 507 /*Add the possible transitions for this machine*/ 508 AddEvent(kSM_NightlyOpen, fTransStart, kSM_Ready, kSM_BadNightlyConfig) 509 (boost::bind(&DataLogger::StartPlease, this)) 510 ("Start the nightly logging. Nightly file location must be specified already"); 511 512 AddEvent(kSM_Ready, fTransStop, kSM_NightlyOpen, kSM_WaitingRun, kSM_Logging) 513 (boost::bind(&DataLogger::GoToReadyPlease, this)) 514 ("Stop all data logging, close all files."); 515 516 AddEvent(kSM_Logging, fTransStartRun, kSM_WaitingRun, kSM_BadRunConfig) 517 (boost::bind(&DataLogger::StartRunPlease, this)) 518 ("Start the run logging. Run file location must be specified already."); 519 520 AddEvent(kSM_WaitingRun, fTransStopRun, kSM_Logging) 521 (boost::bind(&DataLogger::StopRunPlease, this)) 522 ("Wait for a run to be started, open run-files as soon as a run number arrives."); 523 524 AddEvent(kSM_Ready, fTransReset, kSM_Error, kSM_BadNightlyConfig, kSM_BadRunConfig, kSM_Error) 525 (boost::bind(&DataLogger::GoToReadyPlease, this)) 526 ("Transition to exit error states. Closes the nightly file if already opened."); 527 528 AddEvent(kSM_WaitingRun, fTransWait, kSM_NightlyOpen) 529 (boost::bind(&DataLogger::NightlyToWaitRunPlease, this)); 530 531 /*Add the possible configurations for this machine*/ 532 AddEvent(fConfigDay, "C", kSM_Ready, kSM_BadNightlyConfig) 533 (boost::bind(&DataLogger::ConfigureNightlyFileName, this, _1)) 534 ("Configure the folder for the nightly files." 535 "|Path[string]:Absolute or relative path name where the nightly files should be stored."); 536 537 AddEvent(fConfigRun, "C", kSM_Ready, kSM_BadNightlyConfig, kSM_NightlyOpen, kSM_WaitingRun, kSM_BadRunConfig) 538 (boost::bind(&DataLogger::ConfigureRunFileName, this, _1)) 539 ("Configure the folder for the run files." 540 "|Path[string]:Absolute or relative path name where the run files should be stored."); 541 542 AddEvent(fConfigRunNumber, "I", kSM_Ready, kSM_BadNightlyConfig, kSM_NightlyOpen, kSM_WaitingRun, kSM_BadRunConfig) 543 (boost::bind(&DataLogger::ConfigureRunNumber, this, _1)) 544 ("configure the run number. cannot be done in logging state"); 545 546 //Provide a logging command 547 //I get the feeling that I should be going through the EventImp 548 //instead of DimCommand directly, mainly because the commandHandler 549 //is already done in StateMachineImp.cc 550 //Thus I'll simply add a configuration, which I will treat as the logging command 551 AddEvent(fConfigLog, "C", kSM_NightlyOpen, kSM_Logging, kSM_WaitingRun, kSM_BadRunConfig) 552 (boost::bind(&DataLogger::LogMessagePlease, this, _1)) 553 ("Log a single message to the log-files." 554 "|Message[string]:Message to be logged."); 555 556 //Provide a print command 557 stringstream str; 558 str << kSM_Ready << " " << kSM_NightlyOpen << " " << kSM_WaitingRun << " " << kSM_Logging << " " << kSM_BadNightlyConfig; 559 str << " " << kSM_BadRunConfig; 560 AddEvent(fPrintCommand, str.str().c_str(), "") 561 (boost::bind(&DataLogger::PrintStatePlease, this, _1)) 562 ("Print information about the internal status of the data logger."); 563 564 fServiceList.SetHandler(this); 565 CheckForServicesUpdate(); 566 567 //start the monitoring service 568 fContinueMonitoring = true; 569 fMonitoringThread = boost::thread(boost::bind(&DataLogger::ServicesMonitoring, this)); 570 fBaseSizeNightly = 0; 571 fBaseSizeRun = 0; 572 OpenFileToDim fToDim; 573 fToDim.code = 0; 574 fToDim.fileName[0] = '\0'; 575 576 fOpenedNightlyFiles = new DimDescribedService(GetName() + "/FILENAME_NIGHTLY", "I:1;C", fToDim, 577 "Path and base name which is used to compile the filenames for the nightly files." 578 "|Type[int]:type of open files (1=log, 2=rep, 4=fits)" 579 "|Name[string]:path and base file name"); 580 581 fOpenedRunFiles = new DimDescribedService(GetName() + "/FILENAME_RUN", "I:1;C", fToDim, 582 "Path and base name which is used to compile the filenames for the run files." 583 "|Type[int]:type of open files (1=log, 2=rep, 4=fits)" 584 "|Name[string]:path and base file name"); 585 586 fNumSubAndFitsData.numSubscriptions = 0; 587 fNumSubAndFitsData.numOpenFits = 0; 588 fNumSubAndFits = new DimDescribedService(GetName() + "/NUM_SUBS", "I:2", fNumSubAndFitsData, 589 "Shows number of services to which the data logger is currently subscribed and the total number of open files." 590 "|Subscriptions[int]:number of dim services to which the data logger is currently subscribed." 591 "|NumOpenFiles[int]:number of files currently open by the data logger"); 592 593 //black/white list 594 fHasBlackList = false; 595 fHasWhiteList = false; 596 fBlackList.clear(); 597 fWhiteList.clear(); 598 //services parameters 599 fDebugIsOn = false; 600 fStatsPeriodDuration = 1.0f; 601 fOpenedFilesIsOn = true; 602 fNumSubAndFitsIsOn = true; 603 604 //provide services control commands 605 AddEvent(fDebugOnOff, "B:1", kSM_NightlyOpen, kSM_Logging, kSM_WaitingRun, kSM_Ready) 606 (boost::bind(&DataLogger::SetDebugOnOff, this, _1)) 607 ("Switch debug mode on off. Debug mode prints ifnormation about every service written to a file." 608 "|Enable[bool]:Enable of disable debuig mode (yes/no)."); 609 610 AddEvent(fStatsPeriod, "F", kSM_NightlyOpen, kSM_Logging, kSM_WaitingRun, kSM_Ready) 611 (boost::bind(&DataLogger::SetStatsPeriod, this, _1)) 612 ("Interval in which the data-logger statitistics service (STATS) is updated." 613 "Interval[s]:Floating point value in seconds."); 614 615 AddEvent(fStartStopOpenedFiles, "B:1", kSM_NightlyOpen, kSM_Logging, kSM_WaitingRun, kSM_Ready) 616 (boost::bind(&DataLogger::SetOpenedFilesOnOff ,this, _1)) 617 ("Can be used to switch the service off which distributes information about the open files."); 618 619 AddEvent(fStartStopNumSubsAndFits, "B:1", kSM_NightlyOpen, kSM_Logging, kSM_WaitingRun, kSM_Ready) 620 (boost::bind(&DataLogger::SetNumSubsAndFitsOnOff, this, _1)) 621 ("Can be used to switch the service off which distributes information about the number of subscriptions and open files."); 622 623 fDestructing = false; 624 if(fDebugIsOn) 625 { 626 Debug("DataLogger Init Done."); 627 } 650 628 } 651 629 // -------------------------------------------------------------------------- … … 653 631 //! Checks for changes in the existing services. 654 632 //! Any new service will be added to the service list, while the ones which disappeared are removed. 655 //! @todo656 //! add the configuration (using the conf class ?)657 633 // 658 634 //FIXME The service must be udpated so that I get the first notification. This should not be 659 635 bool DataLogger::CheckForServicesUpdate() 660 636 { 661 bool serviceUpdated = false; 662 //get the current server list 663 const std::vector<std::string> serverList = fServiceList.GetServerList(); 664 //first let's remove the servers that may have disapeared 665 //can't treat the erase on maps the same way as for vectors. Do it the safe way instead 666 std::vector<std::string> toBeDeleted; 667 for (SubscriptionsListType::iterator cListe = fServiceSubscriptions.begin(); cListe != fServiceSubscriptions.end(); cListe++) 668 { 669 std::vector<std::string>::const_iterator givenServers; 670 for (givenServers=serverList.begin(); givenServers!= serverList.end(); givenServers++) 671 if (cListe->first == *givenServers) 672 break; 673 if (givenServers == serverList.end())//server vanished. Remove it 674 { 675 toBeDeleted.push_back(cListe->first); 676 serviceUpdated = true; 677 } 678 679 } 680 for (std::vector<std::string>::const_iterator it = toBeDeleted.begin(); it != toBeDeleted.end(); it++) 681 fServiceSubscriptions.erase(*it); 682 //now crawl through the list of servers, and see if there was some updates 683 for (std::vector<std::string>::const_iterator i=serverList.begin(); i!=serverList.end();i++) 684 { 685 //skip the two de-fact excluded services 686 //Dim crashes if the publisher subscribes to its own service. This sounds weird, I agree. 687 if ((i->find("DIS_DNS") != std::string::npos) || 688 (i->find("DATA_LOGGER") != std::string::npos)) 689 continue; 690 //find the current server in our subscription list 691 SubscriptionsListType::iterator cSubs = fServiceSubscriptions.find(*i); 692 //get the service list of the current server 693 std::vector<std::string> cServicesList = fServiceList.GetServiceList(*i); 694 if (cSubs != fServiceSubscriptions.end())//if the current server already is in our subscriptions 695 { //then check and update our list of subscriptions 696 //first, remove the services that may have dissapeared. 697 std::map<std::string, SubscriptionType>::iterator serverSubs; 698 std::vector<std::string>::const_iterator givenSubs; 699 toBeDeleted.clear(); 700 for (serverSubs=cSubs->second.begin(); serverSubs != cSubs->second.end(); serverSubs++) 701 { 702 for (givenSubs = cServicesList.begin(); givenSubs != cServicesList.end(); givenSubs++) 703 if (serverSubs->first == *givenSubs) 704 break; 705 if (givenSubs == cServicesList.end()) 706 { 707 toBeDeleted.push_back(serverSubs->first); 708 serviceUpdated = true; 709 } 710 } 711 for (std::vector<std::string>::const_iterator it = toBeDeleted.begin(); it != toBeDeleted.end(); it++) 712 cSubs->second.erase(*it); 713 //now check for new services 714 for (givenSubs = cServicesList.begin(); givenSubs != cServicesList.end(); givenSubs++) 715 { 716 if (*givenSubs == "SERVICE_LIST") 717 continue; 718 719 if (fHasWhiteList && (fWhiteList.find(*i + "/") == fWhiteList.end()) && 637 bool serviceUpdated = false; 638 //get the current server list 639 const vector<string> serverList = fServiceList.GetServerList(); 640 //first let's remove the servers that may have disapeared 641 //can't treat the erase on maps the same way as for vectors. Do it the safe way instead 642 vector<string> toBeDeleted; 643 for (SubscriptionsListType::iterator cListe = fServiceSubscriptions.begin(); cListe != fServiceSubscriptions.end(); cListe++) 644 { 645 vector<string>::const_iterator givenServers; 646 for (givenServers=serverList.begin(); givenServers!= serverList.end(); givenServers++) 647 if (cListe->first == *givenServers) 648 break; 649 if (givenServers == serverList.end())//server vanished. Remove it 650 { 651 toBeDeleted.push_back(cListe->first); 652 serviceUpdated = true; 653 } 654 } 655 for (vector<string>::const_iterator it = toBeDeleted.begin(); it != toBeDeleted.end(); it++) 656 fServiceSubscriptions.erase(*it); 657 //now crawl through the list of servers, and see if there was some updates 658 for (vector<string>::const_iterator i=serverList.begin(); i!=serverList.end();i++) 659 { 660 //skip the two de-fact excluded services 661 //Dim crashes if the publisher subscribes to its own service. This sounds weird, I agree. 662 if ((i->find("DIS_DNS") != string::npos) || 663 (i->find("DATA_LOGGER") != string::npos)) 664 continue; 665 //find the current server in our subscription list 666 SubscriptionsListType::iterator cSubs = fServiceSubscriptions.find(*i); 667 //get the service list of the current server 668 vector<string> cServicesList = fServiceList.GetServiceList(*i); 669 if (cSubs != fServiceSubscriptions.end())//if the current server already is in our subscriptions 670 { //then check and update our list of subscriptions 671 //first, remove the services that may have dissapeared. 672 map<string, SubscriptionType>::iterator serverSubs; 673 vector<string>::const_iterator givenSubs; 674 toBeDeleted.clear(); 675 for (serverSubs=cSubs->second.begin(); serverSubs != cSubs->second.end(); serverSubs++) 676 { 677 for (givenSubs = cServicesList.begin(); givenSubs != cServicesList.end(); givenSubs++) 678 if (serverSubs->first == *givenSubs) 679 break; 680 if (givenSubs == cServicesList.end()) 681 { 682 toBeDeleted.push_back(serverSubs->first); 683 serviceUpdated = true; 684 } 685 } 686 for (vector<string>::const_iterator it = toBeDeleted.begin(); it != toBeDeleted.end(); it++) 687 cSubs->second.erase(*it); 688 //now check for new services 689 for (givenSubs = cServicesList.begin(); givenSubs != cServicesList.end(); givenSubs++) 690 { 691 if (*givenSubs == "SERVICE_LIST") 692 continue; 693 694 if (fHasWhiteList && (fWhiteList.find(*i + "/") == fWhiteList.end()) && 720 695 (fWhiteList.find(*i + "/" + *givenSubs) == fWhiteList.end()) && 721 696 (fWhiteList.find("/" + *givenSubs) == fWhiteList.end())) 722 continue;697 continue; 723 698 if (fHasBlackList && ((fBlackList.find(*i + "/") != fBlackList.end()) || 724 699 (fBlackList.find(*i + "/" + *givenSubs) != fBlackList.end()) || … … 727 702 728 703 if (cSubs->second.find(*givenSubs) == cSubs->second.end()) 729 {//service not found. Add it730 cSubs->second[*givenSubs].dimInfo = new DimStampedInfo(((*i) + "/" + *givenSubs).c_str(), const_cast<char*>(""), this);731 serviceUpdated = true;732 if(fDebugIsOn)733 {734 stringstream str;735 str << "Subscribing to service " << *i << "/" << *givenSubs;736 Debug(str.str()); 737 }738 } 739 }740 }741 else //server not found in our list. Create its entry742 {743 fServiceSubscriptions[*i] = std::map<std::string, SubscriptionType>();744 std::map<std::string, SubscriptionType>& liste = fServiceSubscriptions[*i];745 for (std::vector<std::string>::const_iterator j = cServicesList.begin(); j!= cServicesList.end(); j++)746 {747 if (*j == "SERVICE_LIST")748 continue;704 {//service not found. Add it 705 cSubs->second[*givenSubs].dimInfo = new DimStampedInfo(((*i) + "/" + *givenSubs).c_str(), const_cast<char*>(""), this); 706 serviceUpdated = true; 707 if(fDebugIsOn) 708 { 709 stringstream str; 710 str << "Subscribing to service " << *i << "/" << *givenSubs; 711 Debug(str.str()); 712 } 713 } 714 } 715 } 716 else //server not found in our list. Create its entry 717 { 718 fServiceSubscriptions[*i] = map<string, SubscriptionType>(); 719 map<string, SubscriptionType>& liste = fServiceSubscriptions[*i]; 720 for (vector<string>::const_iterator j = cServicesList.begin(); j!= cServicesList.end(); j++) 721 { 722 if (*j == "SERVICE_LIST") 723 continue; 749 724 if (fHasWhiteList && (fWhiteList.find(*i + "/") == fWhiteList.end()) && 750 725 (fWhiteList.find(*i + "/" + *j) == fWhiteList.end()) && … … 756 731 continue; 757 732 758 759 liste[*j].dimInfo = new DimStampedInfo(((*i) + "/" + (*j)).c_str(), const_cast<char*>(""), this); 760 serviceUpdated = true; 761 if(fDebugIsOn) 762 { 763 stringstream str; 764 str << "Subscribing to service " << *i << "/" << *j; 765 Debug(str.str()); 766 } 767 } 768 } 769 } 770 return serviceUpdated; 733 liste[*j].dimInfo = new DimStampedInfo(((*i) + "/" + (*j)).c_str(), const_cast<char*>(""), this); 734 serviceUpdated = true; 735 if(fDebugIsOn) 736 { 737 stringstream str; 738 str << "Subscribing to service " << *i << "/" << *j; 739 Debug(str.str()); 740 } 741 } 742 } 743 } 744 return serviceUpdated; 771 745 } 772 746 // -------------------------------------------------------------------------- … … 776 750 DataLogger::~DataLogger() 777 751 { 778 if (fDebugIsOn) 779 { 780 Debug("DataLogger destruction starts"); 781 } 782 fDestructing = true; 783 //first let's go to the ready state 784 //TODO some closing done below has already been executed by GoToReady. figure out what should be removed. 785 GoToReadyPlease(); 786 //release the services subscriptions 787 fServiceSubscriptions.clear(); 788 //exit the monitoring loop 789 fContinueMonitoring = false; 790 // delete[] fDimBuffer; 791 fMonitoringThread.join(); 792 //close the files 793 if (fNightlyLogFile.is_open()) 794 fNightlyLogFile.close(); 795 if (fNightlyReportFile.is_open()) 796 fNightlyReportFile.close(); 797 if (fRunLogFile.is_open()) 798 fRunLogFile.close(); 799 if (fRunReportFile.is_open()) 800 fRunReportFile.close(); 801 delete fOpenedNightlyFiles; 802 delete fOpenedRunFiles; 803 delete fNumSubAndFits; 804 //TODO notify that all files were closed 752 if (fDebugIsOn) 753 { 754 Debug("DataLogger destruction starts"); 755 } 756 fDestructing = true; 757 //first let's go to the ready state 758 GoToReadyPlease(); 759 //release the services subscriptions 760 fServiceSubscriptions.clear(); 761 //exit the monitoring loop 762 fContinueMonitoring = false; 763 764 fMonitoringThread.join(); 765 //close the files 766 if (fNightlyLogFile.is_open()) 767 fNightlyLogFile.close(); 768 if (fNightlyReportFile.is_open()) 769 fNightlyReportFile.close(); 770 if (fRunLogFile.is_open()) 771 fRunLogFile.close(); 772 if (fRunReportFile.is_open()) 773 fRunReportFile.close(); 774 delete fOpenedNightlyFiles; 775 delete fOpenedRunFiles; 776 delete fNumSubAndFits; 805 777 #ifdef HAVE_FITS 806 #ifdef ONE_RUN_FITS_ONLY 807 if (fRunFitsFile != NULL) 808 delete fRunFitsFile; 809 fRunFitsFile = NULL; 778 if (fRunFitsFile != NULL) 779 delete fRunFitsFile; 780 fRunFitsFile = NULL; 810 781 #endif 811 #endif 812 if (fDebugIsOn) 813 { 814 Debug("DataLogger desctruction ends"); 815 } 782 if (fDebugIsOn) 783 { 784 Debug("DataLogger desctruction ends"); 785 } 816 786 } 817 787 … … 823 793 { 824 794 // Make sure getTimestamp is called _before_ getTimestampMillisecs 825 if (fDestructing)826 return;795 if (fDestructing) 796 return; 827 797 828 798 DimInfo* I = getInfo(); 829 SubscriptionsListType::iterator x;830 std::map<std::string, SubscriptionType>::iterator y;831 if (I==NULL)832 {833 if (CheckForServicesUpdate())834 {835 //services were updated. Notify836 fNumSubAndFitsData.numSubscriptions = 0;837 for (x=fServiceSubscriptions.begin(); x != fServiceSubscriptions.end(); x++)838 fNumSubAndFitsData.numSubscriptions += x->second.size();839 if (fNumSubAndFitsIsOn)840 {841 if (fDebugIsOn)842 {843 stringstream str;844 str << "Updating number of subscriptions service: Num Subs=" << fNumSubAndFitsData.numSubscriptions << " Num open FITS=" << fNumSubAndFitsData.numOpenFits;845 Debug(str.str()); 846 }847 fNumSubAndFits->updateService();848 }849 }850 return;851 }852 //check if the service pointer corresponds to something that we subscribed to853 //this is a fix for a bug that provides bad Infos when a server starts854 bool found = false;855 for (x=fServiceSubscriptions.begin(); x != fServiceSubscriptions.end(); x++)856 {//find current service is subscriptions857 for (y=x->second.begin(); y!=x->second.end();y++)858 if (y->second.dimInfo == I)859 {860 found = true; 861 break;862 }863 if (found)864 break;865 }866 if (!found)867 return;868 if (I->getSize() <= 0)869 return;799 SubscriptionsListType::iterator x; 800 map<string, SubscriptionType>::iterator y; 801 if (I==NULL) 802 { 803 if (CheckForServicesUpdate()) 804 { 805 //services were updated. Notify 806 fNumSubAndFitsData.numSubscriptions = 0; 807 for (x=fServiceSubscriptions.begin(); x != fServiceSubscriptions.end(); x++) 808 fNumSubAndFitsData.numSubscriptions += x->second.size(); 809 if (fNumSubAndFitsIsOn) 810 { 811 if (fDebugIsOn) 812 { 813 stringstream str; 814 str << "Updating number of subscriptions service: Num Subs=" << fNumSubAndFitsData.numSubscriptions << " Num open FITS=" << fNumSubAndFitsData.numOpenFits; 815 Debug(str.str()); 816 } 817 fNumSubAndFits->updateService(); 818 } 819 } 820 return; 821 } 822 //check if the service pointer corresponds to something that we subscribed to 823 //this is a fix for a bug that provides bad Infos when a server starts 824 bool found = false; 825 for (x=fServiceSubscriptions.begin(); x != fServiceSubscriptions.end(); x++) 826 {//find current service is subscriptions 827 for (y=x->second.begin(); y!=x->second.end();y++) 828 if (y->second.dimInfo == I) 829 { 830 found = true; 831 break; 832 } 833 if (found) 834 break; 835 } 836 if (!found) 837 return; 838 if (I->getSize() <= 0) 839 return; 870 840 871 841 // Make sure that getTimestampMillisecs is NEVER called before 872 842 // getTimestamp is properly called 873 843 // check that the message has been updated by something, i.e. must be different from its initial value 874 if (I->getTimestamp() == 0)875 return;876 877 CheckForRunNumber(I);878 879 if (fPreviousRunNumber != fRunNumber)880 {//run number has changed. close and reopen run files.881 StopRunPlease();882 StartRunPlease();883 fPreviousRunNumber = fRunNumber;884 }885 886 ReportPlease(I, y->second);844 if (I->getTimestamp() == 0) 845 return; 846 847 CheckForRunNumber(I); 848 849 if (fPreviousRunNumber != fRunNumber) 850 {//run number has changed. close and reopen run files. 851 StopRunPlease(); 852 StartRunPlease(); 853 fPreviousRunNumber = fRunNumber; 854 } 855 856 ReportPlease(I, y->second); 887 857 888 858 } … … 893 863 //! If so, then remember it. A run number is required to open the run-log file 894 864 //! @param I 895 //! the current DimInfo865 //! the current DimInfo 896 866 // 897 867 void DataLogger::CheckForRunNumber(DimInfo* I) 898 868 { 899 if (strstr(I->getName(), fRunNumberInfo) != NULL) 900 {//assumes that the run number is an integer 901 //TODO check the format here 902 fRunNumber = I->getInt(); 903 stringstream str; 904 str << "New run number is " << fRunNumber; 905 Message(str.str()); 906 } 869 if (strstr(I->getName(), fRunNumberInfo) != NULL) 870 {//assumes that the run number is an integer 871 fRunNumber = I->getInt(); 872 stringstream str; 873 str << "New run number is " << fRunNumber; 874 Message(str.str()); 875 } 907 876 } 908 877 … … 911 880 //! write infos to log files. 912 881 //! @param I 913 //! The current DimInfo882 //! The current DimInfo 914 883 //! @param sub 915 //! The dataLogger's subscription corresponding to this DimInfo884 //! The dataLogger's subscription corresponding to this DimInfo 916 885 // 917 886 void DataLogger::ReportPlease(DimInfo* I, SubscriptionType& sub) 918 887 { 919 //should we log or report this info ? (i.e. is it a message ?) 920 bool isItaReport = ((strstr(I->getName(), "Message") == NULL) && (strstr(I->getName(), "MESSAGE") == NULL)); 921 if (I->getFormat()[0] == 'C') 922 isItaReport = false; 923 //TODO add service exclusion 924 925 if (!fNightlyReportFile.is_open()) 926 return; 927 928 //create the converter for that service 929 if (sub.fConv == NULL && isItaReport) 930 { 931 //trick the converter in case of 'C'. why do I do this ? well simple: the converter checks that the right number 932 //of bytes was written. because I skip 'C' with fits, the bytes will not be allocated, hence the "size copied ckeck" 933 //of the converter will fail, hence throwing an exception. 934 std::string fakeFormat(I->getFormat()); 935 if (fakeFormat[fakeFormat.size()-1] == 'C') 936 fakeFormat = fakeFormat.substr(0, fakeFormat.size()-1); 937 sub.fConv = new Converter(Out(), I->getFormat()); 938 if (!sub.fConv) 939 { 940 std::stringstream str; 941 str << "Couldn't properly parse the format... service " << sub.dimInfo->getName() << " ignored."; 942 Error(str); 943 return; 944 } 945 } 946 947 //construct the header 948 std::stringstream header; 949 Time cTime(I->getTimestamp(), I->getTimestampMillisecs()*1000); 950 fQuality = I->getQuality(); 951 fMjD = cTime.Mjd(); 952 953 if (isItaReport) 954 { 955 //write text header 956 header << I->getName() << " " << fQuality << " "; 957 header << cTime.Y() << " " << cTime.M() << " " << cTime.D() << " "; 958 header << cTime.h() << " " << cTime.m() << " " << cTime.s() << " "; 959 header << cTime.ms() << " " << I->getTimestamp() << " "; 960 961 std::string text; 888 //should we log or report this info ? (i.e. is it a message ?) 889 bool isItaReport = ((strstr(I->getName(), "Message") == NULL) && (strstr(I->getName(), "MESSAGE") == NULL)); 890 if (I->getFormat()[0] == 'C') 891 isItaReport = false; 892 893 if (!fNightlyReportFile.is_open()) 894 return; 895 896 //create the converter for that service 897 if (sub.fConv == NULL && isItaReport) 898 { 899 //trick the converter in case of 'C'. why do I do this ? well simple: the converter checks that the right number 900 //of bytes was written. because I skip 'C' with fits, the bytes will not be allocated, hence the "size copied ckeck" 901 //of the converter will fail, hence throwing an exception. 902 string fakeFormat(I->getFormat()); 903 if (fakeFormat[fakeFormat.size()-1] == 'C') 904 fakeFormat = fakeFormat.substr(0, fakeFormat.size()-1); 905 sub.fConv = new Converter(Out(), I->getFormat()); 906 if (!sub.fConv) 907 { 908 stringstream str; 909 str << "Couldn't properly parse the format... service " << sub.dimInfo->getName() << " ignored."; 910 Error(str); 911 return; 912 } 913 } 914 915 //construct the header 916 stringstream header; 917 Time cTime(I->getTimestamp(), I->getTimestampMillisecs()*1000); 918 fQuality = I->getQuality(); 919 fMjD = cTime.Mjd(); 920 921 if (isItaReport) 922 { 923 //write text header 924 header << I->getName() << " " << fQuality << " "; 925 header << cTime.Y() << " " << cTime.M() << " " << cTime.D() << " "; 926 header << cTime.h() << " " << cTime.m() << " " << cTime.s() << " "; 927 header << cTime.ms() << " " << I->getTimestamp() << " "; 928 929 string text; 962 930 try 963 931 { 964 text = sub.fConv->GetString(I->getData(), I->getSize());965 } 966 catch (const std::runtime_error &e)967 { 968 Out() << kRed << e.what() << endl;969 std::stringstream str;970 str << "Could not properly parse the data for service " << sub.dimInfo->getName();971 str << " reason: " << e.what() << ". Entry ignored";932 text = sub.fConv->GetString(I->getData(), I->getSize()); 933 } 934 catch (const runtime_error &e) 935 { 936 Out() << kRed << e.what() << endl; 937 stringstream str; 938 str << "Could not properly parse the data for service " << sub.dimInfo->getName(); 939 str << " reason: " << e.what() << ". Entry ignored"; 972 940 Error(str); 973 941 return; 974 942 } 975 943 976 if (text.empty())977 {978 std::stringstream str;979 str << "Service " << sub.dimInfo->getName() << " sent an empty string";980 Info(str);981 return;982 }944 if (text.empty()) 945 { 946 stringstream str; 947 str << "Service " << sub.dimInfo->getName() << " sent an empty string"; 948 Info(str); 949 return; 950 } 983 951 //replace bizarre characters by white space 984 952 replace(text.begin(), text.end(), '\n', '\\'); 985 replace_if(text.begin(), text.end(), std::ptr_fun<int, int>(&std::iscntrl), ' ');953 replace_if(text.begin(), text.end(), ptr_fun<int, int>(&iscntrl), ' '); 986 954 987 955 //write entry to Nightly report 988 if (fNightlyReportFile.is_open())989 {990 if (fDebugIsOn)991 {992 stringstream str;993 str << "Writing: \"" << header.str() << text << "\" to Nightly report file";994 Debug(str.str()); 995 }996 fNightlyReportFile << header.str() << text << std::endl;997 //check if either eof, bailbit or batbit are set998 if (!fNightlyReportFile.good())999 {1000 Error("An error occured while writing to the nightly report file. Closing it");1001 if (fNightlyReportFile.is_open())1002 fNightlyReportFile.close();1003 }1004 }1005 //write entry to run-report1006 if (fRunReportFile.is_open())1007 {1008 if (fDebugIsOn)1009 {1010 stringstream str;1011 str << "Writing: \"" << header.str() << text << "\" to Run report file";1012 Debug(str.str()); 1013 }1014 fRunReportFile << header.str() << text << std::endl;1015 if (!fRunReportFile.good())1016 {1017 Error("An error occured while writing to the run report file. Closing it.");1018 if (fRunReportFile.is_open())1019 fRunReportFile.close(); 1020 }1021 }1022 }1023 else1024 {//write entry to both Nightly and run logs1025 std::string n = I->getName();1026 std::stringstream msg;1027 msg << n << ": " << I->getString();//n.substr(0, n.find_first_of('/')) << ": " << I->getString();1028 1029 if (fNightlyLogFile.is_open())1030 {1031 if (fDebugIsOn)1032 {1033 stringstream str;1034 str << "Writing: \"" << msg.str() << "\" to Nightly log file";1035 Debug(str.str()); 1036 }1037 MessageImp nightlyMess(fNightlyLogFile);1038 nightlyMess.Write(cTime, msg.str().c_str(), fQuality);1039 if (!fNightlyLogFile.good())1040 {1041 Error("An error occured while writing to the nightly log file. Closing it.");1042 if (fNightlyLogFile.is_open())1043 fNightlyLogFile.close(); 1044 }1045 }1046 if (fRunLogFile.is_open())1047 {1048 if (fDebugIsOn)1049 {1050 stringstream str;1051 str << "Writing: \"" << msg.str() << "\" to Run log file";1052 Debug(str.str()); 1053 }1054 MessageImp runMess(fRunLogFile);1055 runMess.Write(cTime, msg.str().c_str(), fQuality);1056 if (!fRunLogFile.good())1057 {1058 Error("An error occured while writing to the run log file. Closing it.");1059 if (fRunLogFile.is_open())1060 fRunLogFile.close(); 1061 }1062 }1063 }956 if (fNightlyReportFile.is_open()) 957 { 958 if (fDebugIsOn) 959 { 960 stringstream str; 961 str << "Writing: \"" << header.str() << text << "\" to Nightly report file"; 962 Debug(str.str()); 963 } 964 fNightlyReportFile << header.str() << text << endl; 965 //check if either eof, bailbit or batbit are set 966 if (!fNightlyReportFile.good()) 967 { 968 Error("An error occured while writing to the nightly report file. Closing it"); 969 if (fNightlyReportFile.is_open()) 970 fNightlyReportFile.close(); 971 } 972 } 973 //write entry to run-report 974 if (fRunReportFile.is_open()) 975 { 976 if (fDebugIsOn) 977 { 978 stringstream str; 979 str << "Writing: \"" << header.str() << text << "\" to Run report file"; 980 Debug(str.str()); 981 } 982 fRunReportFile << header.str() << text << endl; 983 if (!fRunReportFile.good()) 984 { 985 Error("An error occured while writing to the run report file. Closing it."); 986 if (fRunReportFile.is_open()) 987 fRunReportFile.close(); 988 } 989 } 990 } 991 else 992 {//write entry to both Nightly and run logs 993 string n = I->getName(); 994 stringstream msg; 995 msg << n << ": " << I->getString();//n.substr(0, n.find_first_of('/')) << ": " << I->getString(); 996 997 if (fNightlyLogFile.is_open()) 998 { 999 if (fDebugIsOn) 1000 { 1001 stringstream str; 1002 str << "Writing: \"" << msg.str() << "\" to Nightly log file"; 1003 Debug(str.str()); 1004 } 1005 MessageImp nightlyMess(fNightlyLogFile); 1006 nightlyMess.Write(cTime, msg.str().c_str(), fQuality); 1007 if (!fNightlyLogFile.good()) 1008 { 1009 Error("An error occured while writing to the nightly log file. Closing it."); 1010 if (fNightlyLogFile.is_open()) 1011 fNightlyLogFile.close(); 1012 } 1013 } 1014 if (fRunLogFile.is_open()) 1015 { 1016 if (fDebugIsOn) 1017 { 1018 stringstream str; 1019 str << "Writing: \"" << msg.str() << "\" to Run log file"; 1020 Debug(str.str()); 1021 } 1022 MessageImp runMess(fRunLogFile); 1023 runMess.Write(cTime, msg.str().c_str(), fQuality); 1024 if (!fRunLogFile.good()) 1025 { 1026 Error("An error occured while writing to the run log file. Closing it."); 1027 if (fRunLogFile.is_open()) 1028 fRunLogFile.close(); 1029 } 1030 } 1031 } 1064 1032 1065 1033 #ifdef HAVE_FITS 1066 if (isItaReport)1067 {1068 if (!sub.nightlyFile.IsOpen() || !sub.runFile.IsOpen())1069 OpenFITSFilesPlease(sub); 1070 WriteToFITS(sub);1071 } 1034 if (isItaReport) 1035 { 1036 if (!sub.nightlyFile.IsOpen() || !sub.runFile.IsOpen()) 1037 OpenFITSFilesPlease(sub); 1038 WriteToFITS(sub); 1039 } 1072 1040 #endif 1073 1041 … … 1078 1046 //! write messages to logs. 1079 1047 //! @param evt 1080 //! the current event to log1048 //! the current event to log 1081 1049 //! @returns 1082 //! the new state. Currently, always the current state1050 //! the new state. Currently, always the current state 1083 1051 //! 1084 1052 //! @deprecated 1085 1053 //! I guess that this function should not be any longer 1086 1054 // 1087 //TODO isn't that function not used any longer ? If so I guess that we should get rid of it...1088 1055 //Otherwise re-write it properly with the MessageImp class 1089 1056 int DataLogger::LogMessagePlease(const Event& evt) 1090 1057 { 1091 if (!fNightlyLogFile.is_open())1092 return GetCurrentState();1093 1094 std::stringstream header;1095 const Time& cTime = evt.GetTime();1096 header << evt.GetName() << " " << cTime.Y() << " " << cTime.M() << " " << cTime.D() << " ";1097 header << cTime.h() << " " << cTime.m() << " " << cTime.s() << " ";1098 header << cTime.ms() << " ";1099 1058 if (!fNightlyLogFile.is_open()) 1059 return GetCurrentState(); 1060 Warn("LogMessagePlease has not been checked nor updated since a long while. Undefined behavior to be expected"); 1061 stringstream header; 1062 const Time& cTime = evt.GetTime(); 1063 header << evt.GetName() << " " << cTime.Y() << " " << cTime.M() << " " << cTime.D() << " "; 1064 header << cTime.h() << " " << cTime.m() << " " << cTime.s() << " "; 1065 header << cTime.ms() << " "; 1066 1100 1067 const Converter conv(Out(), evt.GetFormat()); 1101 1068 if (!conv) 1102 1069 { 1103 Error("Couldn't properly parse the format... ignored.");1070 Error("Couldn't properly parse the format... ignored."); 1104 1071 return GetCurrentState(); 1105 1072 } 1106 1073 1107 st d::string text;1074 string text; 1108 1075 try 1109 1076 { 1110 text = conv.GetString(evt.GetData(), evt.GetSize());1111 } 1112 catch (const std::runtime_error &e)1113 { 1114 Out() << kRed << e.what() << endl;1077 text = conv.GetString(evt.GetData(), evt.GetSize()); 1078 } 1079 catch (const runtime_error &e) 1080 { 1081 Out() << kRed << e.what() << endl; 1115 1082 Error("Couldn't properly parse the data... ignored."); 1116 1083 return GetCurrentState(); 1117 1084 } 1118 1085 1119 if (text.empty())1086 if (text.empty()) 1120 1087 return GetCurrentState(); 1121 1088 1122 1089 //replace bizarre characters by white space 1123 1090 replace(text.begin(), text.end(), '\n', '\\'); 1124 replace_if(text.begin(), text.end(), std::ptr_fun<int, int>(&std::iscntrl), ' ');1125 if (fDebugIsOn)1126 {1127 stringstream str;1128 str << "Logging: \"" << header << text << "\"";1129 Debug(str.str()); 1130 }1131 1132 if (fNightlyLogFile.is_open())1133 {1134 fNightlyLogFile << header;1135 if (!fNightlyLogFile.good())1136 {1137 Error("An error occured while writing to the run log file. Closing it.");1138 if (fNightlyLogFile.is_open())1139 fNightlyLogFile.close(); 1140 }1141 }1142 if (fRunLogFile.is_open())1143 {1144 fRunLogFile << header;1145 if (!fRunLogFile.good())1146 {1147 Error("An error occured while writing to the run log file. Closing it.");1148 if (fRunLogFile.is_open())1149 fRunLogFile.close(); 1150 }1151 }1152 if (fNightlyLogFile.is_open())1153 {1154 fNightlyLogFile << text;1155 if (!fNightlyLogFile.good())1156 {1157 Error("An error occured while writing to the run log file. Closing it.");1158 if (fNightlyLogFile.is_open())1159 fNightlyLogFile.close(); 1160 }1161 }1162 if (fRunLogFile.is_open())1163 {1164 fRunLogFile << text;1165 if (!fRunLogFile.good())1166 {1167 Error("An error occured while writing to the run log file. Closing it.");1168 if (fRunLogFile.is_open())1169 fRunLogFile.close(); 1170 }1171 }1172 return GetCurrentState();1091 replace_if(text.begin(), text.end(), ptr_fun<int, int>(&iscntrl), ' '); 1092 if (fDebugIsOn) 1093 { 1094 stringstream str; 1095 str << "Logging: \"" << header << text << "\""; 1096 Debug(str.str()); 1097 } 1098 1099 if (fNightlyLogFile.is_open()) 1100 { 1101 fNightlyLogFile << header; 1102 if (!fNightlyLogFile.good()) 1103 { 1104 Error("An error occured while writing to the run log file. Closing it."); 1105 if (fNightlyLogFile.is_open()) 1106 fNightlyLogFile.close(); 1107 } 1108 } 1109 if (fRunLogFile.is_open()) 1110 { 1111 fRunLogFile << header; 1112 if (!fRunLogFile.good()) 1113 { 1114 Error("An error occured while writing to the run log file. Closing it."); 1115 if (fRunLogFile.is_open()) 1116 fRunLogFile.close(); 1117 } 1118 } 1119 if (fNightlyLogFile.is_open()) 1120 { 1121 fNightlyLogFile << text; 1122 if (!fNightlyLogFile.good()) 1123 { 1124 Error("An error occured while writing to the run log file. Closing it."); 1125 if (fNightlyLogFile.is_open()) 1126 fNightlyLogFile.close(); 1127 } 1128 } 1129 if (fRunLogFile.is_open()) 1130 { 1131 fRunLogFile << text; 1132 if (!fRunLogFile.good()) 1133 { 1134 Error("An error occured while writing to the run log file. Closing it."); 1135 if (fRunLogFile.is_open()) 1136 fRunLogFile.close(); 1137 } 1138 } 1139 return GetCurrentState(); 1173 1140 } 1174 1141 // -------------------------------------------------------------------------- … … 1176 1143 //! print the dataLogger's current state. invoked by the PRINT command 1177 1144 //! @param evt 1178 //! the current event. Not used by the method1145 //! the current event. Not used by the method 1179 1146 //! @returns 1180 //! the new state. Which, in that case, is the current state1147 //! the new state. Which, in that case, is the current state 1181 1148 //! 1182 1149 int DataLogger::PrintStatePlease(const Event& ) 1183 1150 { 1184 Message("-----------------------------------------");1185 Message("------ DATA LOGGER CURRENT STATE --------");1186 Message("-----------------------------------------");1187 //print the path configuration1188 std::string actualTargetDir;1189 if (fNightlyFileName == ".")1190 {1191 char currentPath[FILENAME_MAX];1192 if (getcwd(currentPath, sizeof(currentPath)))1193 actualTargetDir = currentPath;1194 }1195 else1196 actualTargetDir = fNightlyFileName;1197 Message("Nightly Path: " + actualTargetDir);1198 if (fRunFileName == ".")1199 {1200 char currentPath[FILENAME_MAX];1201 if (getcwd(currentPath, sizeof(currentPath)))1202 actualTargetDir = currentPath;1203 }1204 else1205 actualTargetDir = fRunFileName;1206 Message("Run Path: " + actualTargetDir);1207 stringstream str;1208 str << "Run Number: " << fRunNumber;1209 Message(str.str());1210 Message("----------- OPENED FILES ----------------");1211 //print all the open files.1212 if (fNightlyLogFile.is_open())1213 Message("Nightly Log..........OPEN");1214 else1215 Message("Nightly log........CLOSED");1216 if (fNightlyReportFile.is_open())1217 Message("Nightly Report.......OPEN");1218 else1219 Message("Nightly Report.....CLOSED");1220 if (fRunLogFile.is_open())1221 Message("Run Log..............OPEN");1222 else1223 Message("Run Log............CLOSED");1224 if (fRunReportFile.is_open())1225 Message("Run Report...........OPEN");1226 else1227 Message("Run Report.........CLOSED");1228 bool statWarning = false;1229 DataLoggerStats statVar;1230 calculateTotalSizeWritten(statVar, statWarning, false);1231 Message("---------------- STATS ------------------");1232 str.str("");1233 str << "Total Size written: " << statVar.sizeWritten << " bytes.";1151 Message("-----------------------------------------"); 1152 Message("------ DATA LOGGER CURRENT STATE --------"); 1153 Message("-----------------------------------------"); 1154 //print the path configuration 1155 string actualTargetDir; 1156 if (fNightlyFileName == ".") 1157 { 1158 char currentPath[FILENAME_MAX]; 1159 if (getcwd(currentPath, sizeof(currentPath))) 1160 actualTargetDir = currentPath; 1161 } 1162 else 1163 actualTargetDir = fNightlyFileName; 1164 Message("Nightly Path: " + actualTargetDir); 1165 if (fRunFileName == ".") 1166 { 1167 char currentPath[FILENAME_MAX]; 1168 if (getcwd(currentPath, sizeof(currentPath))) 1169 actualTargetDir = currentPath; 1170 } 1171 else 1172 actualTargetDir = fRunFileName; 1173 Message("Run Path: " + actualTargetDir); 1174 stringstream str; 1175 str << "Run Number: " << fRunNumber; 1176 Message(str.str()); 1177 Message("----------- OPENED FILES ----------------"); 1178 //print all the open files. 1179 if (fNightlyLogFile.is_open()) 1180 Message("Nightly Log..........OPEN"); 1181 else 1182 Message("Nightly log........CLOSED"); 1183 if (fNightlyReportFile.is_open()) 1184 Message("Nightly Report.......OPEN"); 1185 else 1186 Message("Nightly Report.....CLOSED"); 1187 if (fRunLogFile.is_open()) 1188 Message("Run Log..............OPEN"); 1189 else 1190 Message("Run Log............CLOSED"); 1191 if (fRunReportFile.is_open()) 1192 Message("Run Report...........OPEN"); 1193 else 1194 Message("Run Report.........CLOSED"); 1195 bool statWarning = false; 1196 DataLoggerStats statVar; 1197 calculateTotalSizeWritten(statVar, statWarning, false); 1198 Message("---------------- STATS ------------------"); 1199 str.str(""); 1200 str << "Total Size written: " << statVar.sizeWritten << " bytes."; 1234 1201 Message(str.str()); 1235 str.str("");1236 str << "Disk free space: " << statVar.freeSpace << " bytes.";1202 str.str(""); 1203 str << "Disk free space: " << statVar.freeSpace << " bytes."; 1237 1204 Message(str.str()); 1238 1205 str.str(""); 1239 1206 str << "Statistics are updated every " << fStatsPeriodDuration << " seconds"; 1240 1207 if (fStatsPeriodDuration != 0) 1241 Message(str);1208 Message(str); 1242 1209 else 1243 Message("Statistics updates are currently disabled"); 1244 Message("----------- DIM SUBSCRIPTIONS -----------"); 1245 1246 str.str(""); 1247 str << "There are " << fNumSubAndFitsData.numSubscriptions << " active DIM subscriptions:"; 1248 Message(str.str()); 1249 1250 for (std::map<const std::string, std::map<std::string, SubscriptionType>>::const_iterator it=fServiceSubscriptions.begin(); it!= fServiceSubscriptions.end();it++) 1251 { 1252 Message("Server "+it->first); 1253 for (std::map<std::string, SubscriptionType>::const_iterator it2=it->second.begin(); it2!=it->second.end(); it2++) 1254 Message(" -> "+it2->first); 1255 } 1256 if (fHasBlackList) 1257 { 1258 Message("------------- BLOCK LIST ----------------"); 1259 for (set<string>::iterator it=fBlackList.begin(); it != fBlackList.end(); it++) 1260 Message(*it); 1261 } 1262 if (fHasWhiteList) 1263 { 1264 Message("----------- ALLOW LIST ------------------"); 1265 for (set<string>::iterator it=fWhiteList.begin(); it != fWhiteList.end(); it++) 1266 Message(*it); 1267 } 1268 1269 return GetCurrentState(); 1210 Message("Statistics updates are currently disabled"); 1211 Message("----------- DIM SUBSCRIPTIONS -----------"); 1212 1213 str.str(""); 1214 str << "There are " << fNumSubAndFitsData.numSubscriptions << " active DIM subscriptions:"; 1215 Message(str.str()); 1216 1217 for (map<const string, map<string, SubscriptionType> >::const_iterator it=fServiceSubscriptions.begin(); it!= fServiceSubscriptions.end();it++) 1218 { 1219 Message("Server "+it->first); 1220 for (map<string, SubscriptionType>::const_iterator it2=it->second.begin(); it2!=it->second.end(); it2++) 1221 Message(" -> "+it2->first); 1222 } 1223 if (fHasBlackList) 1224 { 1225 Message("------------- BLOCK LIST ----------------"); 1226 for (set<string>::iterator it=fBlackList.begin(); it != fBlackList.end(); it++) 1227 Message(*it); 1228 } 1229 if (fHasWhiteList) 1230 { 1231 Message("----------- ALLOW LIST ------------------"); 1232 for (set<string>::iterator it=fWhiteList.begin(); it != fWhiteList.end(); it++) 1233 Message(*it); 1234 } 1235 if (fGrouping.size() != 0) 1236 { 1237 Message("--------- GROUPING LIST -----------------"); 1238 Message("The following servers and/or services will be grouping under a single run fits file:"); 1239 for (set<string>::iterator it=fGrouping.begin(); it != fGrouping.end(); it++) 1240 Message(*it); 1241 } 1242 Message("-----------------------------------------"); 1243 Message("------ END OF DATA LOGGER STATE ---------"); 1244 Message("-----------------------------------------"); 1245 1246 return GetCurrentState(); 1270 1247 } 1271 1248 … … 1274 1251 //! turn debug mode on and off 1275 1252 //! @param evt 1276 //! the current event. contains the instruction string: On, Off, on, off, ON, OFF, 0 or 11253 //! the current event. contains the instruction string: On, Off, on, off, ON, OFF, 0 or 1 1277 1254 //! @returns 1278 //! the new state. Which, in that case, is the current state1255 //! the new state. Which, in that case, is the current state 1279 1256 //! 1280 1257 int DataLogger::SetDebugOnOff(const Event& evt) 1281 1258 { 1282 bool backupDebug = fDebugIsOn;1283 fDebugIsOn = evt.GetBool();1284 if (fDebugIsOn == backupDebug)1285 Warn("Warning: debug mode was already in the requested state");1286 else1287 {1288 stringstream str;1289 str << "Debug mode is now " << fDebugIsOn;1290 Message(str.str());1291 }1292 return GetCurrentState();1259 bool backupDebug = fDebugIsOn; 1260 fDebugIsOn = evt.GetBool(); 1261 if (fDebugIsOn == backupDebug) 1262 Warn("Warning: debug mode was already in the requested state"); 1263 else 1264 { 1265 stringstream str; 1266 str << "Debug mode is now " << fDebugIsOn; 1267 Message(str.str()); 1268 } 1269 return GetCurrentState(); 1293 1270 } 1294 1271 // -------------------------------------------------------------------------- … … 1296 1273 //! set the statistics update period duration. 0 disables the statistics 1297 1274 //! @param evt 1298 //! the current event. contains the new duration.1275 //! the current event. contains the new duration. 1299 1276 //! @returns 1300 //! the new state. Which, in that case, is the current state1277 //! the new state. Which, in that case, is the current state 1301 1278 //! 1302 1279 int DataLogger::SetStatsPeriod(const Event& evt) 1303 1280 { 1304 float backupDuration = fStatsPeriodDuration;1305 fStatsPeriodDuration = evt.GetFloat();1306 if (fStatsPeriodDuration < 0)1307 {1308 Error("Statistics period duration should be greater than zero. Discarding provided value.");1309 fStatsPeriodDuration = backupDuration;1310 return GetCurrentState(); 1311 }1312 if (fStatsPeriodDuration != fStatsPeriodDuration)1313 {1314 Error("Provided duration does not appear to be a valid float. discarding it.");1315 fStatsPeriodDuration = backupDuration;1316 return GetCurrentState(); 1317 }1318 if (backupDuration == fStatsPeriodDuration)1319 Warn("Warning: statistics period was not modified: supplied value already in use");1320 else1321 {1322 if (fStatsPeriodDuration == 0.0f)1323 Message("Statistics are now OFF");1324 else1325 {1326 stringstream str;1327 str << "Statistics period is now " << fStatsPeriodDuration << " seconds";1328 Message(str.str()); 1329 } 1330 }1331 return GetCurrentState();1281 float backupDuration = fStatsPeriodDuration; 1282 fStatsPeriodDuration = evt.GetFloat(); 1283 if (fStatsPeriodDuration < 0) 1284 { 1285 Error("Statistics period duration should be greater than zero. Discarding provided value."); 1286 fStatsPeriodDuration = backupDuration; 1287 return GetCurrentState(); 1288 } 1289 if (fStatsPeriodDuration != fStatsPeriodDuration) 1290 { 1291 Error("Provided duration does not appear to be a valid float. discarding it."); 1292 fStatsPeriodDuration = backupDuration; 1293 return GetCurrentState(); 1294 } 1295 if (backupDuration == fStatsPeriodDuration) 1296 Warn("Warning: statistics period was not modified: supplied value already in use"); 1297 else 1298 { 1299 if (fStatsPeriodDuration == 0.0f) 1300 Message("Statistics are now OFF"); 1301 else 1302 { 1303 stringstream str; 1304 str << "Statistics period is now " << fStatsPeriodDuration << " seconds"; 1305 Message(str.str()); 1306 } 1307 } 1308 return GetCurrentState(); 1332 1309 } 1333 1310 // -------------------------------------------------------------------------- … … 1335 1312 //! set the opened files service on or off. 1336 1313 //! @param evt 1337 //! the current event. contains the instruction string. similar to setdebugonoff1314 //! the current event. contains the instruction string. similar to setdebugonoff 1338 1315 //! @returns 1339 //! the new state. Which, in that case, is the current state1316 //! the new state. Which, in that case, is the current state 1340 1317 //! 1341 1318 int DataLogger::SetOpenedFilesOnOff(const Event& evt) 1342 1319 { 1343 bool backupOpened = fOpenedFilesIsOn;1344 fOpenedFilesIsOn = evt.GetBool();1345 if (fOpenedFilesIsOn == backupOpened)1346 Warn("Warning: opened files service mode was already in the requested state");1347 else1348 {1349 stringstream str;1350 str << "Opened files service mode is now " << fOpenedFilesIsOn;1351 Message(str.str());1352 }1353 return GetCurrentState();1354 1320 bool backupOpened = fOpenedFilesIsOn; 1321 fOpenedFilesIsOn = evt.GetBool(); 1322 if (fOpenedFilesIsOn == backupOpened) 1323 Warn("Warning: opened files service mode was already in the requested state"); 1324 else 1325 { 1326 stringstream str; 1327 str << "Opened files service mode is now " << fOpenedFilesIsOn; 1328 Message(str.str()); 1329 } 1330 return GetCurrentState(); 1331 1355 1332 } 1356 1333 // -------------------------------------------------------------------------- … … 1358 1335 //! set the number of subscriptions and opened fits on and off 1359 1336 //! @param evt 1360 //! the current event. contains the instruction string. similar to setdebugonoff1337 //! the current event. contains the instruction string. similar to setdebugonoff 1361 1338 //! @returns 1362 //! the new state. Which, in that case, is the current state1339 //! the new state. Which, in that case, is the current state 1363 1340 //! 1364 1341 int DataLogger::SetNumSubsAndFitsOnOff(const Event& evt) 1365 1342 { 1366 bool backupSubs = fNumSubAndFitsIsOn;1367 fNumSubAndFitsIsOn = evt.GetBool();1368 if (fNumSubAndFitsIsOn == backupSubs)1369 Warn("Warning: Number of subscriptions service mode was already in the requested state");1370 else1371 {1372 stringstream str;1373 str << "Number of subscriptions service mode is now " << fNumSubAndFitsIsOn;1374 Message(str.str());1375 }1376 return GetCurrentState();1377 } 1378 // -------------------------------------------------------------------------- 1379 // 1380 //! Sets the path to use for the Nightly log file.1343 bool backupSubs = fNumSubAndFitsIsOn; 1344 fNumSubAndFitsIsOn = evt.GetBool(); 1345 if (fNumSubAndFitsIsOn == backupSubs) 1346 Warn("Warning: Number of subscriptions service mode was already in the requested state"); 1347 else 1348 { 1349 stringstream str; 1350 str << "Number of subscriptions service mode is now " << fNumSubAndFitsIsOn; 1351 Message(str.str()); 1352 } 1353 return GetCurrentState(); 1354 } 1355 // -------------------------------------------------------------------------- 1356 // 1357 //! Sets the path to use for the Nightly log file. 1381 1358 //! @param evt 1382 //! the event transporting the path1359 //! the event transporting the path 1383 1360 //! @returns 1384 //! currently only the current state.1361 //! currently only the current state. 1385 1362 // 1386 1363 int DataLogger::ConfigureNightlyFileName(const Event& evt) 1387 1364 { 1388 if (evt.GetText() != NULL)1389 {1390 fNightlyFileName = std::string(evt.GetText()); 1391 Message("New Nightly folder specified: " + fNightlyFileName);1392 }1393 else1394 Error("Empty Nightly folder given. Please specify a valid path.");1395 1396 return GetCurrentState();1365 if (evt.GetText() != NULL) 1366 { 1367 fNightlyFileName = string(evt.GetText()); 1368 Message("New Nightly folder specified: " + fNightlyFileName); 1369 } 1370 else 1371 Error("Empty Nightly folder given. Please specify a valid path."); 1372 1373 return GetCurrentState(); 1397 1374 } 1398 1375 // -------------------------------------------------------------------------- … … 1400 1377 //! Sets the path to use for the run log file. 1401 1378 //! @param evt 1402 //! the event transporting the path1379 //! the event transporting the path 1403 1380 //! @returns 1404 //! currently only the current state1381 //! currently only the current state 1405 1382 int DataLogger::ConfigureRunFileName(const Event& evt) 1406 1383 { 1407 if (evt.GetText() != NULL)1408 {1409 fRunFileName = std::string(evt.GetText());1410 Message("New Run folder specified: " + fRunFileName);1411 }1412 else1413 Error("Empty Nightly folder given. Please specify a valid path");1414 1415 return GetCurrentState();1384 if (evt.GetText() != NULL) 1385 { 1386 fRunFileName = string(evt.GetText()); 1387 Message("New Run folder specified: " + fRunFileName); 1388 } 1389 else 1390 Error("Empty Nightly folder given. Please specify a valid path"); 1391 1392 return GetCurrentState(); 1416 1393 } 1417 1394 // -------------------------------------------------------------------------- … … 1419 1396 //! Sets the run number. 1420 1397 //! @param evt 1421 //! the event transporting the run number1398 //! the event transporting the run number 1422 1399 //! @returns 1423 //! currently only the current state 1424 //TODO remove this function as the run numbers will be distributed through a dedicated service 1400 //! currently only the current state 1425 1401 int DataLogger::ConfigureRunNumber(const Event& evt) 1426 1402 { 1427 fRunNumber = evt.GetInt();1428 std::stringstream str;1429 str << "The new run number is: " << fRunNumber;1430 Message(str.str());1431 return GetCurrentState();1403 fRunNumber = evt.GetInt(); 1404 stringstream str; 1405 str << "The new run number is: " << fRunNumber; 1406 Message(str.str()); 1407 return GetCurrentState(); 1432 1408 } 1433 1409 // -------------------------------------------------------------------------- … … 1435 1411 //! Notifies the DIM service that a particular file was opened 1436 1412 //! @ param name the base name of the opened file, i.e. without path nor extension. 1437 //! WARNING: use string instead of string& because I pass values that do not convert to string&.1438 //! this is not a problem though because file are not opened so often.1413 //! WARNING: use string instead of string& because I pass values that do not convert to string&. 1414 //! this is not a problem though because file are not opened so often. 1439 1415 //! @ param type the type of the opened file. 0 = none open, 1 = log, 2 = text, 4 = fits 1440 inline void DataLogger::NotifyOpenedFile(st d::string name, int type, DimDescribedService* service)1441 { 1442 if (fOpenedFilesIsOn)1443 {1444 if (fDebugIsOn)1445 {1446 stringstream str;1447 str << "Updating files service " << service->getName() << "with code: " << type << " and file: " << name;1448 Debug(str.str());1449 str.str("");1450 str << "Num subs: " << fNumSubAndFitsData.numSubscriptions << " Num open FITS: " << fNumSubAndFitsData.numOpenFits;1451 Debug(str.str());1452 }1453 OpenFileToDim fToDim;1454 fToDim.code = type;1455 memcpy(fToDim.fileName, name.c_str(), name.size()+1);1456 service->setData(reinterpret_cast<void*>(&fToDim), name.size()+1+sizeof(int));1457 service->setQuality(0);1458 service->updateService();1459 }1416 inline void DataLogger::NotifyOpenedFile(string name, int type, DimDescribedService* service) 1417 { 1418 if (fOpenedFilesIsOn) 1419 { 1420 if (fDebugIsOn) 1421 { 1422 stringstream str; 1423 str << "Updating files service " << service->getName() << "with code: " << type << " and file: " << name; 1424 Debug(str.str()); 1425 str.str(""); 1426 str << "Num subs: " << fNumSubAndFitsData.numSubscriptions << " Num open FITS: " << fNumSubAndFitsData.numOpenFits; 1427 Debug(str.str()); 1428 } 1429 OpenFileToDim fToDim; 1430 fToDim.code = type; 1431 memcpy(fToDim.fileName, name.c_str(), name.size()+1); 1432 service->setData(reinterpret_cast<void*>(&fToDim), name.size()+1+sizeof(int)); 1433 service->setQuality(0); 1434 service->updateService(); 1435 } 1460 1436 } 1461 1437 // -------------------------------------------------------------------------- … … 1465 1441 //! and tries to open it. 1466 1442 //! @returns 1467 //! kSM_NightlyOpen if success, kSM_BadNightlyConfig if failure1443 //! kSM_NightlyOpen if success, kSM_BadNightlyConfig if failure 1468 1444 int DataLogger::StartPlease() 1469 1445 { 1470 if (fDebugIsOn) 1471 { 1472 Debug("Starting..."); 1473 } 1474 Time time; 1475 std::stringstream sTime; 1476 sTime << time.Y() << "_" << time.M() << "_" << time.D(); 1477 1478 fFullNightlyLogFileName = fNightlyFileName + '/' + sTime.str() + ".log"; 1479 fNightlyLogFile.open(fFullNightlyLogFileName.c_str(), std::ios_base::out | std::ios_base::app); 1480 if (errno != 0) 1481 { 1482 std::stringstream str; 1483 str << "Unable to open Nightly Log " << fFullNightlyLogFileName << ". Reason: " << strerror(errno) << " [" << errno << "]"; 1484 Error(str); 1485 } 1486 fFullNightlyReportFileName = fNightlyFileName + '/' + sTime.str() + ".rep"; 1487 fNightlyReportFile.open(fFullNightlyReportFileName.c_str(), std::ios_base::out | std::ios_base::app); 1488 if (errno != 0) 1489 { 1490 std::stringstream str; 1491 str << "Unable to open Nightly Report " << fFullNightlyReportFileName << ". Reason: " << strerror(errno) << " [" << errno << "]"; 1492 Error(str); 1493 } 1494 1495 if (!fNightlyLogFile.is_open() || !fNightlyReportFile.is_open()) 1496 { 1497 //TODO send an error message 1498 return kSM_BadNightlyConfig; 1499 } 1500 //get the size of the newly opened file. 1501 struct stat st; 1502 stat(fFullNightlyLogFileName.c_str(), &st); 1503 fBaseSizeNightly = st.st_size; 1504 stat(fFullNightlyReportFileName.c_str(), &st); 1505 fBaseSizeNightly += st.st_size; 1506 fFileSizesMap.clear(); 1507 fBaseSizeRun = 0; 1508 fPreviousSize = 0; 1509 //notify that files were opened 1510 std::string actualTargetDir; 1511 if (fNightlyFileName == ".") 1512 { 1513 char currentPath[FILENAME_MAX]; 1514 if (!getcwd(currentPath, sizeof(currentPath))) 1515 { 1516 if (errno != 0) 1517 { 1518 std::stringstream str; 1519 str << "Unable retrieve current path" << ". Reason: " << strerror(errno) << " [" << errno << "]"; 1520 Error(str); 1521 } 1522 } 1523 actualTargetDir = currentPath; 1524 } 1525 else 1526 { 1527 actualTargetDir = fNightlyFileName; 1528 } 1529 //notify that a new file has been opened. 1530 NotifyOpenedFile(actualTargetDir + '/' + sTime.str(), 3, fOpenedNightlyFiles); 1531 1532 fOpenedNightlyFits.clear(); 1533 1534 return kSM_NightlyOpen; 1446 if (fDebugIsOn) 1447 { 1448 Debug("Starting..."); 1449 } 1450 Time time; 1451 stringstream sTime; 1452 sTime << time.Y() << "_" << time.M() << "_" << time.D(); 1453 1454 fFullNightlyLogFileName = fNightlyFileName + '/' + sTime.str() + ".log"; 1455 fNightlyLogFile.open(fFullNightlyLogFileName.c_str(), ios_base::out | ios_base::app); 1456 if (errno != 0) 1457 { 1458 stringstream str; 1459 str << "Unable to open Nightly Log " << fFullNightlyLogFileName << ". Reason: " << strerror(errno) << " [" << errno << "]"; 1460 Error(str); 1461 } 1462 fFullNightlyReportFileName = fNightlyFileName + '/' + sTime.str() + ".rep"; 1463 fNightlyReportFile.open(fFullNightlyReportFileName.c_str(), ios_base::out | ios_base::app); 1464 if (errno != 0) 1465 { 1466 stringstream str; 1467 str << "Unable to open Nightly Report " << fFullNightlyReportFileName << ". Reason: " << strerror(errno) << " [" << errno << "]"; 1468 Error(str); 1469 } 1470 1471 if (!fNightlyLogFile.is_open() || !fNightlyReportFile.is_open()) 1472 { 1473 stringstream str; 1474 str << "Something went wrong while openning nightly files " << fFullNightlyLogFileName << " and " << fFullNightlyReportFileName; 1475 Error(str.str()); 1476 return kSM_BadNightlyConfig; 1477 } 1478 //get the size of the newly opened file. 1479 struct stat st; 1480 stat(fFullNightlyLogFileName.c_str(), &st); 1481 fBaseSizeNightly = st.st_size; 1482 stat(fFullNightlyReportFileName.c_str(), &st); 1483 fBaseSizeNightly += st.st_size; 1484 fFileSizesMap.clear(); 1485 fBaseSizeRun = 0; 1486 fPreviousSize = 0; 1487 //notify that files were opened 1488 string actualTargetDir; 1489 if (fNightlyFileName == ".") 1490 { 1491 char currentPath[FILENAME_MAX]; 1492 if (!getcwd(currentPath, sizeof(currentPath))) 1493 { 1494 if (errno != 0) 1495 { 1496 stringstream str; 1497 str << "Unable retrieve current path" << ". Reason: " << strerror(errno) << " [" << errno << "]"; 1498 Error(str); 1499 } 1500 } 1501 actualTargetDir = currentPath; 1502 } 1503 else 1504 { 1505 actualTargetDir = fNightlyFileName; 1506 } 1507 //notify that a new file has been opened. 1508 NotifyOpenedFile(actualTargetDir + '/' + sTime.str(), 3, fOpenedNightlyFiles); 1509 1510 fOpenedNightlyFits.clear(); 1511 1512 return kSM_NightlyOpen; 1535 1513 } 1536 1514 … … 1540 1518 //! open if required a the FITS files corresponding to a given subscription 1541 1519 //! @param sub 1542 //! the current DimInfo subscription being examined1520 //! the current DimInfo subscription being examined 1543 1521 void DataLogger::OpenFITSFilesPlease(SubscriptionType& sub) 1544 1522 { 1545 std::string serviceName(sub.dimInfo->getName()); 1546 for (unsigned int i=0;i<serviceName.size(); i++) 1547 { 1548 if (serviceName[i] == '/') 1549 { 1550 serviceName[i] = '_'; 1551 break; 1552 } 1553 } 1554 Time time; 1555 std::stringstream sTime; 1556 sTime << time.Y() << "_" << time.M() << "_" << time.D(); 1557 //we open the NightlyFile anyway, otherwise this function shouldn't have been called. 1558 if (!sub.nightlyFile.IsOpen()) 1559 { 1560 std::string fileNameOnly = sTime.str() + '_' + serviceName + ".fits"; 1561 std::string partialName = fNightlyFileName + '/' + fileNameOnly; 1562 AllocateFITSBuffers(sub); 1563 //get the size of the file we're about to open 1564 if (fFileSizesMap.find(partialName) == fFileSizesMap.end()) 1565 { 1566 struct stat st; 1567 if (!stat(partialName.c_str(), &st)) 1568 fBaseSizeNightly += st.st_size; 1569 fFileSizesMap[partialName] = 0; 1570 //remember that this file was opened. 1571 fOpenedNightlyFits[fileNameOnly] = serviceName; 1572 } 1573 sub.nightlyFile.Open(partialName, serviceName, NULL, &fNumSubAndFitsData.numOpenFits, this);//Out()); 1574 1575 //notify the opening 1576 std::string actualTargetDir; 1577 if (fNightlyFileName == ".") 1578 { 1579 char currentPath[FILENAME_MAX]; 1580 if (getcwd(currentPath, sizeof(currentPath))) 1581 actualTargetDir = currentPath; 1582 } 1583 else 1584 { 1585 actualTargetDir = fNightlyFileName; 1586 } 1587 NotifyOpenedFile(actualTargetDir + '/' + sTime.str(), 7, fOpenedNightlyFiles); 1588 if (fNumSubAndFitsIsOn) 1589 fNumSubAndFits->updateService(); 1590 if (fDebugIsOn) 1591 { 1592 stringstream str; 1593 str << "Opened Nightly FITS: " << partialName << " and table: FACT-" << serviceName << ".current number of opened FITS: " << fNumSubAndFitsData.numOpenFits; 1594 Debug(str.str()); 1595 } 1596 } 1597 if (!sub.runFile.IsOpen() && (GetCurrentState() == kSM_Logging)) 1598 {//buffer for the run file have already been allocated when doing the Nightly file 1599 std::stringstream sRun; 1600 sRun << fRunNumber; 1601 #ifdef ONE_RUN_FITS_ONLY 1602 std::string fileNameOnly = sRun.str() + ".fits"; 1603 std::string partialName = fRunFileName + '/' + fileNameOnly; 1604 if (fRunFitsFile == NULL) 1605 { 1606 #else 1607 std::string fileNameOnly = sRun.str() + '_' + serviceName + ".fits"; 1608 std::string partialName = fRunFileName + '/' + fileNameOnly; 1609 #endif 1610 //get the size of the file we're about to open 1611 if (fFileSizesMap.find(partialName) == fFileSizesMap.end()) 1612 { 1613 struct stat st; 1614 if (!stat(partialName.c_str(), &st)) 1615 fBaseSizeRun += st.st_size; 1616 else 1617 fBaseSizeRun = 0; 1618 fFileSizesMap[partialName] = 0; 1619 fOpenedRunFits[fileNameOnly] = serviceName; 1620 } 1621 #ifdef ONE_RUN_FITS_ONLY 1622 try 1623 { 1624 fRunFitsFile = new CCfits::FITS(partialName, CCfits::RWmode::Write); 1625 (fNumSubAndFitsData.numOpenFits)++; 1626 } 1627 catch (CCfits::FitsError e) 1628 { 1629 std::stringstream str; 1630 str << "Could not open FITS Run file " << partialName << " reason: " << e.message(); 1631 Error(str); 1632 fRunFitsFile = NULL; 1633 } 1634 #endif 1635 std::string actualTargetDir; 1636 if (fRunFileName == ".") 1637 { 1638 char currentPath[FILENAME_MAX]; 1639 if (getcwd(currentPath, sizeof(currentPath))) 1640 actualTargetDir = currentPath; 1641 } 1642 else 1643 { 1644 actualTargetDir = fRunFileName; 1645 } 1646 NotifyOpenedFile(actualTargetDir + '/' + sRun.str(), 7, fOpenedRunFiles);// + '_' + serviceName, 4); 1647 #ifdef ONE_RUN_FITS_ONLY 1648 } 1649 sub.runFile.Open(partialName, serviceName, fRunFitsFile, &fNumSubAndFitsData.numOpenFits, this);//Out()); 1650 #else 1651 sub.runFile.Open(partialName, serviceName, NULL, &fNumSubAndFitsData.numOpenFits, this);//Out()); 1652 #endif //one_run_fits_only 1653 if (fNumSubAndFitsIsOn) 1654 fNumSubAndFits->updateService(); 1655 if (fDebugIsOn) 1656 { 1657 stringstream str; 1658 str << "Opened Run FITS: " << partialName << " and table: FACT-" << serviceName << ".current number of opened FITS: " << fNumSubAndFitsData.numOpenFits; 1659 Debug(str.str()); 1660 } 1661 } 1662 } 1523 string serviceName(sub.dimInfo->getName()); 1524 //we must check if we should group this service subscription to a single fits file before we replace the / by _ 1525 bool hasGrouping = false; 1526 if (!sub.runFile.IsOpen() && (GetCurrentState() == kSM_Logging)) 1527 {//will we find this service in the grouping list ? 1528 for (set<string>::iterator it=fGrouping.begin(); it!=fGrouping.end(); it++) 1529 { 1530 if (serviceName.find(*it) != string::npos) 1531 { 1532 hasGrouping = true; 1533 break; 1534 } 1535 } 1536 } 1537 for (unsigned int i=0;i<serviceName.size(); i++) 1538 { 1539 if (serviceName[i] == '/') 1540 { 1541 serviceName[i] = '_'; 1542 break; 1543 } 1544 } 1545 Time time; 1546 stringstream sTime; 1547 sTime << time.Y() << "_" << time.M() << "_" << time.D(); 1548 //we open the NightlyFile anyway, otherwise this function shouldn't have been called. 1549 if (!sub.nightlyFile.IsOpen()) 1550 { 1551 string fileNameOnly = sTime.str() + '_' + serviceName + ".fits"; 1552 string partialName = fNightlyFileName + '/' + fileNameOnly; 1553 AllocateFITSBuffers(sub); 1554 //get the size of the file we're about to open 1555 if (fFileSizesMap.find(partialName) == fFileSizesMap.end()) 1556 { 1557 struct stat st; 1558 if (!stat(partialName.c_str(), &st)) 1559 fBaseSizeNightly += st.st_size; 1560 fFileSizesMap[partialName] = 0; 1561 //remember that this file was opened. 1562 fOpenedNightlyFits[fileNameOnly].push_back(serviceName); 1563 } 1564 sub.nightlyFile.Open(partialName, serviceName, NULL, &fNumSubAndFitsData.numOpenFits, this);//Out()); 1565 1566 //notify the opening 1567 string actualTargetDir; 1568 if (fNightlyFileName == ".") 1569 { 1570 char currentPath[FILENAME_MAX]; 1571 if (getcwd(currentPath, sizeof(currentPath))) 1572 actualTargetDir = currentPath; 1573 } 1574 else 1575 { 1576 actualTargetDir = fNightlyFileName; 1577 } 1578 NotifyOpenedFile(actualTargetDir + '/' + sTime.str(), 7, fOpenedNightlyFiles); 1579 if (fNumSubAndFitsIsOn) 1580 fNumSubAndFits->updateService(); 1581 if (fDebugIsOn) 1582 { 1583 stringstream str; 1584 str << "Opened Nightly FITS: " << partialName << " and table: FACT-" << serviceName << ".current number of opened FITS: " << fNumSubAndFitsData.numOpenFits; 1585 Debug(str.str()); 1586 } 1587 } 1588 if (!sub.runFile.IsOpen() && (GetCurrentState() == kSM_Logging)) 1589 {//buffer for the run file have already been allocated when doing the Nightly file 1590 stringstream sRun; 1591 sRun << fRunNumber; 1592 string fileNameOnly; 1593 string partialName; 1594 1595 if (hasGrouping) 1596 { 1597 fileNameOnly = sRun.str() + "_group.fits"; 1598 partialName = fRunFileName + '/' + fileNameOnly; 1599 } 1600 else 1601 { 1602 fileNameOnly = sRun.str() + '_' + serviceName + ".fits"; 1603 partialName = fRunFileName + '/' + fileNameOnly; 1604 } 1605 //get the size of the file we're about to open 1606 if (fFileSizesMap.find(partialName) == fFileSizesMap.end()) 1607 { 1608 struct stat st; 1609 if (!stat(partialName.c_str(), &st)) 1610 fBaseSizeRun += st.st_size; 1611 else 1612 fBaseSizeRun = 0; 1613 fFileSizesMap[partialName] = 0; 1614 fOpenedRunFits[fileNameOnly].push_back(serviceName); 1615 } 1616 else 1617 if (hasGrouping) 1618 {//most likely I should add this service name. 1619 //the only case for which I should not add it is if a service disapeared, hence the file was closed 1620 //and reopened again. Unlikely to happen, but well it may 1621 bool found = false; 1622 for (vector<string>::iterator it=fOpenedRunFits[fileNameOnly].begin(); it!=fOpenedRunFits[fileNameOnly].end(); it++) 1623 if (*it == serviceName) 1624 { 1625 found = true; 1626 break; 1627 } 1628 if (!found) 1629 fOpenedRunFits[fileNameOnly].push_back(serviceName); 1630 } 1631 if (hasGrouping && fRunFitsFile == NULL) 1632 try 1633 { 1634 fRunFitsFile = new CCfits::FITS(partialName, CCfits::RWmode::Write); 1635 (fNumSubAndFitsData.numOpenFits)++; 1636 } 1637 catch (CCfits::FitsError e) 1638 { 1639 stringstream str; 1640 str << "Could not open FITS Run file " << partialName << " reason: " << e.message(); 1641 Error(str); 1642 fRunFitsFile = NULL; 1643 } 1644 1645 string actualTargetDir; 1646 if (fRunFileName == ".") 1647 { 1648 char currentPath[FILENAME_MAX]; 1649 if (getcwd(currentPath, sizeof(currentPath))) 1650 actualTargetDir = currentPath; 1651 } 1652 else 1653 { 1654 actualTargetDir = fRunFileName; 1655 } 1656 NotifyOpenedFile(actualTargetDir + '/' + sRun.str(), 7, fOpenedRunFiles);// + '_' + serviceName, 4); 1657 if (hasGrouping) 1658 sub.runFile.Open(partialName, serviceName, fRunFitsFile, &fNumSubAndFitsData.numOpenFits, this);//Out()); 1659 else 1660 sub.runFile.Open(partialName, serviceName, NULL, &fNumSubAndFitsData.numOpenFits, this);//Out()); 1661 1662 if (fNumSubAndFitsIsOn) 1663 fNumSubAndFits->updateService(); 1664 if (fDebugIsOn) 1665 { 1666 stringstream str; 1667 str << "Opened Run FITS: " << partialName << " and table: FACT-" << serviceName << ".current number of opened FITS: " << fNumSubAndFitsData.numOpenFits; 1668 Debug(str.str()); 1669 } 1670 } 1671 } 1663 1672 // -------------------------------------------------------------------------- 1664 1673 // 1665 1674 void DataLogger::AllocateFITSBuffers(SubscriptionType& sub) 1666 1675 { 1667 int size = sub.dimInfo->getSize();1668 1669 //Init the time columns of the file1670 Description dateDesc(std::string("Time"), std::string("Modified Julian Date"), std::string("MjD"));1671 sub.nightlyFile.AddStandardColumn(dateDesc, "1D", &fMjD, sizeof(double));1672 sub.runFile.AddStandardColumn(dateDesc, "1D", &fMjD, sizeof(double));1673 1674 Description QoSDesc("Qos", "Quality of service", "None");1675 sub.nightlyFile.AddStandardColumn(QoSDesc, "1J", &fQuality, sizeof(int));1676 sub.runFile.AddStandardColumn(QoSDesc, "1J", &fQuality, sizeof(int));1677 1678 const Converter::FormatList flist = sub.fConv->GetList();1676 int size = sub.dimInfo->getSize(); 1677 1678 //Init the time columns of the file 1679 Description dateDesc(string("Time"), string("Modified Julian Date"), string("MjD")); 1680 sub.nightlyFile.AddStandardColumn(dateDesc, "1D", &fMjD, sizeof(double)); 1681 sub.runFile.AddStandardColumn(dateDesc, "1D", &fMjD, sizeof(double)); 1682 1683 Description QoSDesc("Qos", "Quality of service", "None"); 1684 sub.nightlyFile.AddStandardColumn(QoSDesc, "1J", &fQuality, sizeof(int)); 1685 sub.runFile.AddStandardColumn(QoSDesc, "1J", &fQuality, sizeof(int)); 1686 1687 const Converter::FormatList flist = sub.fConv->GetList(); 1679 1688 // Compilation failed 1680 1689 if (flist.empty() || flist.back().first.second!=0) 1681 1690 { 1682 Error("Compilation of format string failed.");1691 Error("Compilation of format string failed."); 1683 1692 return; 1684 1693 } 1685 1694 1686 //we've got a nice structure describing the format of this service's messages. 1687 //Let's create the appropriate FITS columns 1688 std::vector<std::string> dataFormatsLocal; 1689 for (unsigned int i=0;i<flist.size()-1;i++) 1690 { 1691 std::stringstream dataQualifier; 1692 1693 dataQualifier << flist[i].second.first; 1694 switch (flist[i].first.first->name()[0]) 1695 {//TODO handle all the data format cases 1696 case 'c': 1697 case 'C': 1698 dataQualifier.str("S"); 1699 break; 1700 case 's': 1701 dataQualifier << "I"; 1702 break; 1703 case 'i': 1704 case 'I': 1705 dataQualifier << "J"; 1706 break; 1707 case 'l': 1708 case 'L': 1709 dataQualifier << "J"; 1710 //TODO triple check that in FITS, long = int 1711 break; 1712 case 'f': 1713 case 'F': 1714 dataQualifier << "E"; 1715 break; 1716 case 'd': 1717 case 'D': 1718 dataQualifier << "D"; 1719 break; 1720 case 'x': 1721 case 'X': 1722 dataQualifier << "K"; 1723 break; 1724 case 'S': 1725 //for strings, the number of elements I get is wrong. Correct it 1726 dataQualifier.str(""); //clear 1727 dataQualifier << size-1 << "A"; 1728 size = size-1; 1729 break; 1730 1731 default: 1732 Fatal("THIS SHOULD NEVER BE REACHED. dataLogger.cc ln 1198."); 1733 }; 1734 //we skip the variable length strings for now (in fits only) 1735 if (dataQualifier.str() != "S") 1736 dataFormatsLocal.push_back(dataQualifier.str()); 1737 } 1738 sub.nightlyFile.InitDataColumns(fServiceList.GetDescriptions(sub.dimInfo->getName()), dataFormatsLocal, sub.dimInfo->getData(), size); 1739 sub.runFile.InitDataColumns(fServiceList.GetDescriptions(sub.dimInfo->getName()), dataFormatsLocal, sub.dimInfo->getData(), size); 1695 //we've got a nice structure describing the format of this service's messages. 1696 //Let's create the appropriate FITS columns 1697 vector<string> dataFormatsLocal; 1698 for (unsigned int i=0;i<flist.size()-1;i++) 1699 { 1700 stringstream dataQualifier; 1701 1702 dataQualifier << flist[i].second.first; 1703 switch (flist[i].first.first->name()[0]) 1704 { 1705 case 'c': 1706 case 'C': 1707 dataQualifier.str("S"); 1708 break; 1709 case 's': 1710 dataQualifier << "I"; 1711 break; 1712 case 'i': 1713 case 'I': 1714 dataQualifier << "J"; 1715 break; 1716 case 'l': 1717 case 'L': 1718 dataQualifier << "J"; 1719 break; 1720 case 'f': 1721 case 'F': 1722 dataQualifier << "E"; 1723 break; 1724 case 'd': 1725 case 'D': 1726 dataQualifier << "D"; 1727 break; 1728 case 'x': 1729 case 'X': 1730 dataQualifier << "K"; 1731 break; 1732 case 'S': 1733 //for strings, the number of elements I get is wrong. Correct it 1734 dataQualifier.str(""); //clear 1735 dataQualifier << size-1 << "A"; 1736 size = size-1; 1737 break; 1738 1739 default: 1740 Fatal("THIS SHOULD NEVER BE REACHED. dataLogger.cc ln 1198."); 1741 }; 1742 //we skip the variable length strings for now (in fits only) 1743 if (dataQualifier.str() != "S") 1744 dataFormatsLocal.push_back(dataQualifier.str()); 1745 } 1746 sub.nightlyFile.InitDataColumns(fServiceList.GetDescriptions(sub.dimInfo->getName()), dataFormatsLocal, sub.dimInfo->getData(), size); 1747 sub.runFile.InitDataColumns(fServiceList.GetDescriptions(sub.dimInfo->getName()), dataFormatsLocal, sub.dimInfo->getData(), size); 1740 1748 } 1741 1749 // -------------------------------------------------------------------------- … … 1745 1753 void DataLogger::WriteToFITS(SubscriptionType& sub) 1746 1754 { 1747 //nightly File status (open or not) already checked1748 if (sub.nightlyFile.IsOpen())1749 {1750 sub.nightlyFile.Write(sub.fConv);1751 if (fDebugIsOn)1752 {1753 Debug("Writing to nightly FITS " + sub.nightlyFile.fFileName); 1754 }1755 }1756 if (sub.runFile.IsOpen())1757 {1758 sub.runFile.Write(sub.fConv);1759 if (fDebugIsOn)1760 {1761 Debug("Writing to Run FITS " + sub.runFile.fFileName); 1762 }1763 }1755 //nightly File status (open or not) already checked 1756 if (sub.nightlyFile.IsOpen()) 1757 { 1758 sub.nightlyFile.Write(sub.fConv); 1759 if (fDebugIsOn) 1760 { 1761 Debug("Writing to nightly FITS " + sub.nightlyFile.fFileName); 1762 } 1763 } 1764 if (sub.runFile.IsOpen()) 1765 { 1766 sub.runFile.Write(sub.fConv); 1767 if (fDebugIsOn) 1768 { 1769 Debug("Writing to Run FITS " + sub.runFile.fFileName); 1770 } 1771 } 1764 1772 } 1765 1773 #endif //if has_fits … … 1770 1778 //! and tries to open it. 1771 1779 //! @returns 1772 //! kSM_Logging if success, kSM_BadRunConfig if failure.1780 //! kSM_Logging if success, kSM_BadRunConfig if failure. 1773 1781 int DataLogger::StartRunPlease() 1774 1782 { 1775 if (fDebugIsOn) 1776 { 1777 Debug("Starting Run Logging..."); 1778 } 1779 //attempt to open run file with current parameters 1780 // if (fRunNumber == -1) 1781 // return kSM_BadRunConfig; 1782 std::stringstream sRun; 1783 sRun << fRunNumber; 1784 fFullRunLogFileName = fRunFileName + '/' + sRun.str() + ".log"; 1785 fRunLogFile.open(fFullRunLogFileName.c_str(), std::ios_base::out | std::ios_base::app); //maybe should be app instead of ate 1786 if (errno != 0) 1787 { 1788 std::stringstream str; 1789 str << "Unable to open run Log " << fFullRunLogFileName << ". Reason: " << strerror(errno) << " [" << errno << "]"; 1790 Error(str); 1791 } 1792 fFullRunReportFileName = fRunFileName + '/' + sRun.str() + ".rep"; 1793 fRunReportFile.open(fFullRunReportFileName.c_str(), std::ios_base::out | std::ios_base::app); 1794 if (errno != 0) 1795 { 1796 std::stringstream str; 1797 str << "Unable to open run report " << fFullRunReportFileName << ". Reason: " << strerror(errno) << " [" << errno << "]"; 1798 Error(str); 1799 } 1800 1801 if (!fRunLogFile.is_open() || !fRunReportFile.is_open()) 1802 { 1803 //TODO send an error message 1804 return kSM_BadRunConfig; 1805 } 1806 //get the size of the newly opened file. 1807 struct stat st; 1808 fBaseSizeRun = 0; 1809 if (fFileSizesMap.find(fFullRunLogFileName) == fFileSizesMap.end()) 1810 { 1811 stat(fFullRunLogFileName.c_str(), &st); 1812 if (errno != 0) 1813 { 1814 std::stringstream str; 1815 str << "Unable to stat " << fFullRunLogFileName << ". Reason: " << strerror(errno) << " [" << errno << "]"; 1816 Error(str); 1817 } 1818 else 1819 fBaseSizeRun += st.st_size; 1820 fFileSizesMap[fFullRunLogFileName] = 0; 1821 } 1822 if (fFileSizesMap.find(fFullRunReportFileName) == fFileSizesMap.end()) 1823 { 1824 stat(fFullRunReportFileName.c_str(), &st); 1825 if (errno != 0) 1826 { 1827 std::stringstream str; 1828 str << "Unable to stat " << fFullRunReportFileName << ". Reason: " << strerror(errno) << " [" << errno << "]"; 1829 Error(str); 1830 } 1831 else 1832 fBaseSizeRun += st.st_size; 1833 fFileSizesMap[fFullRunReportFileName] = 0; 1834 } 1835 std::string actualTargetDir; 1836 if (fRunFileName == ".") 1837 { 1838 char currentPath[FILENAME_MAX]; 1839 if (!getcwd(currentPath, sizeof(currentPath))) 1840 { 1841 if (errno != 0) 1842 { 1843 std::stringstream str; 1844 str << "Unable to retrieve the current path" << ". Reason: " << strerror(errno) << " [" << errno << "]"; 1845 Error(str); 1846 } 1847 } 1848 actualTargetDir = currentPath; 1849 } 1850 else 1851 { 1852 actualTargetDir = fRunFileName; 1853 } 1854 NotifyOpenedFile(actualTargetDir + '/' + sRun.str(), 3, fOpenedRunFiles); 1855 1856 fOpenedRunFits.clear(); 1857 1858 return kSM_Logging; 1783 if (fDebugIsOn) 1784 { 1785 Debug("Starting Run Logging..."); 1786 } 1787 //attempt to open run file with current parameters 1788 // if (fRunNumber == -1) 1789 // return kSM_BadRunConfig; 1790 stringstream sRun; 1791 sRun << fRunNumber; 1792 fFullRunLogFileName = fRunFileName + '/' + sRun.str() + ".log"; 1793 fRunLogFile.open(fFullRunLogFileName.c_str(), ios_base::out | ios_base::app); //maybe should be app instead of ate 1794 if (errno != 0) 1795 { 1796 stringstream str; 1797 str << "Unable to open run Log " << fFullRunLogFileName << ". Reason: " << strerror(errno) << " [" << errno << "]"; 1798 Error(str); 1799 } 1800 fFullRunReportFileName = fRunFileName + '/' + sRun.str() + ".rep"; 1801 fRunReportFile.open(fFullRunReportFileName.c_str(), ios_base::out | ios_base::app); 1802 if (errno != 0) 1803 { 1804 stringstream str; 1805 str << "Unable to open run report " << fFullRunReportFileName << ". Reason: " << strerror(errno) << " [" << errno << "]"; 1806 Error(str); 1807 } 1808 1809 if (!fRunLogFile.is_open() || !fRunReportFile.is_open()) 1810 { 1811 stringstream str; 1812 str << "Something went wrong while openning nightly files " << fFullRunLogFileName << " and " << fFullRunReportFileName; 1813 Error(str.str()); 1814 return kSM_BadRunConfig; 1815 } 1816 //get the size of the newly opened file. 1817 struct stat st; 1818 fBaseSizeRun = 0; 1819 if (fFileSizesMap.find(fFullRunLogFileName) == fFileSizesMap.end()) 1820 { 1821 stat(fFullRunLogFileName.c_str(), &st); 1822 if (errno != 0) 1823 { 1824 stringstream str; 1825 str << "Unable to stat " << fFullRunLogFileName << ". Reason: " << strerror(errno) << " [" << errno << "]"; 1826 Error(str); 1827 } 1828 else 1829 fBaseSizeRun += st.st_size; 1830 fFileSizesMap[fFullRunLogFileName] = 0; 1831 } 1832 if (fFileSizesMap.find(fFullRunReportFileName) == fFileSizesMap.end()) 1833 { 1834 stat(fFullRunReportFileName.c_str(), &st); 1835 if (errno != 0) 1836 { 1837 stringstream str; 1838 str << "Unable to stat " << fFullRunReportFileName << ". Reason: " << strerror(errno) << " [" << errno << "]"; 1839 Error(str); 1840 } 1841 else 1842 fBaseSizeRun += st.st_size; 1843 fFileSizesMap[fFullRunReportFileName] = 0; 1844 } 1845 string actualTargetDir; 1846 if (fRunFileName == ".") 1847 { 1848 char currentPath[FILENAME_MAX]; 1849 if (!getcwd(currentPath, sizeof(currentPath))) 1850 { 1851 if (errno != 0) 1852 { 1853 stringstream str; 1854 str << "Unable to retrieve the current path" << ". Reason: " << strerror(errno) << " [" << errno << "]"; 1855 Error(str); 1856 } 1857 } 1858 actualTargetDir = currentPath; 1859 } 1860 else 1861 { 1862 actualTargetDir = fRunFileName; 1863 } 1864 NotifyOpenedFile(actualTargetDir + '/' + sRun.str(), 3, fOpenedRunFiles); 1865 1866 fOpenedRunFits.clear(); 1867 1868 return kSM_Logging; 1859 1869 } 1860 1870 #ifdef HAVE_FITS 1861 1871 void DataLogger::CreateFitsGrouping(bool runGroup) 1862 1872 { 1863 //create the FITS group corresponding to the ending run.ETIENNEICI 1873 if (fDebugIsOn) 1874 { 1875 stringstream str; 1876 str << "Creating fits group for "; 1877 if (runGroup) 1878 str << "run files"; 1879 else 1880 str << "nightly files"; 1881 Debug(str.str()); 1882 } 1883 //create the FITS group corresponding to the ending run. 1864 1884 CCfits::FITS* groupFile; 1865 1866 #ifdef ONE_RUN_FITS_ONLY 1867 if (runGroup) 1868 return; 1869 #endif 1870 map<string, string>& filesToGroup = runGroup? fOpenedRunFits : fOpenedNightlyFits; 1871 unsigned int numFilesToGroup = filesToGroup.size(); 1885 map<string, vector<string> >& filesToGroup = runGroup? fOpenedRunFits : fOpenedNightlyFits; 1886 unsigned int numFilesToGroup = 0; 1887 for (map<string, vector<string> >::iterator it=filesToGroup.begin(); it != filesToGroup.end(); it++) 1888 { 1889 numFilesToGroup += it->second.size(); 1890 } 1891 if (fDebugIsOn) 1892 { 1893 stringstream str; 1894 str << "There are " << numFilesToGroup << " tables to group"; 1895 Debug(str.str()); 1896 } 1872 1897 if (numFilesToGroup <= 1) 1873 1898 { … … 1883 1908 { 1884 1909 Time time; 1885 st d::stringstream sTime;1910 stringstream sTime; 1886 1911 sTime << time.Y() << "_" << time.M() << "_" << time.D(); 1887 1912 1888 1913 groupName << fNightlyFileName << '/' << sTime.str() << ".fits"; 1889 1914 } 1915 CCfits::Table* groupTable; 1916 int maxCharLength = 50;//FILENAME_MAX; 1890 1917 try 1891 1918 { 1892 1919 groupFile = new CCfits::FITS(groupName.str(), CCfits::RWmode::Write); 1893 1920 //setup the column names 1894 int maxCharLength = FILENAME_MAX;1895 1921 stringstream pathTypeName; 1896 1922 pathTypeName << maxCharLength << "A"; … … 1905 1931 names.push_back("MEMBER_NAME"); 1906 1932 dataTypes.push_back(pathTypeName.str()); 1907 CCfits::Table* groupTable = groupFile->addTable("GROUPING", numFilesToGroup, names, dataTypes); 1933 1934 groupTable = groupFile->addTable("GROUPING", numFilesToGroup, names, dataTypes); 1908 1935 } 1909 1936 catch (CCfits::FitsError e) 1910 1937 { 1911 st d::stringstream str;1938 stringstream str; 1912 1939 str << "Could not open or create FITS table GROUPING in file " << groupName.str() << " reason: " << e.message(); 1913 1940 Error(str); … … 1920 1947 //create appropriate buffer. 1921 1948 unsigned char* fitsBuffer = new unsigned char[8 + 3 + 2*maxCharLength + 1]; //+1 for trailling character 1949 memset(fitsBuffer, 0, 8 + 3 + 2*maxCharLength + 1); 1922 1950 char* startOfExtension = reinterpret_cast<char*>(fitsBuffer); 1923 1951 char* startOfURI = reinterpret_cast<char*>(&fitsBuffer[8]); 1924 1952 char* startOfLocation = reinterpret_cast<char*>(&fitsBuffer[8 + 3]); 1925 1953 char* startOfName = reinterpret_cast<char*>(&fitsBuffer[8+3+maxCharLength]); 1954 // char* startOfNameVisible = reinterpret_cast<char*>(&fitsBuffer[8 + 3 + 2*maxCharLength]); 1926 1955 sprintf(startOfExtension, "%s", "BINTABLE"); 1927 1956 sprintf(startOfURI, "%s", "URL"); 1928 1957 int i=1; 1929 for (map<string, string>::iterator it=filesToGroup.begin(); it!=filesToGroup.end(); it++, i++) 1930 { 1931 strcpy(startOfLocation, it->first.c_str()); 1932 strcpy(startOfName, it->second.c_str()); 1933 int status = 0; 1934 fits_write_tblbytes(groupFile->fitsPointer(), i, 1, 8+3+2*maxCharLength, fitsBuffer, &status); 1935 if (status) 1936 { 1937 stringstream str; 1938 str << "Could not write row #" << i << "In the fits grouping file " << groupName << ". Cfitsio error code: " << status; 1939 Error(str.str()); 1940 } 1941 } 1958 for (map<string, vector<string> >::iterator it=filesToGroup.begin(); it!=filesToGroup.end(); it++) 1959 for (vector<string>::iterator jt=it->second.begin(); jt != it->second.end(); jt++, i++) 1960 { 1961 strcpy(startOfLocation, it->first.c_str()); 1962 strcpy(startOfName, jt->c_str()); 1963 if (fDebugIsOn) 1964 { 1965 stringstream str; 1966 str << "Grouping " << it->first << " " << *jt; 1967 Debug(str.str()); 1968 } 1969 // strcpy(startOfNameVisible, jt->c_str()); 1970 int status = 0; 1971 fits_write_tblbytes(groupFile->fitsPointer(), i, 1, 8+3+2*maxCharLength, fitsBuffer, &status); 1972 if (status) 1973 { 1974 stringstream str; 1975 str << "Could not write row #" << i << "In the fits grouping file " << groupName << ". Cfitsio error code: " << status; 1976 Error(str.str()); 1977 } 1978 } 1942 1979 1943 1980 filesToGroup.clear(); … … 1950 1987 //! Attempts to close the run file. 1951 1988 //! @returns 1952 //! kSM_WaitingRun if success, kSM_FatalError otherwise1989 //! kSM_WaitingRun if success, kSM_FatalError otherwise 1953 1990 int DataLogger::StopRunPlease() 1954 1991 { 1955 1992 1956 if (fDebugIsOn)1957 {1958 Debug("Stopping Run Logging..."); 1959 }1960 if (!fRunLogFile.is_open() || !fRunReportFile.is_open())1961 return kSM_FatalError;1962 if (fRunLogFile.is_open())1963 fRunLogFile.close();1964 if (fRunReportFile.is_open())1965 fRunReportFile.close();1993 if (fDebugIsOn) 1994 { 1995 Debug("Stopping Run Logging..."); 1996 } 1997 if (!fRunLogFile.is_open() || !fRunReportFile.is_open()) 1998 return kSM_FatalError; 1999 if (fRunLogFile.is_open()) 2000 fRunLogFile.close(); 2001 if (fRunReportFile.is_open()) 2002 fRunReportFile.close(); 1966 2003 #ifdef HAVE_FITS 1967 for (SubscriptionsListType::iterator i = fServiceSubscriptions.begin(); i != fServiceSubscriptions.end(); i++) 1968 for (std::map<std::string, SubscriptionType>::iterator j = i->second.begin(); j != i->second.end(); j++) 1969 { 1970 if (j->second.runFile.IsOpen()) 1971 j->second.runFile.Close(); 1972 } 1973 #ifdef ONE_RUN_FITS_ONLY 1974 if (fRunFitsFile != NULL) 1975 { 1976 delete fRunFitsFile; 1977 fRunFitsFile = NULL; 1978 (fNumSubAndFitsData.numOpenFits)--; 1979 } 2004 for (SubscriptionsListType::iterator i = fServiceSubscriptions.begin(); i != fServiceSubscriptions.end(); i++) 2005 for (map<string, SubscriptionType>::iterator j = i->second.begin(); j != i->second.end(); j++) 2006 { 2007 if (j->second.runFile.IsOpen()) 2008 j->second.runFile.Close(); 2009 } 2010 if (fRunFitsFile != NULL) 2011 { 2012 delete fRunFitsFile; 2013 fRunFitsFile = NULL; 2014 (fNumSubAndFitsData.numOpenFits)--; 2015 } 1980 2016 #endif 1981 #endif 1982 NotifyOpenedFile("", 0, fOpenedRunFiles); 1983 if (fNumSubAndFitsIsOn) 1984 fNumSubAndFits->updateService(); 1985 1986 CreateFitsGrouping(true); 1987 1988 return kSM_WaitingRun; 2017 NotifyOpenedFile("", 0, fOpenedRunFiles); 2018 if (fNumSubAndFitsIsOn) 2019 fNumSubAndFits->updateService(); 2020 2021 CreateFitsGrouping(true); 2022 2023 return kSM_WaitingRun; 1989 2024 1990 2025 } … … 1994 2029 //! Attempts to close any openned file. 1995 2030 //! @returns 1996 //! kSM_Ready2031 //! kSM_Ready 1997 2032 int DataLogger::GoToReadyPlease() 1998 2033 { 1999 if (fDebugIsOn)2000 {2001 Debug("Going to the Ready state...");2002 } 2003 if (fNightlyLogFile.is_open())2004 fNightlyLogFile.close();2005 if (fNightlyReportFile.is_open())2006 fNightlyReportFile.close();2007 2008 if (fRunLogFile.is_open())2009 fRunLogFile.close();2010 if (fRunReportFile.is_open())2011 fRunReportFile.close();2012 2034 if (fDebugIsOn) 2035 { 2036 Debug("Going to the Ready state..."); 2037 } 2038 if (fNightlyLogFile.is_open()) 2039 fNightlyLogFile.close(); 2040 if (fNightlyReportFile.is_open()) 2041 fNightlyReportFile.close(); 2042 2043 if (fRunLogFile.is_open()) 2044 fRunLogFile.close(); 2045 if (fRunReportFile.is_open()) 2046 fRunReportFile.close(); 2047 2013 2048 #ifdef HAVE_FITS 2014 for (SubscriptionsListType::iterator i = fServiceSubscriptions.begin(); i != fServiceSubscriptions.end(); i++) 2015 for (std::map<std::string, SubscriptionType>::iterator j = i->second.begin(); j != i->second.end(); j++) 2016 { 2017 if (j->second.nightlyFile.IsOpen()) 2018 j->second.nightlyFile.Close(); 2019 if (j->second.runFile.IsOpen()) 2020 j->second.runFile.Close(); 2021 } 2022 #ifdef ONE_RUN_FITS_ONLY 2023 if (fRunFitsFile != NULL) 2024 { 2025 delete fRunFitsFile; 2026 fRunFitsFile = NULL; 2027 (fNumSubAndFitsData.numOpenFits)--; 2028 } 2049 for (SubscriptionsListType::iterator i = fServiceSubscriptions.begin(); i != fServiceSubscriptions.end(); i++) 2050 for (map<string, SubscriptionType>::iterator j = i->second.begin(); j != i->second.end(); j++) 2051 { 2052 if (j->second.nightlyFile.IsOpen()) 2053 j->second.nightlyFile.Close(); 2054 if (j->second.runFile.IsOpen()) 2055 j->second.runFile.Close(); 2056 } 2057 if (fRunFitsFile != NULL) 2058 { 2059 delete fRunFitsFile; 2060 fRunFitsFile = NULL; 2061 (fNumSubAndFitsData.numOpenFits)--; 2062 } 2029 2063 #endif 2030 #endif 2031 if (GetCurrentState() == kSM_Logging) 2032 NotifyOpenedFile("", 0, fOpenedRunFiles); 2033 if (GetCurrentState() == kSM_Logging || 2034 GetCurrentState() == kSM_WaitingRun || 2035 GetCurrentState() == kSM_NightlyOpen) 2036 { 2037 NotifyOpenedFile("", 0, fOpenedNightlyFiles); 2038 if (fNumSubAndFitsIsOn) 2039 fNumSubAndFits->updateService(); 2040 } 2041 CreateFitsGrouping(true); 2042 CreateFitsGrouping(false); 2043 2044 return kSM_Ready; 2064 if (GetCurrentState() == kSM_Logging) 2065 NotifyOpenedFile("", 0, fOpenedRunFiles); 2066 if (GetCurrentState() == kSM_Logging || 2067 GetCurrentState() == kSM_WaitingRun || 2068 GetCurrentState() == kSM_NightlyOpen) 2069 { 2070 NotifyOpenedFile("", 0, fOpenedNightlyFiles); 2071 if (fNumSubAndFitsIsOn) 2072 fNumSubAndFits->updateService(); 2073 } 2074 CreateFitsGrouping(true); 2075 CreateFitsGrouping(false); 2076 2077 return kSM_Ready; 2045 2078 } 2046 2079 // -------------------------------------------------------------------------- … … 2048 2081 //! Implements the transition towards kSM_WaitingRun 2049 2082 //! Does nothing really. 2050 //! @returns2051 //! kSM_WaitingRun2083 //! @returns 2084 //! kSM_WaitingRun 2052 2085 int DataLogger::NightlyToWaitRunPlease() 2053 2086 { 2054 if (fDebugIsOn)2055 {2056 Debug("Going to Wait Run Number state..."); 2057 }2058 return kSM_WaitingRun; 2087 if (fDebugIsOn) 2088 { 2089 Debug("Going to Wait Run Number state..."); 2090 } 2091 return kSM_WaitingRun; 2059 2092 } 2060 2093 … … 2063 2096 fDebugIsOn = conf.Get<bool>("debug"); 2064 2097 2065 //Set the block or allow list2066 fBlackList.clear();2067 fWhiteList.clear();2098 //Set the block or allow list 2099 fBlackList.clear(); 2100 fWhiteList.clear(); 2068 2101 if (conf.Has("block")) 2069 2102 { 2070 vector<string> vec = conf.Get<vector<string>>("block");2071 if (vec.size() != 0)2072 {2073 fHasBlackList = true;2074 if (fDebugIsOn)2075 Debug("Setting BLOCK list:");2076 }2077 for (vector<string>::iterator it = vec.begin(); it != vec.end(); it++)2078 {2079 fBlackList.insert(*it);2080 if (fDebugIsOn)2081 Debug(" " + *it);2082 }2103 vector<string> vec = conf.Get<vector<string>>("block"); 2104 if (vec.size() != 0) 2105 { 2106 fHasBlackList = true; 2107 if (fDebugIsOn) 2108 Debug("Setting BLOCK list:"); 2109 } 2110 for (vector<string>::iterator it = vec.begin(); it != vec.end(); it++) 2111 { 2112 fBlackList.insert(*it); 2113 if (fDebugIsOn) 2114 Debug(" " + *it); 2115 } 2083 2116 } 2084 2117 if (conf.Has("allow")) 2085 2118 { 2086 vector<string> vec = conf.Get<vector<string>>("allow"); 2087 if (vec.size() != 0) 2088 { 2089 fHasWhiteList = true; 2090 if (fDebugIsOn) 2091 Debug("Setting ALLOW list:"); 2092 } 2093 for (vector<string>::iterator it=vec.begin(); it != vec.end(); it++) 2094 { 2095 fWhiteList.insert(*it); 2096 if (fDebugIsOn) 2097 Debug(" " + *it); 2098 } 2119 vector<string> vec = conf.Get<vector<string>>("allow"); 2120 if (vec.size() != 0) 2121 { 2122 fHasWhiteList = true; 2123 if (fDebugIsOn) 2124 Debug("Setting ALLOW list:"); 2125 } 2126 for (vector<string>::iterator it=vec.begin(); it != vec.end(); it++) 2127 { 2128 fWhiteList.insert(*it); 2129 if (fDebugIsOn) 2130 Debug(" " + *it); 2131 } 2132 } 2133 //Set the grouping 2134 if (conf.Has("group")) 2135 { 2136 vector<string> vec = conf.Get<vector<string>>("group"); 2137 if (vec.size() != 0) 2138 if (fDebugIsOn) 2139 Debug("Setting GROUPING list:"); 2140 for (vector<string>::iterator it=vec.begin(); it != vec.end(); it++) 2141 { 2142 fGrouping.insert(*it); 2143 if (fDebugIsOn) 2144 Debug(" " + *it); 2145 } 2099 2146 } 2100 2147 return true; … … 2109 2156 //log.SetWindow(stdscr); 2110 2157 if (conf.Has("log")) 2111 if (!wout.OpenLogFile(conf.Get<st d::string>("log")))2112 wout << kRed << "ERROR - Couldn't open log-file " << conf.Get<st d::string>("log") << ": " << strerror(errno) << std::endl;2158 if (!wout.OpenLogFile(conf.Get<string>("log"))) 2159 wout << kRed << "ERROR - Couldn't open log-file " << conf.Get<string>("log") << ": " << strerror(errno) << endl; 2113 2160 2114 2161 // Start io_service.Run to use the StateMachineImp::Run() loop … … 2125 2172 void RunThread(DataLogger* logger) 2126 2173 { 2127 // This is necessary so that the StateMachine Thread can signal the2128 // Readline thread to exit2129 logger->Run(true);2130 Readline::Stop(); 2174 // This is necessary so that the StateMachine Thread can signal the 2175 // Readline thread to exit 2176 logger->Run(true); 2177 Readline::Stop(); 2131 2178 } 2132 2179 … … 2140 2187 2141 2188 if (conf.Has("log")) 2142 if (!wout.OpenLogFile(conf.Get<st d::string>("log")))2143 win << kRed << "ERROR - Couldn't open log-file " << conf.Get<st d::string>("log") << ": " << strerror(errno) << std::endl;2189 if (!wout.OpenLogFile(conf.Get<string>("log"))) 2190 win << kRed << "ERROR - Couldn't open log-file " << conf.Get<string>("log") << ": " << strerror(errno) << endl; 2144 2191 2145 2192 DataLogger logger(wout); … … 2149 2196 shell.SetReceiver(logger); 2150 2197 2151 boost::thread t(boost::bind(RunThread, &logger));2152 2153 shell.Run(); // Run the shell2154 2155 logger.Stop();2156 2157 //Wait until the StateMachine has finished its thread2158 //before returning and destroyinng the dim objects which might2159 //still be in use.2160 t.join();2198 boost::thread t(boost::bind(RunThread, &logger)); 2199 2200 shell.Run(); // Run the shell 2201 2202 logger.Stop(); 2203 2204 //Wait until the StateMachine has finished its thread 2205 //before returning and destroyinng the dim objects which might 2206 //still be in use. 2207 t.join(); 2161 2208 2162 2209 return 0; … … 2235 2282 po::options_description configs("Scheduler options"); 2236 2283 configs.add_options() 2237 ("block,b", vars<string>(), "Black-list of services") 2238 ("allow,a", vars<string>(), "White-list of services") 2239 ("debug", po_bool(), "Debug mode. Print clear text of received service reports to log-stream") 2284 ("block,b", vars<string>(), "Black-list of services") 2285 ("allow,a", vars<string>(), "White-list of services") 2286 ("debug", po_bool(), "Debug mode. Print clear text of received service reports to log-stream") 2287 ("group,g", vars<string>(), "Grouping of services into a single run-Fits") 2240 2288 ; 2241 2289 … … 2257 2305 vm = conf.Parse(argc, argv); 2258 2306 } 2259 catch ( std::exception &e)2307 catch (exception &e) 2260 2308 { 2261 2309 #if BOOST_VERSION > 104000 … … 2300 2348 return RunShell<LocalConsole>(conf); 2301 2349 } 2302 /* catch ( std::exception& e)2350 /* catch (exception& e) 2303 2351 { 2304 2352 cerr << "Exception: " << e.what() << endl;
Note:
See TracChangeset
for help on using the changeset viewer.
