Changeset 10364 for trunk/FACT++
- Timestamp:
- 04/13/11 11:06:40 (14 years ago)
- Location:
- trunk/FACT++/src
- Files:
-
- 3 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/FACT++/src/Converter.cc
r10356 r10364 849 849 } 850 850 851 void Converter::ToFits(void* dest, const void* src, size_t size) 852 { 853 //crawl through the src buffer and copy the data appropriately to the destination buffer 854 //Assumption: the string is always last. This way we use the provided size to determine the number 855 //of character to copy 856 char * charDest = static_cast<char*>(dest); 857 const char* charSrc = static_cast<const char*>(src); 858 size_t cOffset = 0; 859 int elemSize = 0; 860 861 for (unsigned int i=0;i<fList.size()-1;i++) 862 { 863 if (fList[i].first.first->name()[0] == 'S') //string 864 { 865 for (size_t j=cOffset;j<size;j++) 866 charDest[j] = charSrc[j]; 867 continue; 868 } 851 852 void Converter::ToFits(void *dest, const void *src, size_t size) const 853 { 854 // crawl through the src buffer and copy the data appropriately to the 855 // destination buffer 856 // Assumption: the string is always last. This way we 857 // use the provided size to determine the number 858 // of character to copy 859 860 char *charDest = static_cast<char*>(dest); 861 const char *charSrc = static_cast<const char*>(src); 862 863 for (Converter::FormatList::const_iterator i=fList.begin(); i!=fList.end(); i++) 864 { 865 //ETIENNE this check fails for very fine cases. Disabled it 866 // FIXME: This is still not really safe 867 // if (charDest-size>=dest) 868 // { 869 // ostringstream err; 870 // err << "Format description [fmt=" << fFormat << "] exceeds available data size (" << size << ")"; 871 // throw runtime_error(err.str()); 872 // } 873 874 const char type = i->first.first->name()[0]; 875 876 // string types 877 if (type=='S' || type=='O' || type=='W') 878 { 879 // copy string until termination 880 while (*charSrc) 881 *charDest++ = *charSrc++; 882 883 // Copy \0-termination 884 //ETIENNE: Do not copy the \0 as it must not be written to fits files. just increment charSrc instead 885 // *charDest++ = *charSrc++; 886 charSrc++; 887 continue; 888 } 889 890 const int s = i->first.second; // size of element 891 const int n = i->second.first; // number of elements 892 893 // for all elements of this column 894 for (int j=0; j<n; j++) 895 { 896 //ETIENNE moved the +s-1 to the second argument and removed the -1 897 reverse_copy(charSrc, charSrc+s, charDest); 869 898 870 elemSize = fList[i].first.second; 871 for (int j=0;j<fList[i].second.first;j++)//for all elements of this column 872 { 873 for (int k=0;k<elemSize;k++)//swap the element bytes 874 charDest[cOffset+k] = charSrc[cOffset + elemSize - (k+1)]; 875 cOffset += elemSize; 876 } 877 } 878 } 879 880 881 882 883 884 885 886 899 charSrc += s; 900 charDest += s; 901 } 902 } 903 904 if (charDest-size!=dest) 905 { 906 ostringstream err; 907 err << "Data block size (" << size << ") doesn't fit format description [fmt=" << fFormat << "]"; 908 throw runtime_error(err.str()); 909 } 910 } 911 912 vector<char> Converter::ToFits(const void *src, size_t size) const 913 { 914 vector<char> dest(size); 915 ToFits(&dest[0], src, size); 916 return dest; 917 } 918 919 920 921 922 923 924 925 -
trunk/FACT++/src/Converter.h
r10356 r10364 91 91 static std::string GetHex(const void *d, size_t size, size_t chunk=1); 92 92 93 void ToFits(void* dest, const void* src, size_t size); 93 void ToFits(void* dest, const void* src, size_t size) const; 94 95 std::vector<char> ToFits(const void* src, size_t size) const; 94 96 95 97 /* -
trunk/FACT++/src/dataLogger.cc
r10330 r10364 52 52 #include "LocalControl.h" 53 53 54 //#define HAS_FITS 54 #include "Description.h" 55 56 #define HAS_FITS 55 57 56 58 #include <fstream> … … 59 61 60 62 #ifdef HAS_FITS 61 #include <astroroot.h> 63 //#include <astroroot.h> 64 #include "FactFits.h" 62 65 #endif 63 66 … … 96 99 int fRunNumber; 97 100 ///Current year 98 short fYear;101 // short fYear; 99 102 ///Current Month 100 short fMonth;103 // short fMonth; 101 104 ///Current Day 102 short fDay;105 // short fDay; 103 106 ///Current Hour 104 short fHour;107 // short fHour; 105 108 ///Current Minute 106 short fMin;109 // short fMin; 107 110 ///Current Second 108 short fSec;111 // short fSec; 109 112 ///Current Milliseconds 110 int fMs;113 // int fMs; 111 114 ///Current Service Quality 112 115 int fQuality; … … 152 155 #ifdef HAS_FITS 153 156 ///daily FITS output file 154 AstroRootIodailyFile;157 FactFits dailyFile; 155 158 ///run-specific FITS output file 156 AstroRootIorunFile;159 FactFits runFile; 157 160 #endif 158 161 ///the actual dimInfo pointer 159 162 DimStampedInfo* dimInfo; 163 ///the converter for outputting the data according to the format 164 Converter* fConv; 160 165 ///the number of existing handlers to this structure. 161 166 ///This is required otherwise I MUST handle the deleting of dimInfo outside from the destructor … … 169 174 dimInfo = other.dimInfo; 170 175 numCopies = other.numCopies; 176 fConv = other.fConv; 171 177 (*numCopies)++; 172 178 } … … 179 185 dimInfo = other.dimInfo; 180 186 numCopies = other.numCopies; 187 fConv = other.fConv; 181 188 (*numCopies)++; 182 189 } … … 184 191 { 185 192 dimInfo = info; 193 fConv = NULL; 186 194 numCopies = new int(1); 187 195 } … … 189 197 { 190 198 dimInfo = NULL; 199 fConv = NULL; 191 200 numCopies = new int(1); 192 201 } … … 208 217 if (numCopies) 209 218 delete numCopies; 219 delete fConv; 220 fConv = NULL; 210 221 dimInfo = NULL; 211 222 numCopies = NULL; … … 231 242 ///checks whether or not the current info being treated is a run number 232 243 void CheckForRunNumber(DimInfo* I); 233 234 244 /// start transition 235 245 int StartPlease(); … … 278 288 // 279 289 DataLogger::DataLogger(std::ostream &out) : StateMachineDim(out, "DATA_LOGGER") 280 { 290 { 281 291 //initialize member data 282 292 fDailyFileName = "/home/lyard/log"; … … 290 300 AddStateName(kSM_BadRunConfig, "ErrRunFolder"); 291 301 292 293 294 302 /*Add the possible transitions for this machine*/ 303 304 //start the daily logging. daily file location must be specified already 295 305 AddTransition(kSM_DailyOpen, fTransStart, kSM_Ready, kSM_BadDailyConfig). 296 306 AssignFunction(boost::bind(&DataLogger::StartPlease, this)); 297 307 298 308 //stop the data logging 299 309 AddTransition(kSM_Ready, fTransStop, kSM_DailyOpen, kSM_WaitingRun, kSM_Logging). 300 310 AssignFunction(boost::bind(&DataLogger::GoToReadyPlease, this)); 301 311 302 303 312 //start the run logging. run file location must be specified already. 313 AddTransition(kSM_Logging, fTransStartRun, kSM_WaitingRun, kSM_BadRunConfig). 304 314 AssignFunction(boost::bind(&DataLogger::StartRunPlease, this)); 305 315 306 316 AddTransition(kSM_WaitingRun, fTransStopRun, kSM_Logging). 307 317 AssignFunction(boost::bind(&DataLogger::StopRunPlease, this)); 308 318 309 319 //transition to exit error states. dunno if required or not, would close the daily file if already openned. 310 320 AddTransition(kSM_Ready, fTransReset, kSM_Error, kSM_BadDailyConfig, kSM_BadRunConfig, kSM_Error). 311 321 AssignFunction(boost::bind(&DataLogger::GoToReadyPlease, this)); 312 322 313 323 AddTransition(kSM_WaitingRun, fTransWait, kSM_DailyOpen). 314 324 AssignFunction(boost::bind(&DataLogger::DailyToWaitRunPlease, this)); 315 325 316 /*Add the possible configurations for this machine*/ 317 //configure the daily file location. cannot be done before the file is actually opened 326 /*Add the possible configurations for this machine*/ 327 328 //configure the daily file location. cannot be done before the file is actually opened 318 329 AddConfiguration(fConfigDay, "C", kSM_Ready, kSM_BadDailyConfig). 319 330 AssignFunction(boost::bind(&DataLogger::ConfigureDailyFileName, this, _1)); 320 331 321 332 //configure the run file location. cannot be done before the file is actually opened, and not in a dailly related error. 322 333 AddConfiguration(fConfigRun, "C", kSM_Ready, kSM_BadDailyConfig, kSM_DailyOpen, kSM_WaitingRun, kSM_BadRunConfig). 323 334 AssignFunction(boost::bind(&DataLogger::ConfigureRunFileName, this, _1)); … … 333 344 fServiceList.SetHandler(this); 334 345 CheckForServicesUpdate(); 346 335 347 } 336 348 // -------------------------------------------------------------------------- … … 341 353 //! add the configuration (using the conf class ?) 342 354 // 355 //FIXME The service must be udpated so that I get the first notification. This should not be 343 356 void DataLogger::CheckForServicesUpdate() 344 357 { … … 544 557 case kSM_Logging: 545 558 case kSM_DailyOpen: 546 //TODO check that this is indeed correct 547 return 0;//LogMessagePlease(evt); 559 return 0; 548 560 break; 549 561 550 562 } 551 //Getting here means that an invalid configuration has been asked. 552 //TODO Log an error message 553 //and return the fatal error state 563 554 564 return kSM_FatalError; 555 565 } … … 572 582 std::map<std::string, SubscriptionType>::iterator y; 573 583 for (x=fServiceSubscriptions.begin(); x != fServiceSubscriptions.end(); x++) 574 {// instead of extracting the server and service names, I crawl through my records. dunno what's faster, but both should work584 {//find current service is subscriptions 575 585 for (y=x->second.begin(); y!=x->second.end();y++) 576 586 if (y->second.dimInfo == I) … … 617 627 //! The current DimInfo 618 628 // 619 void DataLogger::ReportPlease(DimInfo* I, SubscriptionType& )629 void DataLogger::ReportPlease(DimInfo* I, SubscriptionType& sub) 620 630 { 621 631 //should we log or report this info ? (i.e. is it a message ?) 622 632 bool isItaReport = ((strstr(I->getName(), "Message") == NULL) && (strstr(I->getName(), "MESSAGE") == NULL)); 623 633 624 // std::ofstream & dailyFile = fDailyReportFile;//isItaReport? fDailyReportFile : fDailyLogFile;625 // std::ofstream & runFile = fRunReportFile;//isItaReport? fRunReportFile : fRunLogFile;626 627 634 //TODO add service exclusion 635 628 636 if (!fDailyReportFile.is_open()) 629 637 return; 638 639 //create the converter for that service 640 if (sub.fConv == NULL) 641 { 642 sub.fConv = new Converter(Out(), I->getFormat()); 643 if (!sub.fConv) 644 { 645 Error("Couldn't properly parse the format... service ignored."); 646 return; 647 } 648 } 630 649 631 650 //construct the header 632 651 std::stringstream header; 633 634 652 Time cTime((time_t)(I->getTimestamp()), I->getTimestampMillisecs()); 635 636 //Buffer them for FITS write 637 //TODO this has been replaced by MjD. So I guess that these member variables can go. 638 fYear = cTime.Y(); fMonth = cTime.M(); fDay = cTime.D(); 639 fHour = cTime.h(); fMin = cTime.m(); fSec = cTime.s(); 640 fMs = cTime.ms(); fQuality = I->getQuality(); 641 653 fQuality = I->getQuality(); 642 654 fMjD = cTime.Mjd(); 643 655 644 656 if (isItaReport) 645 657 { 646 658 //write text header 647 659 header << I->getName() << " " << fQuality << " "; 648 header << fYear << " " << fMonth << " " << fDay << " "; 649 header << fHour << " " << fMin << " " << fSec << " "; 650 header << fMs << " " << I->getTimestamp() << " "; 651 652 const Converter conv(Out(), I->getFormat()); 653 if (!conv) 654 { 655 Error("Couldn't properly parse the format... ignored."); 656 return; 657 } 658 659 std::string text; 660 try 661 { 662 text = conv.GetString(I->getData(), I->getSize()); 663 } 664 catch (const std::runtime_error &e) 665 { 666 Out() << kRed << e.what() << endl; 667 Error("Couldn't properly parse the data... ignored."); 668 return; 669 } 660 header << cTime.Y() << " " << cTime.M() << " " << cTime.D() << " "; 661 header << cTime.h() << " " << cTime.m() << " " << cTime.s() << " "; 662 header << cTime.ms() << " " << I->getTimestamp() << " "; 663 664 std::string text; 665 try 666 { 667 text = sub.fConv->GetString(I->getData(), I->getSize()); 668 } 669 catch (const std::runtime_error &e) 670 { 671 Out() << kRed << e.what() << endl; 672 Error("Couldn't properly parse the data... ignored."); 673 return; 674 } 670 675 671 676 if (text.empty()) 672 673 674 675 676 677 return; 678 679 //replace bizarre characters by white space 680 replace(text.begin(), text.end(), '\n', '\\'); 681 replace_if(text.begin(), text.end(), std::ptr_fun<int, int>(&std::iscntrl), ' '); 677 682 678 683 if (fDailyReportFile.is_open()) … … 681 686 fRunReportFile << header.str(); 682 687 683 688 if (fDailyReportFile.is_open()) 684 689 fDailyReportFile << text << std::endl; 685 690 if (fRunReportFile.is_open()) … … 699 704 } 700 705 } 701 706 702 707 #ifdef HAS_FITS 703 708 if (!sub.dailyFile.IsOpen() || !sub.runFile.IsOpen()) 704 709 OpenFITSFilesPlease(sub); 705 710 WriteToFITS(sub); 711 706 712 #endif 707 713 … … 718 724 //! I guess that this function should not be any longer 719 725 // 726 //TODO isn't that function not used any longer ? If so I guess that we should get rid of it... 720 727 int DataLogger::LogMessagePlease(const Event& evt) 721 728 { … … 729 736 header << cTime.ms() << " "; 730 737 731 // std::string text = ToString(evt.GetFormat().c_str(), evt.GetData(), evt.GetSize()); 732 733 const Converter conv(Out(), evt.GetFormat()); 734 if (!conv) 735 { 736 Error("Couldn't properly parse the format... ignored."); 737 return GetCurrentState(); 738 } 739 740 std::string text; 741 try 742 { 743 text = conv.GetString(evt.GetData(), evt.GetSize()); 744 } 745 catch (const std::runtime_error &e) 746 { 747 Out() << kRed << e.what() << endl; 748 Error("Couldn't properly parse the data... ignored."); 749 return GetCurrentState(); 750 } 751 752 753 if (text.empty()) 754 return GetCurrentState(); 755 756 //replace bizarre characters by white space 757 replace(text.begin(), text.end(), '\n', '\\'); 758 replace_if(text.begin(), text.end(), std::ptr_fun<int, int>(&std::iscntrl), ' '); 738 const Converter conv(Out(), evt.GetFormat()); 739 if (!conv) 740 { 741 Error("Couldn't properly parse the format... ignored."); 742 return GetCurrentState(); 743 } 744 745 std::string text; 746 try 747 { 748 text = conv.GetString(evt.GetData(), evt.GetSize()); 749 } 750 catch (const std::runtime_error &e) 751 { 752 Out() << kRed << e.what() << endl; 753 Error("Couldn't properly parse the data... ignored."); 754 return GetCurrentState(); 755 } 756 757 if (text.empty()) 758 return GetCurrentState(); 759 760 //replace bizarre characters by white space 761 replace(text.begin(), text.end(), '\n', '\\'); 762 replace_if(text.begin(), text.end(), std::ptr_fun<int, int>(&std::iscntrl), ' '); 759 763 760 764 if (fDailyLogFile.is_open()) … … 834 838 fullName = fDailyFileName + '/' + sTime.str() + ".rep"; 835 839 fDailyReportFile.open(fullName.c_str(), std::ios_base::out | std::ios_base::app); 840 836 841 if (!fDailyLogFile.is_open() || !fDailyReportFile.is_open()) 837 { 842 { 838 843 //TODO send an error message 839 844 return kSM_BadDailyConfig; 840 845 } 846 841 847 return kSM_DailyOpen; 842 848 } … … 866 872 { 867 873 std::string partialName = fDailyFileName + '/' + sTime.str() + '_' + serviceName + ".fits"; 868 std::string fullName = fDailyFileName + '/' + sTime.str() + '_' + serviceName + ".fits[" + serviceName + "]";869 870 874 AllocateFITSBuffers(sub); 871 //currently, the FITS are written in the same directory as the text files. 872 //thus the write permissions have already been checked by the text files. 873 //if the target folder changes, then I should check the write permissions here 874 //now we only check whether the target file exists or not 875 std::ifstream readTest(partialName.c_str()); 876 if (readTest.is_open()) 877 { 878 readTest.close(); 879 sub.dailyFile.Open(fullName.c_str(), "UPDATE"); 880 } 881 else { 882 sub.dailyFile.Open(fullName.c_str(), "CREATE"); 883 } 884 885 //TODO Write the header's attributes 875 sub.dailyFile.Open(partialName, serviceName); 886 876 } 887 877 if (!sub.runFile.IsOpen() && (GetCurrentState() == kSM_Logging)) … … 890 880 sRun << fRunNumber; 891 881 std::string partialName = fRunFileName + '/' + sRun.str() + '_' + serviceName + ".fits"; 892 std::string fullName = fRunFileName + '/' + sRun.str() + '_' + serviceName + ".fits[" + serviceName + "]"; 893 894 std::ifstream readTest(partialName.c_str()); 895 if (readTest.is_open()) 896 { 897 readTest.close(); 898 sub.runFile.Open(fullName.c_str(), "UPDATE"); 899 } 900 else 901 sub.runFile.Open(fullName.c_str(), "CREATE"); 902 //TODO Write the header's attributes 882 sub.runFile.Open(partialName, serviceName); 903 883 } 904 884 } … … 907 887 void DataLogger::AllocateFITSBuffers(SubscriptionType& sub) 908 888 { 909 const char* format = sub.dimInfo->getFormat(); 910 const int size = sub.dimInfo->getSize(); 889 int size = sub.dimInfo->getSize(); 911 890 912 //Init the time columns of the file 913 sub.dailyFile.InitCol("Date", "double", &fMjD); 914 sub.runFile.InitCol("Date", "double", &fMjD); 915 916 // sub.dailyFile.InitCol("Year", "short", &fYear); 917 // sub.dailyFile.InitCol("Month", "short", &fMonth); 918 // sub.dailyFile.InitCol("Day", "short", &fDay); 919 // sub.dailyFile.InitCol("Hour", "short", &fHour); 920 // sub.dailyFile.InitCol("Minute", "short", &fMin); 921 // sub.dailyFile.InitCol("Second", "short", &fSec); 922 // sub.dailyFile.InitCol("MilliSec", "int", &fMs); 923 sub.dailyFile.InitCol("QoS", "int", &fQuality); 924 925 // sub.runFile.InitCol("Year", "short", &fYear); 926 // sub.runFile.InitCol("Month", "short", &fMonth); 927 // sub.runFile.InitCol("Day", "short", &fDay); 928 // sub.runFile.InitCol("Hour", "short", &fHour); 929 // sub.runFile.InitCol("Minute", "short", &fMin); 930 // sub.runFile.InitCol("Second", "short", &fSec); 931 // sub.runFile.InitCol("MilliSec", "int", &fMs); 932 sub.runFile.InitCol("QoS", "int", &fQuality); 933 934 const Converter::FormatList flist = Converter::Compile(Out(), format); 935 936 // Compilation failed 937 if (fList.empty() || fList.back().first.second!=0) 938 { 939 Error("Compilation of format string failed."); 940 return; 941 } 942 943 //we've got a nice structure describing the format of this service's messages. 944 //Let's create the appropriate FITS columns 945 for (unsigned int i=0;i<flist.size();i++) 946 { 947 std::stringstream colName; 891 //Init the time columns of the file 892 Description dateDesc(std::string("Time"), std::string("MjD"), std::string("Modified Julian Date")); 893 sub.dailyFile.AddStandardColumn(dateDesc, "1D", &fMjD, sizeof(double)); 894 sub.runFile.AddStandardColumn(dateDesc, "1D", &fMjD, sizeof(double)); 895 896 Description QoSDesc("Qos", "None", "Quality of service"); 897 sub.dailyFile.AddStandardColumn(QoSDesc, "1J", &fQuality, sizeof(int)); 898 sub.runFile.AddStandardColumn(QoSDesc, "1J", &fQuality, sizeof(int)); 899 900 const Converter::FormatList flist = sub.fConv->GetList(); 901 // Compilation failed 902 if (flist.empty() || flist.back().first.second!=0) 903 { 904 Error("Compilation of format string failed."); 905 return; 906 } 907 908 //we've got a nice structure describing the format of this service's messages. 909 //Let's create the appropriate FITS columns 910 std::vector<std::string> dataFormatsLocal; 911 for (unsigned int i=0;i<flist.size()-1;i++) 912 { 948 913 std::stringstream dataQualifier; 949 void * dataPointer = static_cast<char*>(sub.dimInfo->getData()) + flist[i].second.second; 950 colName << "Data" << i; 914 951 915 dataQualifier << flist[i].second.first; 952 switch (flist[i].first.first )916 switch (flist[i].first.first->name()[0]) 953 917 { 954 918 case 'c': … … 978 942 dataQualifier.str(""); //clear 979 943 dataQualifier << size-1 << "A"; 944 size = size-1; 980 945 break; 981 946 982 947 default: 983 Error("THIS SHOULD NEVER BE REACHED. dataLogger.cc ln 9 62.");948 Error("THIS SHOULD NEVER BE REACHED. dataLogger.cc ln 948."); 984 949 }; 985 sub.dailyFile.InitCol(colName.str().c_str(), dataQualifier.str().c_str(), dataPointer); 986 sub.runFile.InitCol(colName.str().c_str(), dataQualifier.str().c_str(), dataPointer); 950 dataFormatsLocal.push_back(dataQualifier.str()); 987 951 } 988 952 989 //TODO init the attributes 953 sub.dailyFile.InitDataColumns(fServiceList.GetDescriptions(sub.dimInfo->getName()), dataFormatsLocal, sub.dimInfo->getData(), size); 954 sub.runFile.InitDataColumns(fServiceList.GetDescriptions(sub.dimInfo->getName()), dataFormatsLocal, sub.dimInfo->getData(), size); 990 955 } 991 956 // -------------------------------------------------------------------------- … … 997 962 //dailyFile status (open or not) already checked 998 963 if (sub.dailyFile.IsOpen()) 999 sub.dailyFile.Write( );964 sub.dailyFile.Write(sub.fConv); 1000 965 if (sub.runFile.IsOpen()) 1001 sub.runFile.Write( );966 sub.runFile.Write(sub.fConv); 1002 967 } 1003 968 #endif //if has_fits … … 1131 1096 1132 1097 logger.SetReady(); 1098 // logger.StartPlease(); 1133 1099 shell.Run(); // Run the shell 1134 logger.SetNotReady();1100 logger.SetNotReady(); 1135 1101 1136 1102 return 0; … … 1183 1149 1184 1150 // To allow overwriting of DIM_DNS_NODE set 0 to 1 1185 setenv("DIM_DNS_NODE", conf.Get<std::string>("dns").c_str(), 1);1151 // setenv("DIM_DNS_NODE", conf.Get<std::string>("dns").c_str(), 0); 1186 1152 1187 1153 try … … 1191 1157 return RunDim(conf); 1192 1158 1193 // Co sole access w/ and w/o Dim1159 // Console access w/ and w/o Dim 1194 1160 if (conf.Get<int>("console")==0) 1195 1161 return RunShell<LocalShell>(conf);
Note:
See TracChangeset
for help on using the changeset viewer.