26 #include <boost/algorithm/string/predicate.hpp> 43 for (vector<Description>::const_iterator it=fStandardColDesc.begin(); it != fStandardColDesc.end(); it++)
44 if (it->name == desc.
name)
47 fStandardColDesc.push_back(desc);
48 fStandardFormats.push_back(dataFormat);
49 fStandardPointers.push_back(dataPointer);
50 fStandardNumBytes.push_back(numDataBytes);
64 fDataFormats = dataFormat;
66 if ((desc.size() == 0) && (dataFormat.size() == 0))
75 (desc.size() == dataFormat.size()+1) ||
76 (desc.size() == dataFormat.size()+2)
83 fTableDesc = desc[0].comment;
84 if (fTableDesc.size() > 68)
86 out->
Warn(
"Table description '" + fTableDesc +
"' exceeds 68 chars... truncated.");
87 fTableDesc = fTableDesc.substr(0,68);
90 for (
unsigned int i=0;
i<dataFormat.size();
i++)
92 string name = desc[
i+1].name;
93 if (name.length() > 68)
95 out->
Warn(
"Column name '" + name +
"' exceeds 68 chars... truncated.");
96 name = name.substr(0, 68);
99 string comment = desc[
i+1].comment;
100 if (comment.length() + name.length() > 71)
102 out->
Warn(
"Column '" + name +
" / " + comment +
"' exceeds 68 chars... truncated.");
103 comment = comment.substr(0,68);
106 string unit = desc[
i+1].unit;
107 if (unit.length() > 68)
109 out->
Warn(
"Unit '" + name +
"' exceeds 68 chars... truncated.");
110 unit = comment.substr(0,68);
113 const size_t p = fDataFormats[
i].find_last_of(
'B');
114 if ((boost::iequals(unit,
"text") || boost::iequals(unit,
"string")) && p!=string::npos)
116 out->
Info(
"Column '" + name +
"' detected to be an ascii string (FITS format 'A').");
117 fDataFormats[
i].replace(p, 1,
"A");
120 fDataColDesc.push_back(
Description(name, comment, unit));
127 str <<
"Expected " << dataFormat.size() <<
" descriptions of columns, got " << (int)(desc.size())-1 <<
" for service: ";
133 out->
Warn(str.str());
136 fDataColDesc.clear();
138 for (
unsigned int i=0;
i<dataFormat.size();
i++)
142 fDataColDesc.push_back(
Description(stt.str(),
"",
""));
156 bool Fits::Open(
const string& fileName,
const string& tableName, uint32_t* fitsCounter,
MessageImp* out,
int runNumber,
FITS* file)
160 fFileName = fileName;
164 fMess->
Error(
"File already open...");
172 if (!fFile->OpenFile(fileName,
true))
175 fNumOpenFitsFiles = fitsCounter;
176 (*fNumOpenFitsFiles)++;
180 if (!fFile->SetFile(file))
186 for (
unsigned int i=0;
i<fStandardColDesc.size();
i++)
188 fFile->AddColumn(fStandardColDesc[
i].name, fStandardFormats[
i],
189 fStandardColDesc[i].unit);
192 for (
unsigned int i=0;
i<fDataColDesc.size();
i++)
194 string name = fDataColDesc[
i].name;
202 fFile->AddColumn(name, fDataFormats[
i], fDataColDesc[i].unit);
207 if (!fFile->OpenNewTable(tableName, 100))
212 string fileNameWithoutFits = fFileName.substr(0, fileName.size()-4);
214 while (counter < 100)
216 ostringstream newFileName;
217 newFileName << fileNameWithoutFits << counter <<
".fits";
218 ifstream testStream(newFileName.str().c_str());
221 if (rename(fFileName.c_str(), newFileName.str().c_str()))
233 if (!fFile->OpenFile(fileName,
true))
235 fNumOpenFitsFiles = fitsCounter;
236 (*fNumOpenFitsFiles)++;
240 if (!fFile->SetFile(file))
246 for (
unsigned int i=0;
i<fStandardColDesc.size();
i++)
248 fFile->AddColumn(fStandardColDesc[
i].name, fStandardFormats[
i],
249 fStandardColDesc[i].unit);
252 for (
unsigned int i=0;
i<fDataColDesc.size();
i++)
254 string name = fDataColDesc[
i].name;
262 fFile->AddColumn(name, fDataFormats[
i], fDataColDesc[i].unit);
264 if (!fFile->OpenNewTable(tableName, 100))
271 fCopyBuffer.resize(fFile->GetDataSize());
275 for (
unsigned int i=0;
i<fStandardColDesc.size();
i++)
278 str <<
"TTYPE" <<
i+1;
279 fFile->WriteKeyNT(str.str(), fStandardColDesc[
i].name, fStandardColDesc[
i].comment);
281 str <<
"TCOMM" << i+1;
282 fFile->WriteKeyNT(str.str(), fStandardColDesc[
i].comment,
"");
285 for (
unsigned int i=0;
i<fDataColDesc.size();
i++)
287 string name = fDataColDesc[
i].name;
295 str <<
"TTYPE" <<
i+fStandardColDesc.size()+1;
296 fFile->WriteKeyNT(str.str(), name, fDataColDesc[
i].comment);
298 str <<
"TCOMM" <<
i+fStandardColDesc.size()+1;
299 fFile->WriteKeyNT(str.str(), fDataColDesc[
i].comment,
"");
302 fFile->WriteKeyNT(
"COMMENT", fTableDesc,
"");
304 if (fFile->GetNumRows() == 0)
313 return fFile->GetNumRows()==0 ? WriteHeaderKeys() :
true;
315 catch (
const CCfits::FitsException &e)
317 cout <<
"Exception !" << endl;
318 fMess->Error(
"Opening or creating table '"+tableName+
"' in '"+fileName+
"': "+e.message());
320 fFile->fTable = NULL;
335 if (!fFile->WriteDefaultKeys(
"datalogger"))
338 if (!fFile->WriteKeyNT(
"TSTARTI", 0,
"Time when first event received (integral part)") ||
339 !fFile->WriteKeyNT(
"TSTARTF", 0,
"Time when first event received (fractional part)") ||
340 !fFile->WriteKeyNT(
"TSTOPI", 0,
"Time when last event received (integral part)") ||
341 !fFile->WriteKeyNT(
"TSTOPF", 0,
"Time when last event received (fractional part)") ||
342 !fFile->WriteKeyNT(
"DATE-OBS", 0,
"Time when first event received") ||
343 !fFile->WriteKeyNT(
"DATE-END", 0,
"Time when last event received") ||
344 !fFile->WriteKeyNT(
"RUNID",
fRunNumber,
"Run number. 0 means not run file"))
351 ostringstream corruptName;
354 corruptName << fFileName <<
"corrupt" << append;
355 while (!stat(corruptName.str().c_str(), &st))
359 corruptName << fFileName <<
"corrupt" << append;
361 if (rename(fFileName.c_str(), corruptName.str().c_str()) != 0)
364 str <<
"rename() failed for '" << fFileName <<
"': " << strerror(errno) <<
" [errno=" << errno <<
"]";
369 fMess->Message(
"Renamed file " + fFileName +
" to " + corruptName.str());
381 for (
unsigned int i=0;
i<fStandardNumBytes.size();
i++)
383 const char *charSrc =
reinterpret_cast<char*
>(fStandardPointers[
i]);
384 reverse_copy(charSrc, charSrc+fStandardNumBytes[
i], fCopyBuffer.data()+shift);
385 shift += fStandardNumBytes[
i];
390 conv.
ToFits(fCopyBuffer.data()+shift,
data, fCopyBuffer.size()-shift);
392 catch (
const runtime_error &e)
395 str << fFile->GetName() <<
": " << e.what();
402 if (!fFile->AddRow())
405 MoveFileToCorruptedFile();
408 if (!fFile->WriteData(fCopyBuffer))
413 const double tm = *
reinterpret_cast<double*
>(fStandardPointers[0]);
419 fFile->WriteKeyNT(
"TSTARTI", uint32_t(floor(tm)),
"Time when first event received (integral part)");
420 fFile->WriteKeyNT(
"TSTARTF", fmod(tm, 1),
"Time when first event received (fractional part)");
421 fFile->WriteKeyNT(
"TSTOPI", uint32_t(floor(fEndMjD)),
"Time when last event received (integral part)");
422 fFile->WriteKeyNT(
"TSTOPF", fmod(fEndMjD, 1),
"Time when last event received (fractional part)");
424 fFile->WriteKeyNT(
"DATE-OBS",
Time(tm+40587).Iso(),
425 "Time when first event received");
427 fFile->WriteKeyNT(
"DATE-END",
Time(fEndMjD+40587).Iso(),
428 "Time when last event received");
445 if (fFile->IsOpen() && fFile->IsOwner())
448 fFile->WriteKeyNT(
"TSTOPI", uint32_t(floor(fEndMjD)),
"Time when last event received (integral part)");
449 fFile->WriteKeyNT(
"TSTOPF", fmod(fEndMjD, 1),
"Time when last event received (fractional part)");
451 fFile->WriteKeyNT(
"DATE-END",
Time(fEndMjD+40587).Iso(),
452 "Time when last event received");
454 if (fFile->IsOwner())
456 if (fNumOpenFitsFiles != NULL)
457 (*fNumOpenFitsFiles)--;
459 const string name = fFile->GetName();
462 fMess->Info(
"Closed: "+name);
481 if (stat(fFile->GetName().c_str(), &st))
The base implementation of a distributed messaging system.
void InitDataColumns(const vector< Description > &desc, const vector< string > &dataFormat, MessageImp *out)
Adds columns specific to the service being logged.
Adds some functionality to boost::posix_time::ptime for our needs.
void AddStandardColumn(const Description &desc, const string &dataFormat, void *dataPointer, long unsigned int numDataBytes)
Adds a column that exists in all FITS files.
bool WriteHeaderKeys()
Write the FITS header keys.
bool Write(const Converter &conv, const void *data)
Write one line of data. Use the given converter.
A struct which stores a name, a unit and a comment.
void MoveFileToCorruptedFile()
int Error(const std::string &str)
int Warn(const std::string &str)
FITS writter for the FACT project.
int GetWrittenSize() const
Get the size currently written on the disk.
void Flush()
Flush the currently opened file to disk.
int Info(const std::string &str)
bool Open(const string &fileName, const string &tableName, uint32_t *fitsCounter, MessageImp *out, int runNumber, CCfits::FITS *file=0)
Opens a FITS file.
A compiler for the DIM data format string.
void Close()
Close the currently opened file.
void ToFits(void *dest, const void *src, size_t size) const